TestNG 是一个测试框架,用于自动化测试 Java 和 Scala 应用程序,它是 JUnit 和 NUnit 的一个强大替代品。TestNG 支持数据驱动测试、参数化测试、测试套件、依赖管理、多线程测试等特性。TestNG官网:TestNG Documentation
目录
1.TestNG 基本注解
注解 | 描述 |
---|---|
@Test | 标记一个方法为测试方法。 |
@BeforeSuite | 在测试套件中的所有测试运行之前运行。 |
@AfterSuite | 在测试套件中的所有测试运行之后运行。 |
@BeforeTest | 在当前测试类中的所有测试运行之前运行。 |
@AfterTest | 在当前测试类中的所有测试运行之后运行。 |
@BeforeClass | 在当前类中的所有测试运行之前运行,仅运行一次。 |
@AfterClass | 在当前类中的所有测试运行之后运行,仅运行一次。 |
@BeforeMethod | 在每个测试方法运行之前运行。 |
@AfterMethod | 在每个测试方法运行之后运行。 |
@Parameters | 指定一个属性文件,TestNG 会从该文件中读取参数。 |
@DataProvider | 为测试方法提供参数。 |
@Listeners | 指定监听器类,监听器可以处理测试的执行和报告。 |
代码示例:
import org.testng.annotations.*;
public class BasicAnnotationsTest {
@BeforeSuite
public void beforeSuite() {
System.out.println("Before Suite");
}
@AfterSuite
public void afterSuite() {
System.out.println("After Suite");
}
@Test
public void testMethod1() {
System.out.println("Test Method 1");
}
@Test(dependsOnMethods = "testMethod1")
public void testMethod2() {
System.out.println("Test Method 2");
}
@BeforeMethod
public void beforeMethod() {
System.out.println("Before Method");
}
@AfterMethod
public void afterMethod() {
System.out.println("After Method");
}
}
在这个示例中,我们展示了如何使用 TestNG 的基本注解来组织测试方法的执行顺序和执行时机。
2.TestNG 测试分组
注解 | 描述 |
---|---|
@Test | 标记一个方法为测试方法,可以指定分组。 |
groups | 指定当前测试方法属于哪个测试分组。 |
@Groups | 定义一组测试分组,可以被 @Test 注解引用。 |
代码示例:
import org.testng.annotations.Test;
import org.testng.annotations.Groups;
@Groups({ "unitTests", "smokeTests" })
public class GroupTest {
@Test(groups = "unitTests")
public void unitTestMethod() {
System.out.println("Running unit test method");
}
@Test(groups = "integrationTests")
public void integrationTestMethod() {
System.out.println("Running integration test method");
}
@Test(groups = "smokeTests")
public void smokeTestMethod() {
System.out.println("Running smoke test method");
}
}
public class TestRunner {
public static void main(String[] args) {
org.testng.TestNG.main(new String[] {
"-groups", "unitTests", "-class", "GroupTest"
});
}
}
在这个示例中,我们使用了 @Groups
注解来定义测试分组,然后在 @Test
注解中通过 groups
属性指定了测试方法所属的分组。TestRunner
类中的 main
方法展示了如何通过命令行运行指定分组的测试。
当然还可以通过XML 配置文件将测试方法或类分配到不同的组。这样,你可以通过指定组名来运行特定的测试集合。以下是如何使用 XML 配置文件来设置测试分组的示例:
XML配置示例:
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="MySuite" verbose="1">
<test name="Unit Tests" annotations="JDK">
<groups>
<run>
<include name="unit"/>
</run>
</groups>
<classes>
<class name="com.example.CalculatorTest">
<methods>
<include name="testAdd"/>
<include name="testMultiply"/>
</methods>
</class>
</classes>
</test>
<test name="Integration Tests" annotations="JDK">
<groups>
<run>
<include name="integration"/>
</run>
</groups>
<classes>
<class name="com.example.ApiIntegrationTest"/>
</classes>
</test>
</suite>
在这个配置文件中,我们定义了一个名为 MySuite
的测试套件,它包含两个测试 Unit Tests
和 Integration Tests
。每个测试定义了一个 groups
块,其中 run
块里的 include
元素指明了要运行的测试组的名称。
com.example.CalculatorTest
类中的 testAdd
和 testMultiply
方法被明确包含在 Unit Tests
测试中,并且它们应该被注解为属于 "unit" 组:
import org.testng.annotations.Test;
import org.testng.annotations.Groups;
@Groups({ "unit" })
public class CalculatorTest {
@Test
public void testAdd() {
// ...
}
@Test
public void testMultiply() {
// ...
}
}
com.example.ApiIntegrationTest
类应该被注解为属于 "integration" 组:
import org.testng.annotations.Test;
import org.testng.annotations.Groups;
@Groups({ "integration" })
public class ApiIntegrationTest {
@Test
public void testApiEndpoint() {
// ...
}
}
要运行这个配置文件,你可以使用 TestNG 的命令行工具并指定 XML 文件:
java -cp path/to/testng.jar org.testng.TestNG path/to/testng.xml
这样,TestNG 将会根据 XML 配置文件中的分组信息运行指定的测试。
3.TestNG 参数化测试
注解 | 描述 |
---|---|
@Test | 标记一个方法为测试方法,可以用于参数化测试。 |
@Parameters | 指定测试方法的参数来源于何处,如外部文件或数据提供器。 |
@DataProvider | 提供测试方法的参数。 |
dataProviderThreadCount | 设置数据提供器的线程数量。 |
代码示例:
import org.testng.annotations.Test;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Parameters;
public class ParameterizedTest {
@Test(dataProvider = "getData", dataProviderClass = DataProviderClass.class)
public void parameterizedTest(String param1, int param2) {
System.out.println("Parameter 1: " + param1);
System.out.println("Parameter 2: " + param2);
}
public static class DataProviderClass {
@DataProvider(name = "getData")
public Object[][] provideData() {
return new Object[][] {
{ "Value1", 1 },
{ "Value2", 2 },
{ "Value3", 3 }
};
}
}
}
在这个示例中,我们通过 @DataProvider
注解定义了一个数据提供器类 DataProviderClass
,它提供了参数化测试方法 parameterizedTest
的参数。parameterizedTest
方法使用 @Test
注解来指定数据提供器的名称和类。
还可以通过@Parameters注解,结合外部的xml文件配置,获取参数值
使用@Parameters注解的xml配置示例:
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="ParameterizedTestSuite" configfailurepolicy="continue">
<parameter name="endpoint" value="http://localhost:8080"/>
<test name="ParameterizedTests">
<parameter name="username" value="testuser"/>
<parameter name="password" value="testpass"/>
<classes>
<class name="com.example.ParameterizedTest"/>
</classes>
</test>
</suite>
在这个配置文件中,我们定义了一个测试套件 ParameterizedTestSuite
,其中包含了两个参数:endpoint
和 username
、password
。这些参数可以在测试方法中通过 @Parameters
注解引用
代码示例:
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;
public class ParameterizedTest {
String username;
String password;
@Parameters({ "username", "password" })
public void setParameters(String username, String password) {
this.username = username;
this.password = password;
}
@Test
public void testLogin() {
// 使用提供的参数来执行测试
boolean success = login(username, password);
assert success : "Login failed for " + username;
}
private boolean login(String username, String password) {
// 模拟登录过程
return "testuser".equals(username) && "testpass".equals(password);
}
}
在这个代码示例中,setParameters
方法使用了 @Parameters
注解,它允许方法接收来自 XML 配置文件中定义的参数。然后,testLogin
方法使用这些参数来执行测试。
要运行参数化测试,你需要确保 TestNG 的命令行工具指向了包含参数定义的 XML 文件:
java -cp path/to/testng.jar org.testng.TestNG path/to/testng.xml
这样,TestNG 将会加载参数并在测试运行时将它们传递给相应的测试方法。
4.TestNG 时间依赖性测试
注解 | 描述 |
---|---|
@Test | 标记一个方法为测试方法,可以指定时间依赖性。 |
timeOut | 指定测试方法的最大执行时间,单位为毫秒。 |
expectedExceptions | 期望抛出的异常类型,如果测试方法抛出了指定的异常,则测试通过。 |
expectedExceptionsMessageRegExp | 期望异常消息匹配的正则表达式。 |
代码示例:
import org.testng.annotations.Test;
import org.testng.Assert;
import java.util.concurrent.TimeUnit;
public class TimeDependencyTest {
@Test(timeOut = 1000) // 测试方法最多执行1秒
public void timeOutTest() throws InterruptedException {
TimeUnit.SECONDS.sleep(2); // 模拟耗时操作
}
@Test(expectedExceptions = ArithmeticException.class)
public void expectedExceptionTest() {
int result = 10 / 0; // 故意抛出异常
}
@Test(expectedExceptions = ArithmeticException.class, expectedExceptionsMessageRegExp = "divide by zero")
public void expectedExceptionMessageTest() {
int result = 10 / 0; // 异常消息包含 "divide by zero"
}
}
在这个示例中,timeOutTest
方法演示了如何使用 timeOut
属性来限制测试方法的执行时间。如果方法执行时间超过指定的时间限制,TestNG 将报告该测试失败。
expectedExceptionTest
方法演示了如何使用 expectedExceptions
属性来指定一个测试方法应该抛出的异常类型。如果测试方法没有抛出指定的异常,TestNG 将报告该测试失败。
expectedExceptionMessageTest
方法演示了如何使用 expectedExceptionsMessageRegExp
属性来指定一个正则表达式,该表达式用于匹配异常消息。如果异常消息不匹配正则表达式,TestNG 将报告该测试失败。
5.TestNG 依赖测试方法
注解 | 描述 |
---|---|
@Test | 标记一个方法为测试方法,可以指定依赖关系。 |
dependsOnMethods | 指定当前测试方法依赖的其他方法。 |
dependsOnGroups | 指定当前测试方法依赖的测试分组。 |
代码示例:
import org.testng.annotations.Test;
public class DependencyTest {
@Test
public void methodOne() {
System.out.println("Method One");
}
@Test(dependsOnMethods = "methodOne")
public void methodTwo() {
System.out.println("Method Two");
}
@Test(dependsOnGroups = "groupOne")
public void methodThree() {
System.out.println("Method Three");
}
}
在这个示例中,methodTwo
依赖于 methodOne
,这意味着 methodOne
必须先运行,然后 methodTwo
才能执行。methodThree
依赖于名为 groupOne
的测试分组,这意味着属于 groupOne
分组的所有测试方法必须先运行,然后 methodThree
才能执行。
6.TestNG 并发测试
注解 | 描述 |
---|---|
@Test | 标记一个方法为测试方法,可以指定并发执行的属性。 |
invocationCount | 指定测试方法应该被调用的次数。 |
threadPoolSize | 指定用于并发执行测试方法的线程池大小。 |
parallel | 指定测试是否可以并行执行。 |
代码示例:
import org.testng.annotations.Test;
import org.testng.annotations.DataProvider;
public class ConcurrencyTest {
@Test(invocationCount = 5, threadPoolSize = 3)
public void testMethod() {
System.out.println("Test method executed by thread: " + Thread.currentThread().getName());
}
@Test(invocationCount = 10, threadPoolSize = 2, parallel = true)
public void testMethodWithDataProvider(@SuppressWarnings("unused") int i) {
System.out.println("Test method with data provider executed by thread: " + Thread.currentThread().getName());
}
@DataProvider(name = "numbers")
public Object[][] provideNumbers() {
return new Object[][] {
{1}, {2}, {3}, {4}, {5}
};
}
}
在这个示例中,testMethod
使用了 invocationCount
和 threadPoolSize
属性来指定测试方法应该被调用 5 次,并且使用一个大小为 3 的线程池来并发执行这些调用。
testMethodWithDataProvider
方法演示了如何结合 DataProvider
和并发执行。它将被调用 10 次,每次调用都由线程池中的线程执行,且线程池的大小为 2。parallel
属性设置为 true
,允许测试方法的调用在并行中执行。
在 TestNG 中,可以通过 XML 配置文件来设置并发测试。这允许你指定测试应该以多线程的方式运行,以及定义线程池的大小。以下是一个使用 XML 配置文件来设置并发测试的示例:
<!--
tests级别:不同的test tag下的用例可以在不同的线程下执行
相同的test tag下的用例只能在同一个线程中去执行
classs级别:相同的class tag 下的用例在同一个线程中执行
不同的class tag 下的用例可以在不同的线程中执行
methods级别:所有用例都可以在不同的线程下去执行
thread-count:代表了最大并发线程数
xml文件配置这种方式不能指定线程池,只有方法上才可以指定线程池
-->
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="MySuite" parallel="methods" thread-count="5">
<test name="ConcurrentTests">
<classes>
<class name="com.example.ConcurrentTest1"/>
<class name="com.example.ConcurrentTest2"/>
</classes>
</test>
</suite>
在这个配置文件中,suite
标签的 parallel
属性设置为 "methods"
,这表示测试方法将并发执行。thread-count
属性设置为 "5"
,定义了线程池的大小为 5,即最多可以有 5 个测试方法同时运行。
测试类示例:
package com.example;
import org.testng.annotations.Test;
public class ConcurrentTest1 {
@Test
public void testMethod1() {
// 测试逻辑
}
}
class ConcurrentTest2 {
@Test
public void testMethod2() {
// 测试逻辑
}
}
在上述 Java 代码中,ConcurrentTest1
和 ConcurrentTest2
类中的测试方法将根据 XML 配置文件中的设置并发执行。
运行并发测试
要运行这个配置文件,你可以使用 TestNG 的命令行工具并指定 XML 文件:
java -cp path/to/testng.jar;path/to/your/tests org.testng.TestNG path/to/testng.xml
确保你的类路径(Classpath)包含了 TestNG jar 文件和你的测试类。
这样,TestNG 将会根据 XML 配置文件中的设置并发地运行测试方法。
7.TestNG 命令行参数
参数/选项 | 描述 |
---|---|
-suite | 指定要运行的测试套件文件。 |
-test | 指定要运行的测试类。 |
-method | 指定要运行的测试方法。 |
-groups | 运行指定的测试分组。 |
-class | 运行指定的测试类。 |
-d | 指定生成的测试报告的目录。 |
-listener | 指定监听器类。 |
-dataproviderthreadcount | 设置数据提供器的线程数量。 |
-threadcount | 指定并发执行的线程数量。 |
-p | 指定属性文件。 |
-s | 指定套件文件。 |
-c | 指定类文件。 |
-m | 指定方法文件。 |
-t | 指定测试文件。 |
-v | 打印 TestNG 的版本信息。 |
-h | 打印帮助信息。 |
示例
java -cp path/to/testng.jar org.testng.TestNG -test TestClass -method testMethod
在这个示例中,我们使用命令行参数 -test
来指定要运行的测试类 TestClass
,以及 -method
来指定要运行的测试方法 testMethod
。
8.TestNG 测试结果和断言
注解/类 | 描述 |
---|---|
@Test | 标记测试方法,可以指定期望的异常或超时时间。 |
Assert | TestNG 提供的断言类,包含多种断言方法。 |
ITestResult | 提供测试结果的详细信息,如状态、日志等。 |
ITestListener | 监听测试事件,可以自定义测试结果的处理。 |
代码示例:
import org.testng.Assert;
import org.testng.annotations.Test;
import org.testng.ITestResult;
public class ResultAndAssertTest {
@Test
public void assertionExample() {
int expected = 4;
int actual = 2 + 2;
Assert.assertEquals(actual, expected, "2 + 2 should equal 4");
}
@Test
public void testResultExample(ITestResult result) {
// 这里可以获取测试结果的详细信息
System.out.println("Test status: " + result.getStatus());
}
}
在这个示例中,assertionExample
方法使用 Assert.assertEquals
方法来验证实际结果是否等于期望结果。如果不等于,测试将失败,并打印出提供的消息。
testResultExample
方法演示了如何使用 ITestResult
接口来获取测试结果的详细信息,如测试状态。
9.TestNG 测试套件(Suite)的配置
配置项 | 描述 |
---|---|
suite-name | 定义测试套件的名称。 |
test-name | 定义测试的名称。 |
parallel | 指定测试是否可以并行执行。 |
thread-count | 指定并发执行的线程数量。 |
suite-filename | 指定测试套件的文件名。 |
test-filename | 指定测试的文件名。 |
groups | 指定要运行的测试分组。 |
method-selectors | 指定如何选择测试方法。 |
在 TestNG 中,测试套件(Suite)是一个容器,它允许你将多个测试组合在一起进行批量执行。测试套件可以通过 XML 文件来配置,也可以通过注解直接在代码中定义。以下是两种定义测试套件的方法:
XML配置后方式的代码示例
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="MyTestSuite" parallel="tests" thread-count="2">
<test name="Unit Tests">
<classes>
<class name="com.example.CalculatorTest"/>
</classes>
</test>
<test name="Integration Tests">
<classes>
<class name="com.example.ApiIntegrationTest"/>
</classes>
</test>
</suite>
在这个 XML 配置文件中,我们定义了一个名为 MyTestSuite
的测试套件,它包含了两个测试 Unit Tests
和 Integration Tests
。每个 test
标签下可以包含一个或多个 class
标签,指定了需要运行的测试类。
使用注解在代码中定义测试套件的示例:
import org.testng.annotations.SuiteBeforeClass;
import org.testng.annotations.Test;
public class SuiteTest {
@SuiteBeforeClass
public void setUp() {
// 初始化操作,如数据库连接等
}
@Test
public void testMethod1() {
// 单元测试逻辑
}
@Test(dependsOnGroups = "integration")
public void testMethod2() {
// 集成测试逻辑
}
}
在这个 Java 代码示例中,我们使用了 @SuiteBeforeClass
注解来定义一个在测试套件所有测试运行之前执行的方法。虽然这个例子没有直接定义多个测试,但是可以通过组合使用 @Test
注解和分组(groups)来实现类似的效果。
运行测试套件
使用 XML 文件运行测试套件的命令如下:
java -cp path/to/testng.jar;path/to/your/tests org.testng.TestNG path/to/testng.xml
请确保将 path/to/testng.jar
替换为 TestNG jar 文件的实际路径,将 path/to/your/tests
替换为你的测试类文件所在的路径,将 path/to/testng.xml
替换为 XML 配置文件的实际路径。
使用注解定义的测试套件可以通过直接运行带有 @Test
注解的测试类来执行。TestNG 将自动识别和执行定义的测试套件。
10.TestNG 测试方法选择器
注解/类 | 描述 |
---|---|
IMethodSelector | 实现该接口的类可以自定义选择要运行的测试方法的逻辑。 |
XmlMethodSelector | 基于 XML 文件选择测试方法的内置选择器。 |
DefaultMethodSelector | 默认的选择器,按定义顺序运行测试方法。 |
代码示例:
import org.testng.IMethodSelector;
import org.testng.ITestContext;
import org.testng.annotations.Test;
public class CustomMethodSelector implements IMethodSelector {
@Override
public boolean includeMethod(ITestContext context, IMethod method, Object[] parameters) {
String methodName = method.getMethodName();
// 自定义选择逻辑,例如只运行以 "Test" 结尾的方法
return methodName.endsWith("Test");
}
}
@Test
public class SampleTest {
@Test(invocations = 1, methodSelectors = {CustomMethodSelector.class})
public void testMethod1() {
// 这个测试方法将被执行
}
@Test(invocations = 1, methodSelectors = {CustomMethodSelector.class})
public void anotherTestMethod() {
// 这个测试方法不会被执行,因为它的名称不以 "Test" 结尾
}
}
在这个示例中,CustomMethodSelector
类实现了 IMethodSelector
接口,提供了自定义的选择逻辑,只选择方法名以 "Test" 结尾的测试方法执行。SampleTest
类中的 testMethod1
将被执行,而 anotherTestMethod
不会,因为其方法名不满足选择器的逻辑。
11.TestNG 报告监听器
注解/类 | 描述 |
---|---|
ITestListener | 实现该接口的类可以自定义测试事件的处理逻辑。 |
ISuiteListener | 监听测试套件级别的事件。 |
ITestListenerFactory | 可以创建自定义的 ITestListener 实例。 |
TestListenerAdapter | 提供了 ITestListener 接口的默认实现。 |
代码示例:
import org.testng.ITestListener;
import org.testng.ITestResult;
import org.testng.TestListenerAdapter;
import org.testng.annotations.Test;
public class CustomTestListener extends TestListenerAdapter {
@Override
public void onTestFailure(ITestResult result) {
super.onTestFailure(result);
System.out.println("Custom listener: Test failed - " + result.getName());
}
}
@Test.listeners(CustomTestListener.class)
public class SampleTest {
@Test
public void failingTest() {
throw new AssertionError("Intentional failure");
}
}
在这个示例中,CustomTestListener
类继承了 TestListenerAdapter
类并重写了 onTestFailure
方法,以在测试失败时输出自定义的消息。
SampleTest
类使用了 @Test.listeners
注解来指定 CustomTestListener
作为其测试的监听器。当 failingTest
方法失败时,CustomTestListener
的 onTestFailure
方法会被调用,输出自定义的消息。
12.TestNG 动态依赖性
注解/类 | 描述 |
---|---|
IHookable | 允许测试方法具有动态依赖性。 |
ITest | 提供测试的详细信息,包括其依赖性 |
代码示例:
import org.testng.IHookable;
import org.testng.ITest;
import org.testng.annotations.Test;
public class DynamicDependencyTest implements IHookable {
@Override
public boolean skip(ITest test, ITestResult iTestResult) {
// 动态决定是否跳过当前测试
String testName = test.getMethodName();
if (testName.contains("Skipped")) {
return true; // 跳过包含 "Skipped" 的测试方法
}
return false;
}
@Test
public void testMethod1() {
System.out.println("Running testMethod1");
}
@Test
public void skippedTestMethod() {
System.out.println("Running skippedTestMethod");
}
}
在这个示例中,DynamicDependencyTest
类实现了 IHookable
接口,通过 skip
方法提供了动态跳过测试的逻辑。如果测试方法的名称包含 "Skipped",则该方法将被跳过。
13.TestNG 跨测试方法共享数据
概念/类 | 描述 |
---|---|
ITestContext | 提供对当前测试上下文的访问,可以用于跨测试方法共享数据。 |
setAttribute | 将数据设置到测试上下文中。 |
getAttribute | 从测试上下文中获取数据。 |
removeAttribute | 从测试上下文中移除数据。 |
代码示例:
import org.testng.ITestContext;
import org.testng.annotations.Test;
public class DataSharingTest {
@Test
public void setAttributeTest(ITestContext testContext) {
// 将数据设置到测试上下文中
testContext.setAttribute("sharedData", "This is shared data");
}
@Test(dependsOnMethods = "setAttributeTest")
public void getAttributeTest(ITestContext testContext) {
// 从测试上下文中获取数据
String sharedData = (String) testContext.getAttribute("sharedData");
System.out.println("Shared data: " + sharedData);
}
}
在这个示例中,setAttributeTest
方法使用 ITestContext
将数据设置到测试上下文中。然后,getAttributeTest
方法从测试上下文中获取之前设置的数据,并打印出来。
14.TestNG 灵活的测试运行配置
参数/选项 | 描述 |
---|---|
-p 或 -params | 指定参数文件,用于为测试提供外部输入。 |
-D | 指定系统属性,可以被测试使用。 |
-configfailurepolicy | 配置失败策略,如继续执行、抛出异常等。 |
-groups | 运行指定的测试分组。 |
-testrunfactory | 指定测试运行工厂类,用于自定义测试运行逻辑。 |
示例:
java -cp path/to/testng.jar org.testng.TestNG -p config.properties -Dbrowser=chrome
在这个示例中,命令行参数 -p
用于指定一个属性文件 config.properties
,该文件可以包含测试所需的参数。-D
参数用于设置系统属性 browser
的值为 chrome
,这个属性可以在测试中被读取和使用。
15.TestNG 测试结果的自定义
注解/类 | 描述 |
---|---|
ITestResultListener | 允许自定义测试结果的监听器。 |
onTestStart | 当测试开始时调用。 |
onTestSuccess | 当测试成功时调用。 |
onTestFailure | 当测试失败时调用。 |
onTestSkipped | 当测试被跳过时调用。 |
onTestFailedButWithinSuccessPercentage | 当测试失败但失败率在允许的百分比内时调用。 |
代码示例:
import org.testng.ITestResultListener;
import org.testng.ITestResult;
public class CustomTestResultListener implements ITestResultListener {
@Override
public void onTestStart(ITestResult result) {
System.out.println("Test " + result.getName() + " is starting.");
}
@Override
public void onTestSuccess(ITestResult result) {
System.out.println("Test " + result.getName() + " succeeded.");
}
@Override
public void onTestFailure(ITestResult result) {
System.out.println("Test " + result.getName() + " failed.");
}
@Override
public void onTestSkipped(ITestResult result) {
System.out.println("Test " + result.getName() + " was skipped.");
}
@Override
public void onTestFailedButWithinSuccessPercentage(ITestResult result) {
System.out.println("Test " + result.getName() + " failed but is within the success percentage.");
}
}
在这个示例中,CustomTestResultListener
实现了 ITestResultListener
接口,提供了在测试的不同阶段自定义行为的方法。这些自定义的方法可以在测试执行的不同阶段提供额外的日志信息或其他自定义行为。
16.TestNG 软依赖性测试
注解/类 | 描述 |
---|---|
@Test | 标记一个方法为测试方法,可以指定软依赖性。 |
expectedExceptions | 期望抛出的异常类型,如果测试方法抛出了指定的异常,则测试通过。 |
dependsOnMethods | 可以指定当前测试方法依赖的其他方法,并且可以设置是否为软依赖。 |
代码示例:
import org.testng.annotations.Test;
public class SoftDependencyTest {
@Test
public void methodOne() {
System.out.println("Method One");
}
@Test(dependsOnMethods = "methodOne", alwaysRun = true)
public void methodTwo() {
System.out.println("Method Two");
}
}
在这个示例中,methodTwo
依赖于 methodOne
,但由于使用了 alwaysRun = true
,即使 methodOne
失败,methodTwo
也会执行。这是软依赖性的一个例子,即依赖的方法失败不会导致当前方法跳过。
17.TestNG 测试优先级
注解/类 | 描述 |
---|---|
@Test | 标记一个方法为测试方法,可以指定优先级。 |
priority | 指定测试方法的执行优先级。 |
代码示例:
import org.testng.annotations.Test;
public class TestPriority {
@Test(priority = 1)
public void highPriorityTest() {
System.out.println("High priority test");
}
@Test(priority = 2)
public void mediumPriorityTest() {
System.out.println("Medium priority test");
}
@Test(priority = 3)
public void lowPriorityTest() {
System.out.println("Low priority test");
}
}
在这个示例中,我们使用了 @Test
注解的 priority
属性来指定不同测试方法的执行优先级。具有较高优先级的测试方法将优先执行。如果没有指定优先级,则默认优先级为 0。
18.TestNG 测试运行工厂
注解/类 | 描述 |
---|---|
@Test | 标记一个方法为测试方法。 |
ITestRunnerFactory | 允许自定义测试运行器,以控制测试的执行方式。 |
TestRunner | TestNG 提供的测试运行器类。 |
代码示例:
import org.testng.ITestRunnerFactory;
import org.testng.TestRunner;
public class CustomTestRunnerFactory implements ITestRunnerFactory {
@Override
public TestRunner newTestRunner(ITest presentTest, XmlTest xmlTest, XmlSuite xmlSuite) {
// 返回自定义的 TestRunner 实例
return new CustomTestRunner(presentTest, xmlTest, xmlSuite);
}
static class CustomTestRunner extends TestRunner {
public CustomTestRunner(ITest presentTest, XmlTest xmlTest, XmlSuite xmlSuite) {
super(presentTest, xmlTest, xmlSuite);
// 自定义测试运行逻辑
}
}
}
在这个示例中,我们创建了一个实现了 ITestRunnerFactory
接口的 CustomTestRunnerFactory
类,它返回一个自定义的 TestRunner
实例 CustomTestRunner
。这样,我们可以在 CustomTestRunner
类中自定义测试的执行逻辑。
要使用自定义的测试运行工厂,需要在 TestNG 的套件配置文件中指定它:
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="MySuite" >
<listeners>
<listener class-name="path.to.CustomTestRunnerFactory" />
</listeners>
<test name="MyTest">
<classes>
<class name="com.example.MyTestClass" />
</classes>
</test>
</suite>
19. TestNG 测试环境的配置
注解/类 | 描述 |
---|---|
@BeforeSuite | 在测试套件中的所有测试运行之前运行的方法,用于测试环境的配置。 |
@AfterSuite | 在测试套件中的所有测试运行之后运行的方法,用于测试环境的清理。 |
系统属性 | 通过系统属性来配置测试环境。 |
环境变量 | 通过环境变量来配置测试环境。 |
代码示例:
import org.testng.annotations.BeforeSuite;
import org.testng.annotations.AfterSuite;
public class EnvironmentConfiguration {
@BeforeSuite
public void setUp() {
// 设置测试环境,如数据库连接、服务器配置等
System.setProperty("database.url", "jdbc:mysql://localhost:3306/testdb");
}
@AfterSuite
public void tearDown() {
// 清理测试环境
// 关闭数据库连接、停止服务器等
}
}
在这个示例中,setUp
方法在测试套件中的所有测试运行之前执行,用于配置测试环境。tearDown
方法在测试套件中的所有测试运行之后执行,用于清理测试环境。
此外,系统属性和环境变量也常用于配置测试环境。例如,数据库的 URL、端口号、用户名和密码等信息可以通过系统属性或环境变量来设置。
20.Spring Boot 项目中集成 TestNG
20.1 添加TestNG依赖
首先,确保你的 Spring Boot 项目包含 TestNG 依赖。如果你使用 Maven,可以在 pom.xml
文件中添加如下依赖:
<dependencies>
<!-- Other dependencies -->
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>7.4.0</version> <!-- 使用你需要的版本 -->
<scope>test</scope>
</dependency>
</dependencies>
对于 Gradle 用户,添加如下依赖到 build.gradle
文件中:
dependencies {
// Other dependencies
testImplementation 'org.testng:testng:7.4.0' // 使用你需要的版本
}
20.2 配置TestNG
在 src/test/resources
目录下创建 testng.xml
文件,并配置你的测试套件:
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Spring Boot Tests" configfailurepolicy="continue">
<test name="Unit Tests">
<classes>
<class name="com.example.MyUnitTest"/>
</classes>
</test>
<test name="Integration Tests">
<classes>
<class name="com.example.MyIntegrationTest"/>
</classes>
</test>
</suite>
20.3.编写测试类
创建测试类,使用 TestNG 的注解来编写单元测试和集成测试。
import org.testng.annotations.Test;
public class MyUnitTest {
@Test
public void testMethod() {
// 单元测试逻辑
}
}
20.4 运行测试
在 IntelliJ IDEA 或其他支持 Maven 的 IDE 中,TestNG 测试通常可以自动识别并运行。你可以直接通过 IDE 的测试运行器来执行测试。
如果你在命令行中运行测试,可以使用 Maven 的 Surefire 插件:
mvn test
20.5 Spring Boot集成
Spring Boot 应用程序通常需要配置 Spring Test 相关的依赖来支持 Spring Boot 测试。确保你的项目中包含了如下依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
请注意,这里我们通过 exclusions
排除了 JUnit,因为你可能想使用 TestNG 而不是 JUnit。
20.6 配置Spring Boot Test
在 TestNG 的 testng.xml
文件中,你可以配置 Spring Boot Test 的相关设置,例如:
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Spring Boot Integration Tests">
<listeners>
<listener class-name="org.springframework.test.context.TestExecutionListeners"/>
</listeners>
<test name="Spring Boot Tests">
<classes>
<class name="com.example.MySpringBootTest"/>
</classes>
</test>
</suite>
确保你的测试类使用 Spring Test 相关的注解,如 @SpringBootTest
。
20.7 调试和查看报告
TestNG 生成的测试报告可以位于 target/surefire-reports
目录下,你可以通过该目录下的 HTML 文件查看测试结果。
前边提到的以xml方式配置的,放在resources下边的TestNG相关的xml配置文件,idea可以自动识别,所以其实也可以不用执行java -cp ...这样的命令来运行。
idea和eclipse都有TestNG对应的插件: