TestNG is a testing framework inspired by JUnit but introducing a whole set of new functionalities. In this tutorial we will walk through the set up and execution of some example tests with TestNG.
What is TestNG?
TestNG is an open source automated testing framework. It has been designed to reduce some of the limitations of JUnit to make it more flexible and powerful. The highlights of TestNG are:
- TestNG supports a wide range of annotations.
- TestNG uses more Java and OO features.
- TestNG supports testing integrated classes (i.e. by default, no need to create a new test class instance for every test method).
- TestNG has a clean separation from compile-time test code and run-time configuration/data info.
- TestNG supports a flexible runtime configuration.
- TestNG introduces the concept of ‘test groups’. Once you have compiled your tests, you can just ask TestNG to run all the “front-end” tests, or “fast”, “slow”, “database” tests, etc.
- TestNG supports Dependent test methods, parallel testing, load testing, and partial failure.
- TestNG has a flexible plug-in API.
- TestNG has support for multi threaded testing.
Setting up Test NG
Let’s write a proof of concept Hello World example with TestNG.
Firstly, we will add to our pom.xml the latest version of Test NG which as of October 2024 it’s the version 7.10.2:
<dependency> <groupId>org.testng</groupId> <artifactId>testng</artifactId> <version>7.10.2</version> <scope>test</scope> </dependency>
On the other hand, if you are using Gradle, you will need the following basic configuration in your build.gradle file:
test { //this is the gradle task to be executed useTestNG() { //Tells Gradle to use TestNG useDefaultListeners = true // Tells TestNG to execute its default reporting structure suites 'src/test/suite.xml' //location of our suite.xml } }
Running TestNG on Eclipse
You can run your Test classes from the Command Line or from your IDE. For example, to run TestNG suites from Eclipse you can install its plug-in which is available in the Eclipse Marketplace:
Choose Install and restart Eclipse.
Coding your first TestNG Class
Here is your example App.java file:
public class App { public int sum(int a, int b) { return a + b; } }
Now let’s test it with TestNG:
import org.testng.Assert; import org.testng.annotations.Test; public class AppTest { @Test public void helloworld() { App a = new App(); Assert.assertEquals(10, a.sum(5,5)); } }
if you have installed Eclipse TestNG plugin, you can simply run the Test by right-clicking on the Class and choosing Run As | TestNG Test. Otherwise, from the command line, run the Maven test goal:
$ mvn test
Next, check the output:
PASSED: helloworld =============================================== Default test Tests run: 1, Failures: 0, Skips: 0 ================================================
TestNG annotations order
Much alike JUnit, you can capture Test lifecycle steps using annotations. the Following Test class shows how to intercept the various phases of a TestNG Class:
import org.testng.annotations.Test; import org.testng.annotations.BeforeMethod; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeClass; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeTest; import org.testng.annotations.AfterTest; import org.testng.annotations.BeforeSuite; import org.testng.annotations.AfterSuite; public class SampleTestNGClass { @Test public void hello() { System.out.println("@Test annotation"); } @BeforeMethod public void beforeMethod() { System.out.println("@BeforeMethod annotation"); } @AfterMethod public void afterMethod() { System.out.println("@AfterMethod annotation"); } @BeforeClass public void beforeClass() { System.out.println("@BeforeClass annotation"); } @AfterClass public void afterClass() { System.out.println("@AfterClass annotation"); } @BeforeTest public void beforeTest() { System.out.println("@BeforeTest annotation"); } @AfterTest public void afterTest() { System.out.println("@AfterTest annotation"); } @BeforeSuite public void beforeSuite() { System.out.println("@BeforeSuite annotation"); } @AfterSuite public void afterSuite() { System.out.println("@AfterSuite annotation"); } }
And here is the execution order for all the above methods:
- BeforeSuite and AfterSuite methods are executed only once.
- BeforeTest and AfterTest methods are executed only once per test class.
- BeforeClass and AfterClass methods are executed only once per class.
- BeforeMethod and AfterMethod methods are executed for all @Test methods.
- If the TestNG class contains more than one methods marked with @BeforeMethod and @AfterMethod, then all the methods are executed before and after every @Test method.
A common question is about the difference between BeforeTest and BeforeMethod. We can summarize it as follows:
- @BeforeTest : It will call only once, before Test method.
- @BeforeMethod It will call every time before Test Method.
When should you use BeforeSuite?
@BeforeSuite is typically used when we have different environment vars to run your test cases. You can set them in a @BeforeSuite annotated method so that before executing all the test cases, you need to load all the environment variables for your framework, and then it starts executing your test cases.
Running the same Test with multiple parameters
One of the most interesting features of TestNG is the ability to run multiple times the same test using a different set of parameters. You can achieve that by defining a method as @DataProvider and having it to return a set of parameters.
See the following example:
import org.testng.Assert; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; public class DataProviderTest { @Test(dataProvider = "provideNumbers") public void test(int number, int expected) { Assert.assertEquals(number + 10, expected); } @DataProvider(name = "provideNumbers") public Object[][] provideData() { return new Object[][] { { 10, 20 }, { 100, 110 }, { 200, 210 }, { 300, 310 }, { 400, 210 } }; } }
The above example runs 5 executions of the same test method, each one with a different couple of parameters.