在自动化测试中,我们必须依赖某种工具来编写测试用例、验证测试结果、执行测试用例,这种工具就叫做测试框架。基于不同的开发语言,常用的测试框架有如下几类:
框架 | 语言 | 用途 |
---|---|---|
JUnit | Java | 主要用于 Java 代码的单元测试,是 Java 生态中最常用的单元测试框架 |
TestNG | Java | TestNG 是 JUnit 的 “增强升级版”,继承了 JUnit 的基础功能(如注解语法),但通过扩展特性(数据驱动、分组依赖、并行执行等)覆盖了更复杂的测试场景。适合大型项目和复杂测试场景 |
Pytest | Python | 可用于 Python 项目的单元测试、功能测试、集成测试等各种测试场景 |
NUnit | C# | 主要用于 .NET 平台的单元测试和集成测试。 |
各类测试框架的能力和知识点其实都是相通的。本文就以TestNG为例,为大家介绍测试框架的核心能力和使用方法。
注解是测试框架的核心机制之一,要讲测试框架就离不开注解,我们先来看看注解的定义和作用。
技术定义: 注解(Annotation)是一种代码元数据,用于为程序提供额外的描述性信息。这些信息不直接影响代码逻辑,但可以在编译、类加载、运行时被工具(如编译器、测试框架、IDE)读取和使用,从而实现特定功能(如配置、标记、约束等)。
白话解释: 你可以把注解想象成是代码里的小标签。就好比你在生活中,会给不同的物品贴上标签来表明它们的用途、特点或者一些额外的说明。编译器、测试框架或者其他工具会通过这些标签,对被贴标签的内容做一些特殊处理。
注解的核心特点:
声明方式: 通常以 @ 符号开头(如 Java 中的 @Test、Python 中的 @pytest.mark),后跟注解名称和参数。
作用范围: 可作用于类、方法、变量、参数等。
生命周期: 部分注解仅在编译期有效(如 @Override),部分可在运行时读取(如测试框架中的注解)。
注解是测试框架的 “粘合剂”,其核心思想是:通过元数据驱动测试流程。它通过 声明式语法 简化测试逻辑,实现测试用例的自动化识别、配置、分组、参数化等功能。
如:
@Test注解: 它就像一个 “测试标记笔”。测试框架要知道哪些代码是用来做测试的,哪些不是。通过在方法或者类上加上@Test,就可以清楚地告诉测试框架:“这个方法或者类是一个测试用例,你要去执行它”
@BeforeTest/@AfterTest注解: 用来配置测试的一些条件,比如在测试执行前后要做什么事情。这就好比你在做一件事情之前要先准备好工具,做完之后要把工具收拾好。
@DataProvider注解: 有时候一个测试用例需要用不同的数据来测试,@DataProvider可以帮助实现这个功能,就像给测试用例提供不同的 “食材”。
TestNG(Testing Next Generation)是一个受 JUnit 和 NUnit 启发而设计的测试框架,旨在为开发者提供更强大、更灵活的测试解决方案。它支持测试用例分组和依赖管理、数据驱动测试、并行执行测试用例等,能够满足复杂场景下的测试需求。
作为一个测试框架,TestNG提供了几大类的基本能力:测试用例管理能力、断言能力、测试执行能力、测试报告能力。下面我们为大家详细介绍每种能力的具体使用方法。
在 TestNG 中,我们使用 @Test 注解来定义测试用例。通过@Test注解,我们告诉测试框架:“这个方法或者类是一个测试用例,你要去执行它”。
以下是一个简单的示例:
`import org.testng.annotations.Test;
public class TestCaseDefinitionExample {
@Test
public void testAddition() {
int a = 2;
int b = 3;
int result = a + b;
Assert.assertEquals(result , 5);
}
}`
在上述代码中,@Test 注解标记了 testAddition 方法为一个测试用例。当我们运行这个测试类时,TestNG 会自动执行该方法。
TestNG 支持参数化测试,我们可以使用 @DataProvider 注解来为测试用例提供测试数据。以下是一个示例:
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import org.testng.Assert;
public class DataDrivenTestingExample {
//定义名称为testData的数据提供者
@DataProvider(name = "testData")
public Object[][] provideTestData() {
return new Object[][]{
{2, 3, 5},
{4, 5, 9}
};
}
//使用名称为testData的数据提供者来为测试用例传入测试数据
@Test(dataProvider = "testData")
public void testAddition(int a, int b, int expected) {
int result = a + b;
Assert.assertEquals(result , expected);
}
}
在上述代码中,@DataProvider 注解定义了一个名为 testData 的数据提供者,它返回一个二维数组,包含多组测试数据。@Test 注解的 dataProvider 属性指定了使用testData数据提供者,这样 testAddition 方法会针对每组数据执行一次。
TestNG 允许我们定义测试用例之间的依赖关系,使用 @Test注解中的dependsOnMethods 或 dependsOnGroups 属性来实现测试用例之间的依赖关系定义。以下是一个示例:
import org.testng.annotations.Test;
import org.testng.Assert;
public class DependencyManagementExample {
@Test
public void testLogin() {
// 模拟登录测试
System.out.println("Login successful");
}
/*testCreateOrder依赖于testLogin*/
@Test(dependsOnMethods = "testLogin")
public void testCreateOrder() {
// 模拟创建订单测试
System.out.println("Order created");
}
}
在上述代码中,testCreateOrder 方法依赖于 testLogin 方法,只有当 testLogin 方法执行成功后,testCreateOrder 方法才会执行。
TestNG 提供了丰富的断言方法,用于自动验证测试结果,包括硬断言和软断言。
硬断言: 是一种当断言条件不满足时,会立即终止当前测试用例执行的断言方式。一旦硬断言失败,测试框架会认为该测试用例执行失败,并且不会继续执行该测试用例中后续的代码。
软断言:软断言是当断言条件不满足时,不会立即终止当前测试用例的执行,而是会记录下该断言失败的信息,继续执行测试用例中后续的代码。直到测试用例执行完毕,才会将所有软断言的失败信息汇总并报告。
import org.testng.Assert;
import org.testng.annotations.Test;
public class AssertionExample {
@Test
public void testEquality() {
int result = 2 + 2;
Assert.assertEquals(result, 4, "2 + 2 应该等于 4");
}
}
import org.testng.Assert;
import org.testng.annotations.Test;
public class BooleanAssertionExample {
@Test
public void testTrue() {
boolean condition = 5 > 3;
Assert.assertTrue(condition, "5 应该大于 3");
}
@Test
public void testFalse() {
boolean condition = 2 < 1;
Assert.assertFalse(condition, "2 不应该小于 1");
}
}
import org.testng.Assert;
import org.testng.annotations.Test;
public class NullAssertionExample {
@Test
public void testNull() {
String str = null;
Assert.assertNull(str, "str 应该为 null");
}
@Test
public void testNotNull() {
String str = "test";
Assert.assertNotNull(str, "str 不应该为 null");
}
}
import org.testng.annotations.Test;
import org.testng.asserts.SoftAssert;
public class SoftAssertionExample {
@Test
public void testSoftAssertions() {
SoftAssert softAssert = new SoftAssert();
int result1 = 2 + 2;
softAssert.assertEquals(result1, 5, "2 + 2 应该等于 5(故意设置错误)");
boolean condition = 5 < 3;
softAssert.assertTrue(condition, "5 应该小于 3(故意设置错误)");
softAssert.assertAll();
}
}
在上述示例中,即使前两个断言失败,测试方法也会继续执行,直到调用assertAll方法时,才会将所有的失败信息一并报告。软断言在一个测试方法中需要进行多个断言的场景下非常有用,可以一次性获取所有的断言失败信息,方便调试。
在 TestNG 框架中,testng.xml是测试执行的指挥官,能对测试的执行过程进行灵活且精细的控制。所以在介绍测试执行之前,先来看看testng.xml文件的基本组成。
<suite name="FullTestSuite" parallel="methods" thread-count="3">
<parameter name="baseUrl" value="https://example.com"/>
<test name="SampleTest">
<groups>
<run>
<include name="smoke"/>
<exclude name="slow"/>
run>
groups>
<classes>
<class name="com.example.TestClass1"/>
<class name="com.example.TestClass2"/>
classes>
test>
<test name="AnotherTest">
<classes>
<class name="com.example.TestClass3"/>
classes>
test>
suite>
TestNG 提供了多个注解来管理测试的生命周期,通过这些注解定义其被标注的方法在什么阶段运行。
1. 套件级别注解:作用范围是TestNG中的 < suite >标签
@BeforeSuite:在整个测试套件开始执行之前运行,通常用于执行一些全局的初始化操作,比如数据库连接、配置文件加载等。
@AfterSuite:在整个测试套件执行完毕之后运行,用于进行全局的清理工作,例如关闭数据库连接、释放资源等。
2. 测试级别注解:作用范围是TestNG中的 < test > 标签
@BeforeTest:在 标签内的任何测试开始执行之前运行,该注解可用于对每个 进行独立的初始化。
@AfterTest:在 标签内的所有测试执行完毕之后运行,用于清理测试执行后产生的临时数据或资源。
3. 组级别注解:作用范围是TestNG 中的 < groups > 标签
@BeforeGroups:在< groups >标签内的任何测试用例执行之前运行,用于对特定组的测试用例进行前置准备。
@AfterGroups:在< groups >标签内的所有测试用例执行完毕之后运行,用于清理特定组测试用例执行后产生的资源。
4. 类级别注解:作用范围是 Java 的类
@BeforeClass:在当前测试类的第一个测试方法执行之前运行,通常用于对测试类进行初始化,比如创建测试对象等。
@AfterClass:在当前测试类的所有测试方法执行完毕之后运行,用于清理测试类执行过程中产生的资源。
5. 方法级别注解:作用范围是 每个测试方法
@BeforeMethod:在每个测试方法执行之前运行,可用于为每个测试方法提供独立的初始化环境。
@AfterMethod:在每个测试方法执行完毕之后运行,用于清理每个测试方法执行后产生的临时数据。
6. 测试方法注解
@Test:用于标记一个方法为测试方法,TestNG 会执行被该注解标记的方法。
当执行一个 TestNG 测试时,上述注解的执行顺序如下:
@BeforeSuite
@BeforeTest
@BeforeGroups
@BeforeClass
@BeforeMethod
@Test
@AfterMethod
@AfterClass
@AfterGroups
@AfterTest
@AfterSuite
1. 我们可以使用 groups 属性对测试用例进行分组,然后通过 testng.xml 文件来筛选执行特定组的测试用例。
以下是一个示例:
import org.testng.annotations.Test;
public class TestCaseGroupingExample {
@Test(groups = "smoke")
public void testSmoke() {
System.out.println("Executing smoke test");
}
@Test(groups = "regression")
public void testRegression() {
System.out.println("Executing regression test");
}
}
以下是对应的 testng.xml 文件, testng.xml 文件指定只执行 smoke 组的测试用例:
DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="GroupSuite">
<test name="GroupTest">
<groups>
<run>
<include name="smoke"/>
run>
groups>
<classes>
<class name="com.example.TestCaseGroupingExample"/>
classes>
test>
suite>
2. 我们可以使用@test注解的 priority 属性来指定测试用例的执行优先级。priority 属性是一个整数,数值越小,优先级越高。
以下是一个示例:
import org.testng.annotations.Test;
public class PriorityExample {
@Test(priority = 2)
public void testMethod2() {
System.out.println("Executing test method 2");
}
@Test(priority = 1)
public void testMethod1() {
System.out.println("Executing test method 1");
}
@Test(priority = 3)
public void testMethod3() {
System.out.println("Executing test method 3");
}
}
在上述示例中,testMethod1 的优先级最高,会最先执行,接着是 testMethod2,最后是 testMethod3。如果不指定 priority 属性,TestNG 会按照方法的字母顺序执行测试用例。
TestNG 支持并行执行测试用例,我们可以通过配置 testng.xml 文件来实现。以下是一个示例 testng.xml 文件:
DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="ParallelSuite" parallel="methods" thread-count="2">
<test name="ParallelTest">
<classes>
<class name="com.example.TestClass1"/>
<class name="com.example.TestClass2"/>
classes>
test>
suite>
在上述配置中,parallel=“methods” 表示并行执行测试方法,thread-count=“2” 表示使用 2 个线程进行并行执行。
TestNG 会自动生成测试报告,默认情况下,测试报告位于 test-output 目录下。我们可以使用不同的插件来生成更美观、详细的测试报告,如 Allure 报告。以下是配置 Allure 报告的步骤:
<dependency>
<groupId>io.qameta.alluregroupId>
<artifactId>allure-testngartifactId>
<version>2.21.0version>
dependency>
xml
DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="AllureSuite">
<listeners>
<listener class-name="io.qameta.allure.testng.AllureTestNg"/>
listeners>
<test name="AllureTest">
<classes>
<class name="com.example.TestClass"/>
classes>
test>
suite>
allure generate allure-results --clean -o allure-report
allure open allure-report
TestNG 是一个功能强大、灵活的 Java 测试框架,它提供了丰富的测试用例管理、断言、用例执行和测试报告能力。通过本文的介绍和示例,相信新手开发者已经对 TestNG 的主要能力和使用方法有了初步的了解。在实际项目中,合理运用 TestNG 的这些能力,可以提高测试效率,确保软件质量。
希望本文对你有所帮助,祝你在测试工作中取得更好的成果!