TestNG 介绍
TestNG 是 Java 中的一个测试框架, 类似于 JUnit 和 NUnit, 功能都差不多, 只是功能更加强大,使用也更方便。详细使用说明请参考官方链接:https://testng.org/doc/index.html
TestNG 安装
<dependency> <groupId>org.testng</groupId> <artifactId>testng</artifactId> <version>6.10</version> <scope>test</scope></dependency>
复制代码
TestNG 的优点
漂亮的 HTML 格式测试报告
支持并发测试
参数化测试更简单
支持输出日志
支持更多功能的注解
编写 TestNG 测试用例的步骤
TestNG 的简单用例
Java 直接运行
package com.demo.test.testng;import org.testng.annotations.Test;public class NewTest { @Test public void testFunction() { System.out.println("this is new test"); Assert.assertTrue(true); }}
复制代码
xml 方式运行
由于我将 xml 放置在其他文件夹,不和 class 放在一个文件夹,所以需要修改 xml,如下所示:
<?xml version="1.0" encoding="UTF-8"?><suite name="Suite" parallel="false"> <test name="Test"> <classes> <class name="com.demo.test.testng.NewTest"/> </classes> </test> <!-- Test --></suite> <!-- Suite -->
复制代码
TestNG 的注解
TestNG 支持多种注解,可以进行各种组合,如下进行简单的说明
@BeforeSuite > @BeforeTest > @BeforeMethod > @Test > @AfterMethod > @AfterTest > @AfterSuite
如上列表中的 @Factory、@Linsteners 这两个是不常用的;前十个注解看起来不太容易区分,顺序不太容易看明白,以如下范例做简单说明,代码
import org.testng.Assert;import org.testng.annotations.AfterClass;import org.testng.annotations.AfterGroups;import org.testng.annotations.AfterMethod;import org.testng.annotations.AfterSuite;import org.testng.annotations.AfterTest;import org.testng.annotations.BeforeClass;import org.testng.annotations.BeforeGroups;import org.testng.annotations.BeforeMethod;import org.testng.annotations.BeforeSuite;import org.testng.annotations.BeforeTest;import org.testng.annotations.Test;
public class NewTest {
@Test(groups="group1") public void test1() { System.out.println("test1 from group1"); Assert.assertTrue(true); } @Test(groups="group1") public void test11() { System.out.println("test11 from group1"); Assert.assertTrue(true); } @Test(groups="group2") public void test2() { System.out.println("test2 from group2"); Assert.assertTrue(true); } @BeforeTest public void beforeTest() { System.out.println("beforeTest"); } @AfterTest public void afterTest() { System.out.println("afterTest"); } @BeforeClass public void beforeClass() { System.out.println("beforeClass"); } @AfterClass public void afterClass() { System.out.println("afterClass"); } @BeforeSuite public void beforeSuite() { System.out.println("beforeSuite"); } @AfterSuite public void afterSuite() { System.out.println("afterSuite"); } //只对group1有效,即test1和test11 @BeforeGroups(groups="group1") public void beforeGroups() { System.out.println("beforeGroups"); } //只对group1有效,即test1和test11 @AfterGroups(groups="group1") public void afterGroups() { System.out.println("afterGroups"); } @BeforeMethod public void beforeMethod() { System.out.println("beforeMethod"); } @AfterMethod public void afterMethod() { System.out.println("afterMethod"); }}
复制代码
运行结果如下:
beforeSuitebeforeTestbeforeClassbeforeGroupsbeforeMethodtest1 from group1afterMethodbeforeMethodtest11 from group1afterMethodafterGroupsbeforeMethodtest2 from group2afterMethodafterClassafterTestPASSED: test1PASSED: test11PASSED: test2=============================================== Default test Tests run: 3, Failures: 0, Skips: 0===============================================afterSuite
复制代码
如何创建 TestNG 测试集合?
如何配置 testNG.xml 文件?
<suite name = "TestNG Suite"> //自定义的测试集合名称 <test name = "test1"> //自定义的测试名称 <classes> //定义被运行的测试类 <class name = "cn.gloryroad.FirstTestNGDemo" /> //测试类的路径 <class name = "cn.gloryroad.NewTest" /> </classes> </test> </suite>
复制代码
测试用例的分组(group)
执行组分组配置如下:
<suite name = "TestNG Suite"> <test name = "Grouping"> <groups> <run> <include name = "动物" /> </run> </groups> <classes> <class name = "cn.gloryroad.Grouping"/> </classes> </test></suite>
复制代码
执行多组分组时配置如下(两种形式都可以):
<suite name = "TestNG Suite"> <test name = "Grouping"> <groups> <run> <include name = "动物" /> //name分组名称 <include name = "人" /> </run> </groups> <classes> <class name = "cn.gloryroad.Grouping"/> </classes> </test></suite>
复制代码
依赖测试(dependsOnMethod)
被依赖的方法优先于此方法执行
@Test(dependsOnMethod = {"方法名称"})
复制代码
特定顺序执行测试用例(priority)
按照数字大小顺序优先执行,优先执行 1,然后是 2…
@Test(priority = 0/1/2/3/4/…)
复制代码
如何跳过某个测试方法(enabled = false)
@Test(priority = 0/1… , enabled = false)
复制代码
执行结束后,在测试报告中显示跳过的测试用例数,例如 skip=1
创建测试案例类
创建一个 Java 测试类 ParameterizedTest1.java.
测试方法 parameterTest()添加到测试类。此方法需要一个字符串作为输入参数。
添加注释 @Parameters("myName") 到此方法。该参数将被传递 testng.xml,在下一步我们将看到一个值。
创建 Java 类文件名 ParameterizedTest1.java
import org.testng.annotations.Parameters;import org.testng.annotations.Test; public class ParameterizedTest1 { @Test @Parameters("myName") public void parameterTest(String myName) { System.out.println("Parameterized value is : " + myName); }}
复制代码
创建 TESTNG.XML
创建 testng.xml C:\ > TestNG_WORKSPACE 执行测试案例
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" > <suite name="Suite1"> <test name="test1"> <parameter name="myName" value="manisha"/> <classes> <class name="ParameterizedTest1" /> </classes> </test> </suite>
复制代码
我们还可以定义参数在<suite>级别。假设我们已经定义在两个<suite>和<test>级别 myName,在这种情况下,常规的作用域规则适用。这意味着,任何类里面<test>标签将查看值参数定义在<test>,而 testng.xml 文件中的类的其余部分将看到定义在<suite>中值
编译使用 javac 的测试用例类。
javac ParameterizedTest1.java
复制代码
现在,运行 testng.xml,其中将运行 parameterTest 方法。TestNG 的将试图找到一个命名 myName 的第一<test>标签的参数,然后,如果它不能找到它,它会搜索包围在的<suit>标签。
验证输出。
Parameterized value is : manisha ===============================================Suite1Total tests run: 1, Failures: 0, Skips: 0===============================================
复制代码
数据驱动(@DataProvider)
让我们看看下面的例子使用数据提供者。第一个例子是 @DataProvider 的使用 Vector,String 或 Integer 作为参数,第二个例子是关于 @DataProvider 的使用对象作为参数。
实例 1
在这里 @DataProvider 通过整数和布尔参数。
创建 Java 类
创建一个 java 类 PrimeNumberChecker.java。这个类检查,如果是素数。
public class PrimeNumberChecker { public Boolean validate(final Integer primeNumber) { for (int i = 2; i < (primeNumber / 2); i++) { if (primeNumber % i == 0) { return false; } } return true; } }
复制代码
创建测试案例类
创建一个 Java 测试类 ParamTestWithDataProvider1.java.
定义方法 primeNumbers(),其定义为 DataProvider 使用注释。此方法返回的对象数组的数组。
测试方法 testPrimeNumberChecker()添加到测试类中。此方法需要一个整数和布尔值作为输入参数。这个方法验证,如果传递的参数是一个素数。
添加注释 @Test(dataProvider = "test1") 到此方法。dataProvider 的属性被映射到"test1".
创建 Java 类文件名 ParamTestWithDataProvider1.java
import org.testng.Assert; import org.testng.annotations.BeforeMethod; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; public class ParamTestWithDataProvider1 {
private PrimeNumberChecker primeNumberChecker;
@BeforeMethod public void initialize() { primeNumberChecker = new PrimeNumberChecker(); } @DataProvider(name = "test1") public static Object[][] primeNumbers() { return new Object[][] { { 2, true }, { 6, false }, { 19, true }, { 22, false }, { 23, true } }; } // This test will run 4 times since we have 5 parameters defined @Test(dataProvider = "test1") public void testPrimeNumberChecker(Integer inputNumber, Boolean expectedResult) { System.out.println(inputNumber + " " + expectedResult); Assert.assertEquals(expectedResult, primeNumberChecker.validate(inputNumber)); } }
复制代码
创建 TESTNG.XML
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" > <suite name="Suite1"> <test name="test1"> <classes> <class name="ParamTestWithDataProvider1" /> </classes> </test> </suite>
复制代码
运行 testng.xml.
验证输出。 2 true6 false19 true22 false23 true ===============================================Suite1Total tests run: 5, Failures: 0, Skips: 0===============================================
复制代码
实例 2
在这里,@DataProvider 传递对象作为参数。
创建 Java 类
创建一个 Java 类 Bean.java, 对象带有 get/set 方法
public class Bean { private String val; private int i; public Bean(String val, int i){ this.val=val; this.i=i; } public String getVal() { return val; } public void setVal(String val) { this.val = val; } public int getI() { return i; } public void setI(int i) { this.i = i; }}
复制代码
创建测试案例类
创建一个 Java 测试类 ParamTestWithDataProvider2.java.
定义方法 primeNumbers(),其定义为 DataProvider 使用注释。此方法返回的对象数组的数组。
添加测试类中测试方法 TestMethod()。此方法需要对象的 bean 作为参数。
添加注释 @Test(dataProvider = "test1") 到此方法. dataProvider 属性被映射到 "test1".
创建 Java 类文件名 ParamTestWithDataProvider2.java
import org.testng.annotations.DataProvider; import org.testng.annotations.Test; public class ParamTestWithDataProvider2 { @DataProvider(name = "test1") public static Object[][] primeNumbers() { return new Object[][] { { new Bean("hi I am the bean", 111) } }; } @Test(dataProvider = "test1") public void testMethod(Bean myBean) { System.out.println(myBean.getVal() + " " + myBean.getI()); } }
复制代码
创建 TESTNG.XML
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" > <suite name="Suite1"> <test name="test1"> <classes> <class name="ParamTestWithDataProvider2" /> </classes> </test> </suite>
复制代码
运行 testng.xml.
hi I am the bean 111 ===============================================Suite1Total tests run: 1, Failures: 0, Skips: 0===============================================
复制代码
测试报告中自定义日志(Reporter.log(“输入自定义内容”)),例如:
@Test(groups = {"人"})
public void student(){
System.out.println("学生方法被调用");
Reporter.log("学生方法自定义日志");
}
复制代码
测试方法使用大全
TestNG 预期异常测试
预期异常测试通过在 @Test 注解后加入预期的 Exception 来进行添加,范例如下所示:
@Test(expectedExceptions = ArithmeticException.class) public void divisionWithException() { int i = 1 / 0; System.out.println("After division the value of i is :"+ i); }
复制代码
运行结果如下:
[RemoteTestNG] detected TestNG version 6.10.0[TestNG] Running: C:\Users\Administrator\AppData\Local\Temp\testng-eclipse--754789457\testng-customsuite.xml
PASSED: divisionWithException
=============================================== Default test Tests run: 1, Failures: 0, Skips: 0===============================================
===============================================Default suiteTotal tests run: 1, Failures: 0, Skips: 0===============================================
[TestNG] Time taken by org.testng.reporters.JUnitReportReporter@55d56113: 0 ms[TestNG] Time taken by org.testng.reporters.SuiteHTMLReporter@1e127982: 0 ms[TestNG] Time taken by org.testng.reporters.jq.Main@6e0e048a: 32 ms[TestNG] Time taken by [FailedReporter passed=0 failed=0 skipped=0]: 0 ms[TestNG] Time taken by org.testng.reporters.XMLReporter@43814d18: 0 ms[TestNG] Time taken by org.testng.reporters.EmailableReporter2@6ebc05a6: 0 ms
复制代码
TestNG 忽略测试
有时候我们写的用例没准备好,或者该次测试不想运行此用例,那么删掉显然不明智,那么就可以通过注解 @Test(enabled = false)来将其忽略掉,此用例就不会运行了,如下范例:
import org.testng.annotations.Test;
public class TestCase1 {
@Test(enabled=false) public void TestNgLearn1() { System.out.println("this is TestNG test case1"); } @Test public void TestNgLearn2() { System.out.println("this is TestNG test case2"); }}
复制代码
运行结果:
this is TestNG test case2PASSED: TestNgLearn2
复制代码
TestNG 超时测试
“超时”表示如果单元测试花费的时间超过指定的毫秒数,那么 TestNG 将会中止它并将其标记为失败。此项常用于性能测试。如下为一个范例:
import org.testng.annotations.Test;
public class TestCase1 {
@Test(timeOut = 5000) // time in mulliseconds public void testThisShouldPass() throws InterruptedException { Thread.sleep(4000); }
@Test(timeOut = 1000) public void testThisShouldFail() { while (true){ // do nothing }
}}
复制代码
结果如下:
PASSED: testThisShouldPassFAILED: testThisShouldFailorg.testng.internal.thread.ThreadTimeoutException: Method com.demo.test.testng.TestCase1.testThisShouldFail() didn't finish within the time-out 1000 at com.demo.test.testng.TestCase1.testThisShouldFail(TestCase1.java:37) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:104) at org.testng.internal.InvokeMethodRunnable.runOne(InvokeMethodRunnable.java:54) at org.testng.internal.InvokeMethodRunnable.run(InvokeMethodRunnable.java:44) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at java.lang.Thread.run(Thread.java:748)
复制代码
未完待续
后续会进行详细的介绍使用
评论