文章目录
- 简介
- 简单示例
- 执行测试并查看测试报告
- 方式一 在IDEA中运行testng.xml文件
- 方式二 在IDEA中运行测试类或者package
- 方式三 在Maven中运行测试
- 统计测试覆盖率
- 方式一 IDEA 支持详细的代码测试覆盖率统计
- 方式二 Maven支持测试覆盖率
- 在IDEA中创建测试用例
- 使用 IDEA 快速创建单元测试,提高开发和测试效率
- 常用注解
- 常用场景
- 忽略测试
- 参数化测试
- 测试组
- 异常测试
- 超时测试
- 多线程测试
- 重新运行失败的测试
- 断言
- 验证两个值是否相等
- 验证条件是否为真或为假
- 验证值是否为 null 或非 null
- 验证是否抛出了预期的异常
简介
官网: https://testng.org/doc/index.html
TestNG是一个基于 Java 的开源测试框架。该框架受到 JUnit 和 NUnit 的启发,但引入了一些新功能,使其更强大且更易于使用。您可以在测试实施期间创建 HTML 报告。它具有分组测试、注释、参数化等功能,有助于更快地创建测试。
TestNG的核心特性
-
在任意大小的线程池中运行测试,并提供各种可用策略(所有方法都在自己的线程中,每个测试类一个线程等等)。
-
测试您的代码是否是线程安全的。
-
灵活的测试配置。
-
支持数据驱动测试(使用
@DataProvider
)。 -
支持参数。
-
强大的执行模型(不再是
TestSuite
)。 -
由多种工具和插件支持(Eclipse、IDEA、Maven 等)。
-
嵌入 BeanShell 以提高灵活性。
-
用于运行时和日志记录的默认 JDK 函数(无依赖项)。
-
应用程序服务器测试的相关方法。
-
可以进行单元测试,功能测试,端到端测试,集成测试等。
简单示例
1.添加依赖
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>7.1.0</version>
<scope>test</scope>
</dependency>
TestNG 最高 v7.5: JDK 8 或更高版本。
TestNG v7.6.0 及更高版本: JDK 11 或更高版本。
2.简单测试示例
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");
}
}
- 一个测试方法可以属于一个或多个组。
执行测试并查看测试报告
方式一 在IDEA中运行testng.xml文件
这是一个testNG.xml文件
<!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>
在testNG.xml文件上右键运行即可。
方式二 在IDEA中运行测试类或者package
在测试类或者测试的package上右键运行即可。
方式三 在Maven中运行测试
在Maven项目中Maven Surefire Plugin
插件是用来执行单元测试的,所以在pom.xml文件中需要添加Maven Surefire Plugin
插件,在 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>
在执行完之后,surefire的report默认会存放在target/surefire-reports 文件夹中。
<trimStackTrace>
设置为true
,以裁剪堆栈跟踪信息,使其更易读。<parallel>
设置为classes
,以允许并行执行测试类,提高执行速度。<threadCountMethods>
设置为一个适当的线程数,用于并行执行测试方法。<useSystemClassLoader>
设置为false
,以避免使用系统类加载器,减少可能的冲突。<forkCount>
设置为1
,以避免使用多个进程执行测试。<reuseForks>
设置为true
,以重用测试进程,提高执行效率。<argLine>
可以指定额外的 JVM 参数,如堆内存大小、永久代大小等。<rerunFailingTestsCount>
设置为一个适当的值,以在测试失败时重新运行测试。<testFailureIgnore>
设置为true
,以忽略测试失败并继续构建过程。<reportsDirectory>
指定测试报告的输出目录。
Maven也有自己的一些常用命令,我们可以通过Maven命令来执行测试代码。
编译: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 --将压缩文件上传私服
我们可以通过
mvn clean test
执行测试用例,整个过程是通过调用pom.xml 中的Maven Surefire Plugin
插件 - > 运行所配置的测试用例。跳过测试
mvn clean package/install -DskipTests
mvn clean package/install -Dmaven.test.skip=true
统计测试覆盖率
测试代码覆盖率越高,代码质量越高
方式一 IDEA 支持详细的代码测试覆盖率统计
很简单不介绍了
方式二 Maven支持测试覆盖率
JaCoCo是一个开源的覆盖率工具,它针对的开发语言是java,其使用方法很灵活,可以嵌入到Ant、Maven中,很多第三方的工具提供了对JaCoCo的集成,如sonar、Jenkins等。
JaCoCo包含了多种尺度的覆盖率计数器,包含指令级覆盖(Instructions,C0coverage),分支(Branches,C1coverage)、圈复杂度(CyclomaticComplexity)、行覆盖(Lines)、方法覆盖(non-abstract methods)、类覆盖(classes)
pom.xml添加
<!-- 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>
在工程根目录下执行mvn clean test
来执行单元测试并生成覆盖率报告,生成后的报告为./target/site/jacoco/index.html
,通过浏览器打开该文件,可以看到整体的覆盖率以及单元测试的情况。
在IDEA中创建测试用例
使用 IDEA 快速创建单元测试,提高开发和测试效率
在需要测试的类或接口(推荐基于接口创建)名称上使用 Alt+Enter
,然后选择创建测试。
常用注解
注解 | 注释 |
---|---|
@BeforeSuite | 被注解的方法,将在整个测试套件之前运行 |
@AfterSuite | 被注解的方法,将在整个测试套件之后运行 |
@BeforeTest | 被注解的方法,将在测试套件内所有用例执行之前运行 |
@AfterTest | 被注解的方法,将在测试套件内所有用例执行之后运行 |
@BeforeGroups | 被注解的方法,将在指定组内任意用例执行之前运行 |
@AfterGroups | 被注解的方法,将在指定组内任意用例执行之后运行 |
@BeforeClass | 带注释的方法将在调用当前类中的第一个测试方法之前运行。 |
@AfterClass | 被注解的方法将在当前类中的所有测试方法运行完毕后运行。 |
@BeforeMethod | 带注释的方法将在每个测试方法之前运行。 |
@AfterMethod | 带注释的方法将在每个测试方法之后运行。 |
@DataProvider | 被注解的方法,强制返回一个 二维数组Object[ ][ ]作为另外一个@Test方法的数据工厂 |
@Factory | 被注解的方法,作为对象工厂,强制返回一个对象数组 Object[ ] |
@Listeners | 定义一个测试类的监听器 |
@Parameters | 定义一组参数,在方法运行期间向方法传递参数的值,参数的值在testng.xml中定义 |
@Test | 标记方法为测试方法,如果标记的是类,则此类中所有的public方法都为测试方法 |
具体生命周期如下图:
常用场景
忽略测试
有时,你可能需要暂时忽略某些测试方法,以避免执行它们。你可以使用 @Test(enabled = false)
注解来标记需要忽略的测试方法。
import org.testng.annotations.Test;
public class IgnoreTest {
@Test
public void testMethod1() {
// 测试方法1的代码
}
@Test(enabled = false)
public void testMethod2() {
// 测试方法2的代码
}
}
testMethod2
被标记为 enabled = false
,表示该测试方法将被忽略,不会执行。只有被标记为 enabled = true
或未使用 enabled
属性的测试方法才会被执行。
参数化测试
通过参数化测试,可以使用不同的输入值运行相同的测试方法,以验证代码在不同参数下的行为。
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 Groups),可以对测试方法进行分类,并选择性地运行特定组的测试。
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);
}
}
异常测试
在测试中验证代码是否能够正确地抛出预期的异常。
import org.testng.annotations.Test;
public class ExceptionTest {
@Test(expectedExceptions = ArithmeticException.class)
public void testDivideByZero() {
int result = Calculator.divide(10, 0);
}
}
使用 @Test
注解的 expectedExceptions
属性指定了预期的异常类型。如果在测试方法中执行的代码确实抛出了指定的异常,则测试将被标记为通过。
超时测试
设置测试方法的最大执行时间,以确保代码在规定的时间范围内完成执行。
import org.testng.annotations.Test;
public class TimeoutTest {
@Test(timeOut = 500)
public void testLongRunningOperation() throws InterruptedException {
// 模拟一个长时间运行的操作
Thread.sleep(1000);
}
}
使用 @Test
注解的 timeOut
属性指定了最大执行时间(以毫秒为单位)。如果测试方法的执行时间超过指定的时间,测试将被标记为失败。
多线程测试
使用 TestNG,你可以在多个线程中并发地执行测试方法,以模拟并发和并行的场景。可以通过在 @Test
注解中设置 threadPoolSize
和 invocationCount
属性来实现。
import org.testng.annotations.Test;
public class MultiThreadTest {
@Test(threadPoolSize = 5, invocationCount = 10)
public void testMethod() {
// 在多个线程中并发执行的测试方法
}
}
testMethod
使用了 threadPoolSize = 5
和 invocationCount = 10
,表示将在一个具有 5 个线程的线程池中并发地执行该测试方法,总共执行 10 次。这样可以模拟并发的场景,并观察测试方法在多线程环境下的行为。
注意:在编写多线程测试时,要确保测试方法是线程安全的,并处理好线程间的同步和共享资源的访问。
重新运行失败的测试
在maven环境执行测试中,每次测试失败时,TestNG 都会在输出目录中创建一个名为testng-failed.xml
的文件。此 XML 文件包含仅重新运行这些失败的方法所需的信息,使您能够快速重现故障,而无需运行整个测试。
\target\surefire-reports\testng-failed.xml
断言
在 TestNG 中,常用的断言方法位于 org.testng.Assert
类中,它提供了一系列用于验证测试结果的断言方法。以下是一些常用的断言方法及其最佳实践的代码示例:
验证两个值是否相等
assertEquals
:验证两个值是否相等。
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.");
}
}
在上述示例中,assertEquals
方法用于验证 result
的值是否等于 5。如果断言失败,会抛出 AssertionError,并显示指定的错误消息。
验证条件是否为真或为假
assertTrue
和 assertFalse
:验证条件是否为真或为假。
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.");
}
}
在上述示例中,assertTrue
方法用于验证 number
是否为偶数。如果条件不满足,断言失败并显示错误消息。
验证值是否为 null 或非 null
assertNull
和 assertNotNull
:验证值是否为 null 或非 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.");
}
}
在上述示例中,assertNotNull
方法用于验证 names
数组是否为非 null。如果数组为 null,断言失败并显示错误消息。
验证是否抛出了预期的异常
assertThrows
:验证是否抛出了预期的异常。
import org.testng.Assert;
import org.testng.annotations.Test;
public class AssertionTest {
@Test
public void testDivideByZero() {
Assert.assertThrows(ArithmeticException.class, () -> Calculator.divide(10, 0));
}
}
在上述示例中,assertThrows
方法用于验证 Calculator.divide(10, 0)
是否抛出了 ArithmeticException
异常。如果没有抛出预期的异常,断言失败。