Java技术指南「TestNG专题」单元测试框架之TestNG使用教程指南(上)

【Java技术指南「TestNG专题」单元测试框架之TestNG使用教程指南(上)】莫问天涯路几重,轻衫侧帽且从容。这篇文章主要讲述Java技术指南「TestNG专题」单元测试框架之TestNG使用教程指南(上)相关的知识,希望能为你提供帮助。
TestNG介绍
TestNG安装

< dependency> < groupId> org.testng< /groupId> < artifactId> testng< /artifactId> < version> 6.10< /version> < scope> test< /scope> < /dependency>

TestNG的优点
  • 漂亮的html格式测试报告
  • 支持并发测试
  • 参数化测试更简单
  • 支持输出日志
  • 支持更多功能的注解
编写TestNG测试用例的步骤
  • 使用 Eclipse生成TestNG的测试程序框架
  • 在生成的程序框架中编写测试代码逻辑
  • 根据测试代码逻辑,插入TestNG注解标签
  • 配置Testng.xml文件,设定测试类、测试方法、测试分组的执行信息
  • 执行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 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的注解如上列表中的@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"); } }

运行结果如下:
beforeSuite beforeTest beforeClass beforeGroups beforeMethod test1 from group1 afterMethod beforeMethod test11 from group1 afterMethod afterGroups beforeMethod test2 from group2 afterMethod afterClass afterTest PASSED: test1 PASSED: test11 PASSED: test2 =============================================== Default test Tests run: 3, Failures: 0, Skips: 0 =============================================== afterSuite

如何创建TestNG测试集合?
  • 在自动化测试的执行过程中,通常会产生批量运行多个测试用例的需求,此需求称为运行测试集合(Test Suite)
  • TestNG的测试用例可以是相互独立的,也可以按照特定的顺序来执行(配置TestNG.xml)
如何配置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 = {"方法名称"})

按照数字大小顺序优先执行,优先执行1,然后是2…
@Test(priority = 0/1/2/3/4/…)

@Test(priority = 0/1… , enabled = false)

创建测试案例类
  • 创建一个Java测试类 ParameterizedTest1.java.
  • 测试方法parameterTest()添加到测试类。此方法需要一个字符串作为输入参数。
  • 添加注释 @Parameters(" myName" ) 到此方法。该参数将被传递testng.xml,在下一步我们将看到一个值。
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
< ?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="https://www.songbingjia.com/android/manisha"/> < classes> < class name="ParameterizedTest1" /> < /classes> < /test> < /suite>

编译使用javac的测试用例类。
javac ParameterizedTest1.java

验证输出。
Parameterized value is : manisha=============================================== Suite1 Total tests run: 1, Failures: 0, Skips: 0 ===============================================

数据驱动(@DataProvider)
  • 当你需要通过复杂的参数或参数需要创建从Java(复杂的对象,对象读取属性文件或数据库等..),在这种情况下,可以将参数传递使用数据提供者。数据提供者@DataProvider的批注的方法。
  • 这个注解只有一个字符串属性:它的名字。如果不提供名称,数据提供者的名称会自动默认方法的名称。数据提供者返回一个对象数组。
让我们看看下面的例子使用数据提供者。第一个例子是@DataProvider的使用Vector,String或Integer 作为参数,第二个例子是关于@DataProvider 的使用对象作为参数。
实例 1在这里 @DataProvider 通过整数和布尔参数。
创建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 true 6 false 19 true 22 false 23 true=============================================== Suite1 Total tests run: 5, Failures: 0, Skips: 0 ===============================================

实例 2创建Java类
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" .
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 < ?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=============================================== Suite1 Total tests run: 1, Failures: 0, Skips: 0 ===============================================

public void student(){
System.out.println(" 学生方法被调用" );
Reporter.log(" 学生方法自定义日志" );
}
------------#### 测试方法使用大全##### TestNG预期异常测试> 预期异常测试通过在@Test注解后加入预期的Exception来进行添加,范例如下所示:```java @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.xmlPASSED: divisionWithException=============================================== Default test Tests run: 1, Failures: 0, Skips: 0 ============================================================================================== Default suite Total 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忽略测试
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 case2 PASSED: TestNgLearn2

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: testThisShouldPass FAILED: testThisShouldFail org.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)

未完待续后续会进行详细的介绍使用

    推荐阅读