Testng Parameters Before Class Assignments

Let’s learn about the annotation provided by TestNG. allows tests to be created at runtime depending on certain data-sets or conditions.

Sometimes we may need to run a set of tests with different data values. To achieve this we may define a separate set of tests inside a suite in the testng XML and test the required scenario. The problem with this approach is that, if you get an extra set of data, you will need to redefine the test. TestNG solves this problem by providing the annotation feature. Factory in TestNG defines and creates tests dynamically at runtime.

In this tutorial, we’ll learn about annotation using following examples.

Table of ContentsBasic Factory ExamplePassing parameters to test classesUsing @DataProvider along with the @Factory annotationDependent tests with the @Factory annotation

Basic Factory Example

Let’s create a sample program using the @Factory annotation of TestNG.

public class SimpleTest { @Test public void simpleTest() { System.out.println("Simple Test Method."); } } public class SimpleTestFactory { @Factory public Object[] factoryMethod() { return new Object[] { new SimpleTest(), new SimpleTest() }; } }

The preceding class defines a factory method inside it. A factory method is defined by declaring above the respective test method. It’s mandatory that a factory method should return an array of class ().

Let’s run the factory now.

Simple Test Method. Simple Test Method. PASSED: simpleTest PASSED: simpleTest

As you can see in the preceding test results, the test method from the class was executed two times. The execution is based on the array returned by the factory method. As the said method returns two objects of the class, TestNG looks inside the specified returned object and executes all the test methods inside it. In this case, as there was only one test method, TestNG executes the respective test method.

Passing parameters to test classes

One of the main advantage of using the factory methods is that you can pass parameters to test classes while initializing them. These parameters can then be used across all the test methods present in the said classes.

public class SimpleTest { private int param; public SimpleTest(int param) { this.param = param; } @Test public void testMethodOne() { int opValue = param + 1; System.out.println("Test method one output: " + opValue); } @Test public void testMethodTwo() { int opValue = param + 2; System.out.println("Test method two output: " + opValue); } } public class SimpleTestFactory { @Factory public Object[] factoryMethod() { return new Object[] { new SimpleTest(0), new SimpleTest(1) }; } }

The constructor of the previous test class takes one argument as an integer, which is assigned to a local variable param. This variable then is used in the two test methods present in the test class. Each of the test methods adds a value to param and prints it to the console on execution.

Let’s run the test now.

Test method one output: 2 Test method one output: 1 Test method two output: 3 Test method two output: 2 PASSED: testMethodOne PASSED: testMethodOne PASSED: testMethodTwo PASSED: testMethodTwo

As you can see from the preceding test results, each of the test methods are executed two times each. The parameters passed while initializing the test class are used by the test methods and the console shows the respective output.

Using @DataProvider along with the @Factory annotation

The feature can also be used with the annotation for creating tests at runtime. This can be done by declaring the annotation on a constructor of a class or on a regular method.

public class DataProviderTest { private int param; @Factory(dataProvider = "dataMethod") public DataProviderTest(int param) { this.param = param; } @DataProvider public static Object[][] dataMethod() { return new Object[][] { { 0 }, { 1 } }; } @Test public void testMethodOne() { int opValue = param + 1; System.out.println("Test method one output: " + opValue); } @Test public void testMethodTwo() { int opValue = param + 2; System.out.println("Test method two output: " + opValue); } }

The preceding class is similar to the test class, which we used earlier. The constructor of the test class is annotated with the annotation. This annotation uses a DataProvider method named dataMethod for providing values to the constructor of the test class. The DataProvider method returns a double object array in which the first array represents the dataset, which decides the number of times the test will be iterated, whereas the second array is the actual parameter value that will be passed to the test method per iteration. The said double object array contains two datasets with values 0 and 1.

Let’s run the test now.

Test method one output: 2 Test method one output: 1 Test method two output: 3 Test method two output: 2 PASSED: testMethodOne PASSED: testMethodOne PASSED: testMethodTwo PASSED: testMethodTwo

Dependent tests with the @Factory annotation

We have seen different examples of factory implementation so far. Let’s see how a dependency method is executed when used with the factory class.

public class DependencyTest { private int param; public DependencyTest(int param) { this.param = param; } @Test(dependsOnMethods = { "testMethodTwo" }) public void testMethodOne() { System.out.println("Test method one with param values: " + this.param); } @Test public void testMethodTwo() { System.out.println("Test method two with param values: " + this.param); } } public class SimpleTestFactory { @Factory public Object[] factoryMethod() { return new Object[] { new DependencyTest(1), new DependencyTest(2) }; } }

This class contains two test methods and , where depends on . The constructor of the class takes one argument as integer, and sets its value to an internal variable named param. Both of the test methods print their method name along with the param variable value to console when executed.

Let’s run the tests now.

Test method two with param values: 2 Test method two with param values: 1 Test method one with param values: 2 Test method one with param values: 1 PASSED: testMethodTwo PASSED: testMethodTwo PASSED: testMethodOne PASSED: testMethodOne

As you can see from the previous test results both the instances of were executed before any instance of . This is the default behavior of a factory implementation in TestNG, it will execute all the instances of the dependent test methods before the actual test method.

That’s all related to annotation in TestNG. Let me know if you have any queries.

Happy Learning !!

Parallelism or multi-threading in software terms is defined as the ability of the software, operating system, or program to execute multiple parts or sub-components of another program simultaneously. TestNG allows the tests to run in parallel or multi-threaded mode. This means that based on the test suite configuration, different threads are started simultaneously and the test methods are executed in them. This gives a user a lot of advantages over normal execution, mainly reduction in execution time and ability to verify a multi-threaded code.

Table Of ContentsAdvantages of Parallel Tests ExecutionRunning test methods in parallelRunning test classes in parallelRunning tests inside a suite in parallelConfiguring a test method to run in multiple threads

Advantages of Parallel Tests Execution

Parallelism or multi-threaded execution can provide a lot of advantages to the users. The following are two:

1) Reduces execution time: As tests are executed in parallel, multiple tests get executed simultaneously, hence reducing the overall time taken to execute the tests.

2) Allows multi-threaded tests: Using this feature, we can write tests to verify certain multi-threaded code in the applications

This feature is vastly used by the QA industry for functional automation testing. This feature helps QA guys configure their tests to be executed easily in multiple browsers or operating systems simultaneously.

There are different ways in which parallelism feature can be configured in TestNG.

Running test methods in parallel

TestNG provides multiple ways to execute the tests in a multi-threaded condition, one of them is executing each test method in a single thread. This mode reduces the execution time significantly because more tests are executed in parallel, hence reducing the total execution time.

package com.howtodoinjava.parallelism; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; public class ParallelMethodTest { @BeforeMethod public void beforeMethod() { long id = Thread.currentThread().getId(); System.out.println("Before test-method. Thread id is: " + id); } @Test public void testMethodsOne() { long id = Thread.currentThread().getId(); System.out.println("Simple test-method One. Thread id is: " + id); } @Test public void testMethodsTwo() { long id = Thread.currentThread().getId(); System.out.println("Simple test-method Two. Thread id is: " + id); } @AfterMethod public void afterMethod() { long id = Thread.currentThread().getId(); System.out.println("After test-method. Thread id is: " + id); } }

The preceding test class contains two test methods, which prints a message onto the console when executed. The ID of the thread on which the current method is being executed is evaluated using the code. It also contains the and methods, which also prints the thread ID of the current thread onto the console when executed.

Create a new file named under the project and write below code.

<suite name="Test-method Suite" parallel="methods" thread-count="2" > <test name="Test-method test" group-by-instances="true"> <classes> <class name="com.howtodoinjava.parallelism.ParallelMethodTest" /> </classes> </test> </suite>

Select this file in Eclipse and run it as a TestNG suite. You will see the following test result in the Console window:

Before test-method. Thread id is: 10 Before test-method. Thread id is: 9 Simple test-method Two. Thread id is: 10 Simple test-method One. Thread id is: 9 After test-method. Thread id is: 10 After test-method. Thread id is: 9
Note that the Id value shown in the previous screenshot may not be the same in your console output. The Id value is assigned at runtime by the Java virtual machine (JVM) during execution.

The previous test result clearly shows that each test method and its respective and method is executed in a different thread. This is identified by the ID of the thread that is printed on the console.

Running test classes in parallel

In this example, we will learn about ; each test class that is part of the test execution will be executed in its own thread.

ParallelClassesTestOne.java

public class ParallelClassesTestOne { @BeforeClass public void beforeClass() { long id = Thread.currentThread().getId(); System.out.println("Before test-class. Thread id is: " + id); } @Test public void testMethodOne() { long id = Thread.currentThread().getId(); System.out.println("Sample test-method One. Thread id is: " + id); } @Test public void testMethodTwo() { long id = Thread.currentThread().getId(); System.out.println("Sample test-method Two. Thread id is: " + id); } @AfterClass public void afterClass() { long id = Thread.currentThread().getId(); System.out.println("After test-class. Thread id is: " + id); } }

ParallelClassesTestTwo.java

public class ParallelClassesTestTwo { @BeforeClass public void beforeClass() { long id = Thread.currentThread().getId(); System.out.println("Before test-class. Thread id is: " + id); } @Test public void testMethodOne() { long id = Thread.currentThread().getId(); System.out.println("Sample test-method One. Thread id is: " + id); } @Test public void testMethodTwo() { long id = Thread.currentThread().getId(); System.out.println("Sample test-method Two. Thread id is: " + id); } @AfterClass public void afterClass() { long id = Thread.currentThread().getId(); System.out.println("After test-class. Thread id is: " + id); } }

Create a new file named under the project and write below code.

<suite name="Test-class Suite" parallel="classes" thread-count="2" > <test name="Test-class test" > <classes> <class name="com.howtodoinjava.parallelism.ParallelClassesTestOne" /> <class name="com.howtodoinjava.parallelism.ParallelClassesTestTwo" /> </classes> </test> </suite>

Select this file in Eclipse and run it as a TestNG suite. You will see the following test result in the Console window:

Before test-class. Thread id is: 10 Before test-class. Thread id is: 9 Sample test-method One. Thread id is: 9 Sample test-method One. Thread id is: 10 Sample test-method Two. Thread id is: 10 After test-class. Thread id is: 10 Sample test-method Two. Thread id is: 9 After test-class. Thread id is: 9

The previous test result clearly shows that each test class and its respective and methods are executed in a different thread. This is identified by the id of the thread that is printed on the console.

Running tests inside a suite in parallel

Let’s learn about executing each test inside a suite in parallel, that is, each test that is part of the test suite execution will be executed in its own separate respective thread.

package com.howtodoinjava.parallelism; import org.testng.annotations.AfterClass; import org.testng.annotations.AfterTest; import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeTest; import org.testng.annotations.Parameters; import org.testng.annotations.Test; public class ParallelSuiteTest { String testName = ""; @BeforeTest @Parameters({ "test-name" }) public void beforeTest(String testName) { this.testName = testName; long id = Thread.currentThread().getId(); System.out.println("Before test " + testName + ". Thread id is: " + id); } @BeforeClass public void beforeClass() { long id = Thread.currentThread().getId(); System.out.println("Before test-class " + testName + ". Thread id is: " + id); } @Test public void testMethodOne() { long id = Thread.currentThread().getId(); System.out.println("Sample test-method " + testName + ". Thread id is: " + id); } @AfterClass public void afterClass() { long id = Thread.currentThread().getId(); System.out.println("After test-method " + testName + ". Thread id is: " + id); } @AfterTest public void afterTest() { long id = Thread.currentThread().getId(); System.out.println("After test " + testName + ". Thread id is: " + id); } }

Create a new file named under the project and write below code.

<suite name="Test-class Suite" parallel="tests" thread-count="2"> <test name="Test-class test 1"> <parameter name="test-name" value="test-method One" /> <classes> <class name="com.howtodoinjava.parallelism.ParallelSuiteTest" /> </classes> </test> <test name="Test-class test 2"> <parameter name="test-name" value="test-method One" /> <classes> <class name="com.howtodoinjava.parallelism.ParallelSuiteTest" /> </classes> </test> </suite>

Select this file in Eclipse and run it as a TestNG suite. You will see the following test result in the Console window:

Before test Test One. Thread id is: 9 Before test Test Two. Thread id is: 10 Before test-class Test One. Thread id is: 9 Before test-class Test Two. Thread id is: 10 Sample test-method Test One. Thread id is: 9 Sample test-method Test Two. Thread id is: 10 After test-method Test Two. Thread id is: 10 After test-method Test One. Thread id is: 9 After test Test One. Thread id is: 9 After test Test Two. Thread id is: 10

The previous test result clearly shows that each test in a suite is executed in its respective thread. This is identified by the ID of the thread that is printed on the console.

Configuring a test method to run in multiple threads

Earlier we discussed how to run classes, methods, and tests in parallel or in multi-threaded mode. TestNG also provides the flexibility to configure a test method to be run in a multi-threaded environment. This is achieved by configuring it while using the annotation on a method.

public class IndependentTest { @Test(threadPoolSize = 3, invocationCount = 6, timeOut = 1000) public void testMethod() { Long id = Thread.currentThread().getId(); System.out.println("Test method executing on thread with id: " + id); } }

The method is configured to run in multi-threaded mode by using the threadPoolSize attribute along with the Test annotation. The value of the threadPoolSize is set to 3; this configures the test method to be run in three different threads. The other two attributes, invocationCount and timeOut, configures the test to be invoked a multiple number of times and fail if the execution takes more time.

Create a new file named under the project and write below code.

<suite name="Independent test Suite" > <test name="Independent test"> <classes> <class name="com.howtodoinjava.parallelism.IndependentTest" /> </classes> </test> </suite>

Select this file in Eclipse and run it as a TestNG suite. You will see the following test result in the Console window:

Test method executing on thread with id: 11 Test method executing on thread with id: 10 Test method executing on thread with id: 9 Test method executing on thread with id: 11 Test method executing on thread with id: 11 Test method executing on thread with id: 10

Here, test method is executed multiple times based on the invocationCount attribute value. Each execution is done in a separate thread that is clearly visible from the test report output. This feature is useful when you want to run only a fixed number of test methods in multi-threaded mode and not the whole test suite.

Happy Learning !!

0 Replies to “Testng Parameters Before Class Assignments”

Lascia un Commento

L'indirizzo email non verrĂ  pubblicato. I campi obbligatori sono contrassegnati *