TestNG简介
它是一个单元测试框架,它提供了很多的注解(python装饰器)来帮助我们管理测试用例。
它是Java自动化测试最重要的基石。官网:TestNG Documentation
它在java自动化测试里面主要做什么事情?
发现测试用例
执行测试用例
判断测试结果
生成测试报告
新建一个Maven项目
Interlij lDEA=Pycharm
maven:第三方库,你只需要简单的在pom.xml中配置坐标,就可以自动的从库下载对应的包
如何安装TestNG:
<!--单元测试依赖-->
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>6.8.7</version>
</dependency>
TestNG使用它最常用的注解
1.测试用例注解:
- @Test:标识方法是一个基于TestNG的测试用例
- 常用属性:
-
- enabled =false 标识它不是一个测试用例
- priority=-1 默认的测试用例的执行顺序是基于方法名的ASCIl码,priority可以改变用例的执行顺序,值越小优先级越高。
- invocationCount=2 控制测试用例的执行次数
-
-
- dependsOnMethods={"方法名”} 解决测试用例之间的依赖关系
-
-
- dependsOnGroups: 指定当前测试方法依赖于哪些组。依赖的组必须先执行。
dataProvider
属性来指定数据提供者方法的名称
- @DataProvider
-
- 这个注解用于为测试方法提供参数。
- 它可以返回一个数组或一个
Iterator
,每个元素都是一个参数数组。
- @Parameters
-
- 这个注解用于从命令行参数或配置文件中读取参数。
- @Factory
-
- 这个注解用于创建测试类的实例,可以传递参数给构造函数。
- @Listeners
-
- 这个注解用于指定监听器,监听器可以监听测试的执行并执行自定义逻辑。
- @DependsOnMethods 和 @DependsOnGroups
-
- 这两个注解用于设置测试方法或测试组之间的依赖关系。
2.前后置注解
- 比如:链接数据库,打开浏览器
-
- @BeforeClass 和 @AfterClass(相当于一个子模块)
-
-
- 这两个注解用于在测试类的所有测试方法之前和之后执行代码。
@BeforeClass
:在所有测试方法执行之前执行一次。@AfterClass
:在所有测试方法执行之后执行一次。- 在当前测试类中的所有测试方法之前后执行一次。
- 用于执行类级别的初始化,比如创建共享资源、初始化类变量等。
-
-
- @BeforeMethod 和 @AfterMethod(相当于一个功能)
-
-
- 这两个注解用于在每个测试方法之前和之后执行代码。
@BeforeMethod
:在每个测试方法执行之前执行。@AfterMethod
:在每个测试方法执行之后执行。- 在每个测试方法之前后执行。
- 用于执行每个测试方法的初始化,比如重置测试状态、设置测试输入等。
-
-
- @BeforeTest 和 @AfterTest(相等于一个模块)
-
-
- 这两个注解用于在测试类中的所有测试方法之前和之后执行代码。
@BeforeTest
:在测试类中的所有测试方法执行之前执行一次。@AfterTest
:在测试类中的所有测试方法执行之后执行一次。- 在每个测试类(Test)的所有测试方法之前后执行一次。
- 用于执行测试类级别的初始化,比如设置测试数据、测试环境等。
-
-
- @BeforeSuite 和 @AfterSuite(相当于整个项目)
-
-
- 这两个注解用于在测试套件的所有测试类之前和之后执行代码。
@BeforeSuite
:在测试套件的所有测试类执行之前执行一次。@AfterSuite
:在测试套件的所有测试类执行之后执行一次。- 这是最高级别的初始化注解。
- 在整个测试套件(Suite)的所有测试类和测试方法之前后执行一次。
- 通常用于执行整个测试套件开始前后需要进行的一次性设置,比如数据库连接、日志配置等。
-
断言
- assertEquals(expected, actual)
-
- 检查预期值(expected)和实际值(actual)是否相等。
- 如果不相等,测试将失败,并显示预期值和实际值。
assertEquals("Expected value", "Actual value");
- assertTrue(condition)
-
- 检查给定的条件是否为真(boolean true)。
- 如果条件为假,测试将失败。
assertTrue("Condition should be true", condition);
- assertFalse(condition)
-
- 检查给定的条件是否为假(boolean false)。
- 如果条件为真,测试将失败。
assertFalse("Condition should be false", condition);
- assertNull(object)
-
- 检查给定的对象是否为 null。
- 如果对象不为 null,测试将失败。
assertNull("Object should be null", object);
批量执行所有用例
使用 TestNG XML 配置文件:
TestNG 允许你创建一个 XML 配置文件来定义测试套件(Suite),其中可以包含多个测试(Test),每个测试可以包含多个测试类(Class)。以下是 XML 配置文件的一个简单示例:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="MyTestSuite">
<test name="MyTest">
<classes>
<class name="com.example.Test1" />
<class name="com.example.Test2" />
<class name="com.example.Test3" />
</classes>
</test>
</suite>
然后,你可以使用 testng
命令行工具来执行这个 XML 文件:
testng MyTestSuite.xml
使用 Maven 插件:
如果你的项目是基于 Maven 的,你可以在 pom.xml
文件中添加 TestNG 插件配置,并指定要执行的测试类:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.2</version>
<configuration>
<suiteXmlFiles>
<suiteXmlFile>src/test/resources/testng.xml</suiteXmlFile>
</suiteXmlFiles>
</configuration>
</plugin>
</plugins>
</build>
然后,你可以通过执行 mvn test
命令来运行测试。
实现数据驱动(正例和反例)
第一种方法(不可取)
第一步:在testng.xml中定义参数的值:
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="DataDrivenTestSuite">
<test name="DataDrivenTest">
<parameter name="username" value="user1"/>
<parameter name="password" value="pass1"/>
<classes>
<class name="com.example.DataDrivenTest"/>
</classes>
</test>
</suite>
第二步:在测试用例上面通过以下注解来引入参数:
package com.example;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;
public class DataDrivenTest {
@Parameters({ "username", "password" })
@Test
public void testLogin(String username, String password) {
// 测试逻辑,使用提供的用户名和密码进行登录
System.out.println("Testing login with username: " + username + " and password: " + password);
// 这里应该是实际的登录逻辑和断言
}
}
3. 执行测试
testng testng.xml
第二种方法
步骤 1: 定义数据提供者方法
首先,你需要定义一个使用 @DataProvider
注解的方法,该方法返回一个二维数组。数组中的每个子数组代表一组测试数据。
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
public class DataDrivenTest {
// 数据提供者方法
@DataProvider(name = "dataProvider")
public Object[][] provideData() {
// 返回一个二维数组,每个子数组包含一组测试数据
return new Object[][] {
{"user1", "password1"},
{"user2", "password2"},
{"user3", "password3"}
};
}
}
步骤 2: 编写测试方法
接下来,编写测试方法,并使用 @Test
注解的 dataProvider
属性来指定数据提供者方法的名称。测试方法的参数应与数据提供者方法中的数据列对应。
import org.testng.annotations.Test;
public class DataDrivenTest {
// 数据提供者方法
@DataProvider(name = "dataProvider")
public Object[][] provideData() {
// 返回一个二维数组,每个子数组包含一组测试数据
return new Object[][] {
{"user1", "password1"},
{"user2", "password2"},
{"user3", "password3"}
};
}
// 测试方法,使用数据提供者
@Test(dataProvider = "dataProvider")
public void testLogin(String username, String password) {
// 这里添加实际的测试逻辑,例如登录验证
System.out.println("Testing login with username: " + username + " and password: " + password);
// 假设所有用户都能成功登录,实际测试中应替换为具体的断言
assert "password".equals(password) : "Login failed for user: " + username;
}
}
步骤 3: 执行测试
testng DataDrivenTest.java
第三种方法(使用 @Factory
注解)
@Factory
注解可以用来创建测试类的实例,并且每个实例都可以有不同的参数。
import org.testng.annotations.Factory;
import org.testng.annotations.Test;
public class DataDrivenTest {
String username;
String password;
@Factory
public Object[] createInstances() {
return new Object[] {
new DataDrivenTest("user1", "pass1"),
new DataDrivenTest("user2", "pass2")
// 更多实例
};
}
public DataDrivenTest(String username, String password) {
this.username = username;
this.password = password;
}
@Test
public void testLogin() {
// 使用 username 和 password 进行测试
}
}
第四种方法(使用外部数据源)
你可以从外部数据源(如 CSV、Excel、JSON、数据库等)读取数据,并在 @DataProvider
方法中返回这些数据。
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Iterator;
import java.util.NoSuchElementException;
public class DataProviderFromExcel {
@DataProvider(name = "excelData")
public Iterator<Object[]> provideExcelData() throws IOException {
FileInputStream fis = new FileInputStream(new File("data.xlsx"));
Workbook workbook = new XSSFWorkbook(fis);
Sheet sheet = workbook.getSheetAt(0);
Iterator<Row> rowIterator = sheet.iterator();
Iterator<Object[]> data = new Iterator<Object[]>() {
@Override
public boolean hasNext() {
return rowIterator.hasNext();
}
@Override
public Object[] next() {
Row currentRow = rowIterator.next();
int lastColumn = currentRow.getLastCellNum();
Object[] dataRow = new Object[lastColumn];
for (int i = 0; i < lastColumn; i++) {
Cell cell = currentRow.getCell(i);
dataRow[i] = cell.getStringCellValue();
}
return dataRow;
}
};
return data;
}
@Test(dataProvider = "excelData")
public void testMethod(String[] data) {
// 测试逻辑
}
}
第五种方法(使用 Java 8 流和 Lambda 表达式)
如果你使用的是 Java 8 或更高版本,可以利用流(Stream)和 Lambda 表达式来创建数据提供者。
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import java.util.Arrays;
import java.util.stream.Stream;
public class DataProviderUsingStreams {
@DataProvider(name = "streamData")
public static Object[][] provideData() {
return Stream.of(
Arrays.asList("user1", "pass1"),
Arrays.asList("user2", "pass2")
// 更多数据
).map(list -> list.toArray(new Object[0])).toArray(Object[][]::new);
}
@Test(dataProvider = "streamData")
public void testMethod(String username, String password) {
// 测试逻辑
}
}
Alure生成精美的测试报告
1.添加依赖
<dependencies>
<!-- TestNG依赖 -->
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>6.14.3</version>
<scope>test</scope>
</dependency>
<!-- Allure TestNG 依赖 -->
<dependency>
<groupId>io.qameta.allure</groupId>
<artifactId>allure-testng</artifactId>
<version>2.13.5</version>
<scope>test</scope>
</dependency>
<!-- AspectJ依赖 -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.10</version>
</dependency>
</dependencies>
2.构建allure的插件,AOP拦截测试结果
<build>
<plugins>
<!-- 编译插件定义开始 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<!-- 设置编译的Java源码版本和目标字节码版本均为1.8 -->
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<!-- 编译插件定义结束 -->
<!-- 测试插件定义开始,用于运行测试并生成Allure测试报告 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
<configuration>
<!-- 定义Java代理参数,用于启动AspectJ代理 -->
<argLine>
-javaagent:"${settings.localRepository}/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar"
</argLine>
<!-- 指定要执行的TestNG测试套件路径 -->
<suiteXmlFiles>
<suiteXmlFile>${suiteXmlFile}</suiteXmlFile>
</suiteXmlFiles>
<systemProperties>
<property>
<!-- 配置Allure测试结果存储路径 -->
<name>allure.results.directory</name>
<value>${project.build.directory}/allure-results</value>
</property>
</systemProperties>
<!-- 设置测试出现异常时是否继续执行 -->
<testFailureIgnore>true</testFailureIgnore>
</configuration>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${aspectj.version}</version>
</dependency>
</dependencies>
</plugin>
<!-- 测试插件定义结束 -->
</plugins>
</build>
3.生成临时json报告
直接运行testng.xml即可,但是这里有一个问题是每次执行不会自动的清空原来的json报告。
使用 Maven 运行测试用例:(会清空原来的报告)
mvn clean test
这将执行测试用例,并生成 Allure 报告所需的 JSON 结果文件。
4.生成 Allure 报告
测试完成后,在项目根目录下执行以下命令来生成 Allure 报告:
allure generate allure-results -o allure-report
可以使用 Maven 执行以下命令来生成 Allure 报告:
mvn allure:serve
这将在 allure-report
目录下生成 HTML 报告。
5.查看报告
最后,使用以下命令在浏览器中打开生成的 Allure 报告:
allure open allure-report
或者直接打开 allure-report
目录下的 index.html
文件。
通过这些步骤,你可以在 Maven 项目中集成 Allure 并生成精美的测试报告。