Article directory
Introduction
Official website : https://testng.org/doc/index.html
TestNG is a Java-based open source testing framework. The framework is inspired by JUnit and NUnit, but introduces some new features to make it more powerful and easier to use. You can create HTML reports during test implementation. It has features like grouping tests, annotations, parameterization, etc. which help to create tests faster.
Core Features of TestNG
-
Run tests in a thread pool of any size, with various strategies available (all methods in their own thread, one thread per test class, etc.).
-
Test that your code is thread safe.
-
Flexible test configuration.
-
Support for data-driven testing (use
@DataProvider
). -
Support parameters.
-
Powerful execution model (not anymore
TestSuite
). -
Supported by multiple tools and plugins (Eclipse, IDEA, Maven, etc.).
-
Embeds BeanShell for flexibility.
-
Default JDK functions for runtime and logging (no dependencies).
-
Related methods for application server testing.
-
Unit testing, functional testing, end-to-end testing, integration testing, etc. can be done.
simple example
1. Add dependencies
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>7.1.0</version>
<scope>test</scope>
</dependency>
TestNG up to v7.5: JDK 8 or later.
TestNG v7.6.0 and later: JDK 11 or later.
2. Simple test example
import org.testng.annotations.*;
public class SimpleTest {
@BeforeClass
public void setUp() {
// 实例化此测试时将调用的代码
}
@Test(groups = {
"fast" })
public void aFastTest() {
System.out.println("Fast test");
}
@Test(groups = {
"slow" })
public void aSlowTest() {
System.out.println("Slow test");
}
}
- A test method can belong to one or more groups.
Execute tests and view test reports
Method 1 Run the testng.xml file in IDEA
Here is a testNG.xml file
<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd" >
<suite name="Suite1" verbose="1">
<!-- 指定包名-->
<test name="Regression1">
<packages>
<package name="test.sample"/>
</packages>
</test>
<!-- 指定类名称 -->
<test name="Regression2">
<classes>
<class name="test.sample.ParameterSample"/>
<class name="test.sample.ParameterTest"/>
</classes>
</test>
<!-- 指定要包含和排除的组和方法 -->
<test name="Regression3">
<groups>
<run>
<exclude name="brokenTests"/>
<include name="checkinTests"/>
</run>
</groups>
<classes>
<class name="test.IndividualMethodsTest">
<methods>
<include name="testMethod"/>
</methods>
</class>
</classes>
</test>
<!-- 在属性中指定其他详细信息,例如是否并行运行测试、使用多少个线程、是否正在运行 JUnit 测试等 -->
<test name="Regression4" preserve-order="false" parallel="methods" thread-count="5">
<classes>
<class name="test.Test1">
<methods>
<include name="m1"/>
<include name="m2"/>
</methods>
</class>
<class name="test.Test2"/>
</classes>
</test>
</suite>
Right click on the testNG.xml file to run it.
Method 2: Run the test class or package in IDEA
Right-click on the test class or test package to run it.
Way 3 Run tests in Maven
In the Maven project, Maven Surefire Plugin
plug-ins are used to execute unit tests, so plug-ins need to be added to the pom.xml file Maven Surefire Plugin
, and the test files to be executed can be configured in the configuration.
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<!--<version>3.0.0-M5</version>-->
<version>${maven-surefire-plugin.version}</version>
<configuration>
<trimStackTrace>true</trimStackTrace>
<includes>
<include>**/*Test.java</include>
<include>**/*Tests.java</include>
</includes>
<excludes>
<exclude>**/integration/**</exclude>
</excludes>
<parallel>classes</parallel>
<threadCountMethods>2</threadCountMethods>
<useSystemClassLoader>false</useSystemClassLoader>
<forkCount>1</forkCount>
<reuseForks>true</reuseForks>
<argLine>-Xmx1024m -XX:MaxPermSize=256m</argLine>
<rerunFailingTestsCount>3</rerunFailingTestsCount>
<testFailureIgnore>true</testFailureIgnore>
<reportFormat>plain</reportFormat>
<reportsDirectory>${project.build.directory}/surefire-reports</reportsDirectory>
</configuration>
</plugin>
</plugins>
</build>
After execution, the surefire report will be stored in the target/surefire-reports folder by default.
<trimStackTrace>
Set totrue
to crop stack trace information to make it more readable.<parallel>
Set toclasses
, to allow parallel execution of test classes, improving execution speed.<threadCountMethods>
Set to an appropriate number of threads for parallel execution of test methods.<useSystemClassLoader>
Set tofalse
, to avoid using the system classloader, reducing possible conflicts.<forkCount>
Set to1
to avoid using multiple processes to execute tests.<reuseForks>
Set totrue
, to reuse the test process and improve execution efficiency.<argLine>
Additional JVM parameters can be specified, such as heap memory size, permanent generation size, etc.<rerunFailingTestsCount>
Set to an appropriate value to rerun tests if they fail.<testFailureIgnore>
Set totrue
to ignore test failures and continue the build process.<reportsDirectory>
Specifies the output directory for test reports.
Maven also has some common commands of its own, and we can execute test codes through Maven commands.
编译:mvn compile --src/main/java目录java源码编译生成class (target目录下)
测试:mvn test --src/test/java 目录编译
清理:mvn clean --删除target目录,也就是将class文件等删除
打包:mvn package --生成压缩文件:java项目#jar包;web项目#war包,也是放在target目录下
安装:mvn install --将压缩文件(jar或者war)上传到本地仓库
部署:mvn deploy --将压缩文件上传私服
We can
mvn clean test
execute the test case by calling the plug-in in pom.xmlMaven Surefire Plugin
-> run the configured test case.skip test
mvn clean package/install -DskipTests
mvn clean package/install -Dmaven.test.skip=true
Statistical Test Coverage
The higher the test code coverage, the higher the code quality
Method 1 IDEA supports detailed code test coverage statistics
It's very simple not to introduce
Method 2: Maven supports test coverage
JaCoCo is an open source coverage tool. Its development language is java. Its usage method is very flexible and can be embedded in Ant and Maven. Many third-party tools provide JaCoCo integration, such as sonar and Jenkins.
JaCoCo includes coverage counters of various scales, including instruction-level coverage (Instructions, C0coverage), branches (Branches, C1coverage), cyclomatic complexity (CyclomaticComplexity), line coverage (Lines), method coverage (non-abstract methods), Class coverage (classes)
pom.xml add
<!-- jacoco: generate test coverage report -->
<jacoco.version>0.8.8</jacoco.version>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>${jacoco.version}</version>
<configuration>
<includes>
<include>com/**/*</include>
<include>**/*Test.java</include>
</includes>
<excludes>
<exclude>**/AccountImageUtilTest.java</exclude>
</excludes>
<skip>false</skip>
</configuration>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>generate-code-coverage-report</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
Execute in the root directory of the project mvn clean test
to execute the unit test and generate a coverage report. After the report is generated ./target/site/jacoco/index.html
, open the file through a browser, and you can see the overall coverage and unit test status.
Create test cases in IDEA
Use IDEA to quickly create unit tests to improve development and testing efficiency
Use on the name of the class or interface (recommended to create based on the interface) that needs to be tested Alt+Enter
, and then select Create Test .
Common Notes
annotation | note |
---|---|
@BeforeSuite | The annotated method will be run before the entire test suite |
@AfterSuite | The annotated method will be run after the entire test suite |
@BeforeTest | The annotated method will be run before all test cases in the test suite are executed |
@AfterTest | The annotated method will be run after all test cases in the test suite are executed |
@BeforeGroups | The annotated method will be run before any use cases in the specified group are executed |
@AfterGroups | The annotated method will run after any use case in the specified group is executed |
@BeforeClass | Annotated methods will run before calling the first test method in the current class . |
@AfterClass | Annotated methods will run after all test methods in the current class have run . |
@BeforeMethod | Annotated methods will be run before every test method . |
@AfterMethod | Annotated methods will be run after each test method . |
@DataProvider | The annotated method is forced to return a two-dimensional array Object[ ][ ] as a data factory for another @Test method |
@Factory | The annotated method, as an object factory, is forced to return an object array Object[] |
@Listeners | Define a listener for the test class |
@Parameters | Define a set of parameters, pass the value of the parameter to the method during the running of the method, and the value of the parameter is defined in testng.xml |
@Test | The marked method is a test method. If the mark is a class, all public methods in this class are test methods |
The specific life cycle is as follows :
Common scene
ignore test
Sometimes, you may need to temporarily ignore certain test methods to avoid executing them. You can use @Test(enabled = false)
annotations to mark test methods that need to be ignored.
import org.testng.annotations.Test;
public class IgnoreTest {
@Test
public void testMethod1() {
// 测试方法1的代码
}
@Test(enabled = false)
public void testMethod2() {
// 测试方法2的代码
}
}
testMethod2
is marked as enabled = false
, indicating that the test method will be ignored and will not be executed. Only test methods marked with enabled = true
or without enabled
the attribute will be executed.
parametric test
With parameterized testing, you can run the same test method with different input values to verify how your code behaves under different parameters.
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import static org.testng.Assert.*;
public class ParameterizedTest {
@DataProvider(name = "additionData")
public Object[][] additionData() {
return new Object[][] {
{
2, 3, 5},
{
5, 5, 10},
{
-10, 10, 0}
};
}
@Test(dataProvider = "additionData")
public void testAddition(int a, int b, int expected) {
int result = Calculator.add(a, b);
assertEquals(result, expected);
}
}
test group
With Test Groups, you can categorize test methods and selectively run specific groups of tests.
import org.testng.annotations.Test;
import static org.testng.Assert.*;
public class GroupTest {
@Test(groups = "smoke")
public void testLogin() {
// 测试登录功能
assertTrue(true);
}
@Test(groups = "regression")
public void testHomePage() {
// 测试首页功能
assertTrue(true);
}
@Test(groups = "regression")
public void testProfilePage() {
// 测试个人资料页面功能
assertTrue(true);
}
}
exception test
Verify that the code correctly throws the expected exceptions in the test.
import org.testng.annotations.Test;
public class ExceptionTest {
@Test(expectedExceptions = ArithmeticException.class)
public void testDivideByZero() {
int result = Calculator.divide(10, 0);
}
}
The expected exception type is specified using @Test
the annotation's attribute. expectedExceptions
If the code executed in the test method does throw the specified exception, the test will be marked as passed.
timeout test
Set the maximum execution time of the test method to ensure that the code completes execution within the specified time frame.
import org.testng.annotations.Test;
public class TimeoutTest {
@Test(timeOut = 500)
public void testLongRunningOperation() throws InterruptedException {
// 模拟一个长时间运行的操作
Thread.sleep(1000);
}
}
The maximum execution time in milliseconds is specified using the @Test
annotated attribute. timeOut
If the execution time of the test method exceeds the specified time, the test will be marked as failed.
multithreaded test
Using TestNG, you can execute test methods concurrently in multiple threads to simulate concurrency and parallel scenarios. This can be achieved by @Test
setting the threadPoolSize
and invocationCount
attributes in the annotation.
import org.testng.annotations.Test;
public class MultiThreadTest {
@Test(threadPoolSize = 5, invocationCount = 10)
public void testMethod() {
// 在多个线程中并发执行的测试方法
}
}
testMethod
Using threadPoolSize = 5
and invocationCount = 10
means that the test method will be executed concurrently in a thread pool with 5 threads, for a total of 10 executions. This allows you to simulate concurrent scenarios and observe how your test methods behave in a multi-threaded environment.
Note: When writing multi-threaded tests, make sure the test methods are thread-safe, and handle synchronization between threads and access to shared resources.
rerun failed tests
When executing tests in a maven environment, TestNG will create a file named in the output directory every time a test fails testng-failed.xml
. This XML file contains the information needed to rerun only those failed methods, enabling you to quickly reproduce failures without running the entire test.
\target\surefire-reports\testng-failed.xml
Affirmation
In TestNG, commonly used assertion methods are located org.testng.Assert
in the class, which provides a series of assertion methods for verifying test results. The following are code examples of some commonly used assertion methods and their best practices:
Verify that two values are equal
assertEquals
: Validates that two values are equal.
import org.testng.Assert;
import org.testng.annotations.Test;
public class AssertionTest {
@Test
public void testAddition() {
int result = Calculator.add(2, 3);
Assert.assertEquals(result, 5, "Addition result is incorrect.");
}
}
In the example above, assertEquals
the method is used to verify result
that the value of is equal to 5. If the assertion fails, an AssertionError is thrown with the specified error message.
Verify if a condition is true or false
assertTrue
AND assertFalse
: Validates whether a condition is true or false.
import org.testng.Assert;
import org.testng.annotations.Test;
public class AssertionTest {
@Test
public void testIsEvenNumber() {
int number = 10;
Assert.assertTrue(number % 2 == 0, "Number is not even.");
}
}
In the example above, assertTrue
the method is used to verify number
that is even. If the condition is not met, the assertion fails with an error message.
Validates whether a value is null or not null
assertNull
AND assertNotNull
: Validates whether the value is null or not null.
import org.testng.Assert;
import org.testng.annotations.Test;
public class AssertionTest {
@Test
public void testArray() {
String[] names = {
"John", "Jane", "Doe"};
Assert.assertNotNull(names, "Array is null.");
}
}
In the above example, assertNotNull
the method is used to verify names
that the array is not null. If the array is null, the assertion fails with an error message.
Verify that the expected exception was thrown
assertThrows
: Verify that the expected exception was thrown.
import org.testng.Assert;
import org.testng.annotations.Test;
public class AssertionTest {
@Test
public void testDivideByZero() {
Assert.assertThrows(ArithmeticException.class, () -> Calculator.divide(10, 0));
}
}
In the above example, assertThrows
the method is used to verify Calculator.divide(10, 0)
that the exception was thrown ArithmeticException
. If the expected exception is not thrown, the assertion fails.