Unit Testing, Integration Testing, Priority Testing using TestNG in Java
TestNG is an automated testing framework. In this tutorial, let us explore more about how it can be used in a software lifecycle.
Unit Testing
Instead of testing the whole program, testing the code at the class level, method level, etc., is called Unit Testing The code has to be split into separate classes and methods so that testing can be carried out easily at a unit level.
Integration Testing
After the completion of Unit testing, there will always be the necessity for integration testing. Several units are tested in groups and this will help to reduce the defects exposed at the time of integration of several modules.
Example: We can run tests together by means of specifying “suite name” and can do different classes together.
Priority Testing
By using annotations like @Test(priority=1/2/…), we can set the priority of the tests. If a test class is having @Test annotation alone, it will high priority and if any specific test numbers are given, it is executed as per the order. So we can set the order of execution by using annotations as above. Let us take a maven project and from there will cover important topics.
Example Project
Project Structure:
This is a maven kind of project and hence dependencies need to be mentioned in
pom.xml
XML
<? xml version = "1.0" encoding = "UTF-8" ?>
< modelVersion >4.0.0</ modelVersion >
< groupId >com.gfg.testng</ groupId >
< artifactId >testng</ artifactId >
< version >0.1.0-SNAPSHOT</ version >
< name >testng</ name >
< packaging >jar</ packaging >
< dependencies >
< dependency >
< groupId >org.testng</ groupId >
< artifactId >testng</ artifactId >
< version >${testng.version}</ version >
< scope >test</ scope >
</ dependency >
< dependency >
< groupId >org.slf4j</ groupId >
< artifactId >slf4j-api</ artifactId >
< version >1.7.9</ version >
</ dependency >
</ dependencies >
< build >
< finalName >testng</ finalName >
< resources >
< resource >
< directory >src/main/resources</ directory >
< filtering >true</ filtering >
</ resource >
</ resources >
< testResources >
< testResource >
< directory >src/main/resources</ directory >
< filtering >true</ filtering >
</ testResource >
</ testResources >
</ build >
< profiles >
< profile >
< id >default-second</ id >
< build >
< plugins >
< plugin >
< groupId >org.apache.maven.plugins</ groupId >
< artifactId >maven-surefire-plugin</ artifactId >
< configuration >
< suiteXmlFiles >
< suiteXmlFile >src\test\resources\parametrized_testng.xml</ suiteXmlFile >
</ suiteXmlFiles >
</ configuration >
</ plugin >
</ plugins >
</ build >
</ profile >
< profile >
< id >integration-lite-second</ id >
< build >
< plugins >
< plugin >
< groupId >org.apache.maven.plugins</ groupId >
< artifactId >maven-surefire-plugin</ artifactId >
< configuration >
< suiteXmlFiles >
< suiteXmlFile >src\test\resources\test_int.xml</ suiteXmlFile >
</ suiteXmlFiles >
</ configuration >
</ plugin >
</ plugins >
</ build >
</ profile >
</ profiles >
< properties >
< testng.version >7.1.0</ testng.version >
< project.build.sourceEncoding >UTF-8</ project.build.sourceEncoding >
< maven.compiler.source >1.8</ maven.compiler.source >
< maven.compiler.target >1.8</ maven.compiler.target >
</ properties >
</ project >
|
In TestNG, Via XML files, We can pass parameters as specified in the below XML using <parameter> tag with name and value
XML
< suite name = "My test suite" >
< listeners >
< listener class-name = "com.gfg.reports.CustomisedListener" ></ listener >
</ listeners >
< test name = "numbersXML" >
< parameter name = "value" value = "1" />
< parameter name = "isEven" value = "false" />
< classes >
< class name = "com.gfg.ParametrizedUnitTest" />
</ classes >
</ test >
</ suite >
|
These parameters are collected via @DataProvider or @Parameter in Java files
@DataProvider(name = "numbers")
public static Object[][] evenNumbers() {
return new Object[][]{{11, false}, {2222, true}, {4882, true}};
}
We can run tests together by means of specifying “suite name” and can do different classes together.
XML
< suite name = "int" >
< test name = "integration tests" >
< classes >
< class name = "com.gfg.MultiThreadedIntegrationTest" />
< class name = "com.gfg.TimeOutCheckTest" />
</ classes >
</ test >
</ suite >
|
This specifies that “int” is the suite name and 2 classes namely com.gfg.MultiThreadedIntegrationTest and com.gfg.TimeOutCheckTest together. Like this, we can group classes under a single suite. And also we can specify different suite names and can group classes whichever we need. Dependency tests. i.e. depends upon a specific test and thereupon logging some information
Usecase: Check whether an email is valid or not and if valid, proceed to the next set of steps
private String userEmail = "geek@gfg.com";
@Test
public void checkForValidMail() {
boolean validEmail = userEmail.contains("@");
Assert.assertEquals(validEmail, true);
}
// If first test is success, below test executes and logs the information
@Test(dependsOnMethods = {"checkForValidMail"})
public void logInWhenEmailValid() {
LOGGER.info("Given Email {} valid >> and logging in", userEmail);
}
Order of test execution can be controlled by using @Priority annotation
@Test(priority = 1) // This is executed first
public void stringToIntCheck() {
String testString = "100";
assertTrue(Integer.valueOf(testString) instanceof Integer);
}
@Test(priority = 2) // This is second
public void intToStringCheck() {
int testInt = 100;
assertTrue(String.valueOf(testInt) instanceof String);
}
Test Timeout can be mentioned by using @Test(timeout=<certain value>). TestNG supports for timed out tests.
@Test(timeOut = 1000, enabled = false)
public void asNoStoppingPointItRunsTimeOut() {
while (true) ;
}
- Actually, in the previous test, we are having enabled = false,, that is if we want to ignore the test cases
- We can include
- @BeforeClass and @AfterClass at the class level are mainly used to initialize and clean up the code.
- Similarly, we can include @BeforeMethod and @AfterMethod at the method level
- @BeforeSuite, @AfterSuite, @BeforeGroup, and @AfterGroup annotations, for configurations at suite and group levels respectively.
private int evenNumber, oddNumber;
@BeforeClass
public void setup() {
evenNumber = 100;
oddNumber = 59;
}
@AfterClass
public void tearDown() {
evenNumber = 0;
oddNumber = 0;
}
As a whole let us see the java code with the above features
DependencyUnitTest.java
Java
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.Assert;
import org.testng.annotations.Test;
public class DependencyUnitTest {
private static final Logger LOGGER = LoggerFactory.getLogger(DependencyUnitTest. class );
private String userEmail = "geek@gfg.com" ;
@Test
public void checkForValidMail() {
boolean validEmail = userEmail.contains( "@" );
Assert.assertEquals(validEmail, true );
}
@Test (dependsOnMethods = { "checkForValidMail" })
public void logInWhenEmailValid() {
LOGGER.info( "Given Email {} valid >> and logging in" , userEmail);
}
}
|
MultiThreadedIntegrationTest.java
Java
import org.testng.Assert;
import org.testng.annotations.Test;
public class MultiThreadedIntegrationTest {
@Test (threadPoolSize = 5 , invocationCount = 10 , timeOut = 1000 )
public void checkForCount() {
int count = Thread.activeCount();
Assert.assertTrue(count > 2 );
}
}
|
OddOrEvenNumberCheck.java
Java
import org.testng.Assert;
import org.testng.TestNG;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
public class OddOrEvenNumberCheck extends TestNG {
private int evenNumber, oddNumber;
@BeforeClass
public void setup() {
evenNumber = 100 ;
oddNumber = 59 ;
}
@AfterClass
public void tearDown() {
evenNumber = 0 ;
oddNumber = 0 ;
}
@Test
public void checkEven() {
Assert.assertTrue(evenNumber % 2 == 0 );
}
@Test
public void checkOdd() {
Assert.assertTrue(oddNumber % 2 == 1 );
}
}
|
ParametrizedUnitTest.java
Java
import org.testng.annotations.DataProvider;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;
import static org.testng.Assert.assertEquals;
public class ParametrizedUnitTest {
@DataProvider (name = "numbers" )
public static Object[][] evenNumbers() {
return new Object[][]{{ 11 , false }, { 2222 , true }, { 4882 , true }};
}
@Test (dataProvider = "numbers" )
public void evenNumberCheck(Integer number, boolean expected) {
assertEquals(expected, number % 2 == 0 );
}
@Test (dataProvider = "numbersObject" )
public void evenNumberObjectCheck(EvenNumberPOJO number) {
assertEquals(number.isEven(), number.getValue() % 2 == 0 );
}
@DataProvider (name = "numbersObject" )
public Object[][] parameterProvider() {
return new Object[][]{{ new EvenNumberPOJO( 111 , false )}, { new EvenNumberPOJO( 2432 , true )}, { new EvenNumberPOJO( 4712 , true ),}};
}
class EvenNumberPOJO {
private int value;
private boolean isEven;
EvenNumberPOJO( int number, boolean isEven) {
this .value = number;
this .isEven = isEven;
}
int getValue() {
return value;
}
public void setValue( int value) {
this .value = value;
}
boolean isEven() {
return isEven;
}
public void setEven( boolean even) {
isEven = even;
}
@Override
public String toString() {
return "EvenNumber{" +
"value=" + value +
", isEven=" + isEven +
'}' ;
}
}
}
|
PriorityUnitTest.java
Java
import org.testng.annotations.Test;
import static org.testng.Assert.assertTrue;
public class PriorityUnitTest {
@Test (priority = 1 )
public void stringToIntCheck() {
String testString = "100" ;
assertTrue(Integer.valueOf(testString) instanceof Integer);
}
@Test (priority = 2 )
public void intToStringCheck() {
int testInt = 100 ;
assertTrue(String.valueOf(testInt) instanceof String);
}
}
|
TimeOutCheckTest.java
Java
import org.testng.annotations.Test;
public class TimeOutCheckTest {
@Test (timeOut = 1000 , enabled = false )
public void asNoStoppingPointItRunsTimeOut() {
while ( true ) ;
}
}
|
Now let’s run the test by using
mvn test
Or from eclipse
Output:
We can see the success/failure reports under the target/surefire-reports folder as well.
Last Updated :
15 Nov, 2022
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...