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

学向勤中得,萤窗万卷书。这篇文章主要讲述Java技术指南「TestNG专题」单元测试框架之TestNG使用教程指南(下)相关的知识,希望能为你提供帮助。
承接上文
分组测试
这个group说明可以是在单个的测试方法上,也可以在class上,只要具有同样的group名称都会在同一个group中,同时group名称可以有多个,类似@Test(groups = {" mysql" ," database" })这种,范例如下:
一个测试文件NewTest.class:

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"); }@BeforeGroups(groups="group1") public void beforeGroups() { System.out.println("beforeGroups"); }@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"); } }

另一个TestCase1.class:
@Test(groups= "group2") 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"); } }

xml如下:
< ?xml version="1.0" encoding="UTF-8"?> < suite name="Suite" parallel="false"> < test name="Test"> < groups> < include name="group1"> < /incloud> < include name="group2"> < /incloud> < /groups> < classes> < class name="com.demo.test.testng.NewTest"/> < class name="com.demo.test.testng.TestCase1"/> < /classes> < /test> < !-- Test --> < /suite> < !-- Suite -->

运行结果如下:
beforeSuite beforeTest beforeClass beforeGroups beforeMethod test1 from group1 afterMethod beforeMethod test11 from group1 afterMethod afterGroups beforeMethod test2 from group2 afterMethod afterClass this is TestNG test case2 afterTest afterSuite

如上所示,先运行了group1的两个用例,再运行group2的两条用例;
注意在xml标识group,需要将要运行的group加进来,同时还要将被标识这些group的class也加进来,不被加进去的不会运行;
分suite测试
  • 测试套件是用于测试软件程序的行为或一组行为的测试用例的集合。 在TestNG中,我们无法在测试源代码中定义一个套件,但它可以由一个XML文件表示,因为套件是执行的功能。 它还允许灵活配置要运行的测试。
  • 套件可以包含一个或多个测试,并由< suite> 标记定义。< suite> 是testng.xml的根标记。 它描述了一个测试套件,它又由几个< test> 部分组成。
下表列出了< suite> 接受的所有定义的合法属性。
依赖测试TestNG允许指定依赖关系:
  • 在@Test注释中使用属性dependsOnMethods
  • 在@Test注释中使用属性dependsOnGroups
  • hard依赖:默认为此依赖方式,即其所有依赖的methods或者groups必须全部pass,否则被标识依赖的类或者方法将会被略过,在报告中标识为skip,如后面的范例所示,此为默认的依赖方式;
  • soft依赖:此方式下,其依赖的方法或者组有不是全部pass也不会影响被标识依赖的类或者方法的运行,注意如果使用此方式,则依赖者和被依赖者之间必须不存在成功失败的因果关系,否则会导致用例失败。
  • 此方法在注解中需要加入alwaysRun=true即可,如@Test(dependsOnMethods= {" TestNgLearn1" }, alwaysRun=true);
范例一,被依赖方法pass:
public class TestCase1 { @Test(enabled=true) public void TestNgLearn1() { System.out.println("this is TestNG test case1"); } @Test(dependsOnMethods= {"TestNgLearn1"}) public void TestNgLearn2() { System.out.println("this is TestNG test case2"); } }

运行结果:
this is TestNG test case1 this is TestNG test case2 PASSED: TestNgLearn1 PASSED: TestNgLearn2

范例二,被依赖方法fail:
public class TestCase1 { @Test(enabled=true) public void TestNgLearn1() { System.out.println("this is TestNG test case1"); Assert.assertFalse(true); } @Test(dependsOnMethods= {"TestNgLearn1"}) public void TestNgLearn2() { System.out.println("this is TestNG test case2"); } }

结果:
this is TestNG test case1 FAILED: TestNgLearn1 junit.framework.AssertionFailedError at junit.framework.Assert.fail(Assert.java:47) at junit.framework.Assert.assertTrue(Assert.java:20) at junit.framework.Assert.assertFalse(Assert.java:34) at junit.framework.Assert.assertFalse(Assert.java:41) at com.demo.test.testng.TestCase1.TestNgLearn1(TestCase1.java:26) 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.Invoker.invokeMethod(Invoker.java:645) at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:851) at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1177) at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:129) at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:112) at org.testng.TestRunner.privateRun(TestRunner.java:756) at org.testng.TestRunner.run(TestRunner.java:610) at org.testng.SuiteRunner.runTest(SuiteRunner.java:387) at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:382) at org.testng.SuiteRunner.privateRun(SuiteRunner.java:340) at org.testng.SuiteRunner.run(SuiteRunner.java:289) at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52) at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86) at org.testng.TestNG.runSuitesSequentially(TestNG.java:1293) at org.testng.TestNG.runSuitesLocally(TestNG.java:1218) at org.testng.TestNG.runSuites(TestNG.java:1133) at org.testng.TestNG.run(TestNG.java:1104) at org.testng.remote.AbstractRemoteTestNG.run(AbstractRemoteTestNG.java:114) at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:251) at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:77)SKIPPED: TestNgLearn2

范例三、group依赖:
@Test(groups = { "init" }) public void serverStartedOk() {}@Test(groups = { "init" }) public void initEnvironment() {}@Test(dependsOnGroups = { "init.*" }) public void method1() {}

参数化测试TestNG可以通过两种不同的方式将参数直接传递给测试方法:
使用testng.xml 使用数据提供者下面分别介绍两种传参方式:
  1. 使用textng.xml传送参数
范例代码如下:
public class TestCase1 { @Test(enabled=true) @Parameters({"param1", "param2"}) public void TestNgLearn1(String param1, int param2) { System.out.println("this is TestNG test case1, and param1 is:"+param1+"; param2 is:"+param2); Assert.assertFalse(false); } @Test(dependsOnMethods= {"TestNgLearn1"}) public void TestNgLearn2() { System.out.println("this is TestNG test case2"); } }

xml配置:
< ?xml version="1.0" encoding="UTF-8"?> < suite name="Suite" parallel="false"> < test name="Test"> < parameter name="param1" value="https://www.songbingjia.com/android/1011111" /> < parameter name="param2" value="https://www.songbingjia.com/android/10" /> < classes> < class name="com.demo.test.testng.TestCase1"/> < /classes> < /test> < !-- Test --> < /suite> < !-- Suite -->

运行xml,结果如下:
this is TestNG test case1, and param1 is:1011111; param2 is:10 this is TestNG test case2=============================================== Suite Total tests run: 2, Failures: 0, Skips: 0 ===============================================

使用@DataProvider传递参数代码如下:
public class TestCase1 { @DataProvider(name = "provideNumbers") public Object[][] provideData() { return new Object[][] { { 10, 20 }, { 100, 110 }, { 200, 210 } }; } @Test(dataProvider = "provideNumbers") public void TestNgLearn1(int param1, int param2) { System.out.println("this is TestNG test case1, and param1 is:"+param1+"; param2 is:"+param2); Assert.assertFalse(false); } @Test(dependsOnMethods= {"TestNgLearn1"}) public void TestNgLearn2() { System.out.println("this is TestNG test case2"); } }

运行此class,结果为:
this is TestNG test case1, and param1 is:10; param2 is:20 this is TestNG test case1, and param1 is:100; param2 is:110 this is TestNG test case1, and param1 is:200; param2 is:210 this is TestNG test case2 PASSED: TestNgLearn1(10, 20) PASSED: TestNgLearn1(100, 110) PASSED: TestNgLearn1(200, 210) PASSED: TestNgLearn2

XML配置文件说明suite标签
  1. name属性
  1. verbose属性
  1. parallel属性
  • 此属性是指代运行方式,默认为none,即串行运行方式;并行执行方法包括如下几种,下面做分别说明:
    • methods:方法层级,若为此值,则该suite下所有的测试方法都将进行多线程,即测试用例级别的多线程。如果用例之间有依赖,则执行顺序会按照设定的依赖来运行;
      < suite name="My suite" parallel="methods" thread-count="5">

    • tests:TestNG将在同一线程中运行相同的< Test> 标签中的所有方法,每个< test> 标签都将处于一个单独的线程中,这允许您将不是线程安全的所有类分组在同一个< test> 中,并保证它们都将在同一个线程中运行,同时利用TestNG使用尽可能多的线程运行测试。
      < suite name="My suite" parallel="tests" thread-count="5">

    • classes:类级别并发,即TestNG会将该suite下每个class都将在单独的线程中运行,同一个class下的所有用例都将在同一个线程中运行;
      < suite name="My suite" parallel="classes" thread-count="5">

    • instances:实例级别,即TestNG将在同一线程中运行同一实例中的所有方法,两个不同实例上的两个方法将在不同的线程中运行。
      < suite name="My suite" parallel="instances" thread-count="5">

  1. thread-count属性
  1. annotations属性
  1. time-out属性
  1. group-by-instances属性
  1. preserve-order属性
2、test标签
此标签无特别意义,其下可以包括多个标签,如groups、classes等,如下介绍下几种书写方式:
选择一个包中的全部测试脚本(包含子包)
< test name = "allTestsInAPackage" > < packages> < package name = "whole.path.to.package.* /> < /packages> < /test>

< test name = "allTestsInAClass" > < classes> < class name="whole.path.to.package.className /> < /classes> < /test>

< test name = "aFewTestsFromAClass" > < classes> < class name="whole.path.to.package.className > < methods> < include name = "firstMethod" /> < include name = "secondMethod" /> < include name = "thirdMethod" /> < /methods> < /class> < /classes> < /test>

group标签此标签必然是在< test> 标签下的,用于标识那些组会被用于测试或者被排除在测试之外,其同级必然要包含一个< classes> 标签或者< pakages> 标签,用于指定groups来自于哪些包或者类;
如下即为包含一个group,排除一个group的例子:
< groups> < run> < include name = "includedGroupName" /> < exclude name = "excludedGroupName" /> < /run> < /groups>

高级应用:
< test name="Regression1"> < groups> < define name="functest"> < include name="windows"/> < include name="linux"/> < /define> < define name="all"> < include name="functest"/> < include name="checkintest"/> < /define> < run> < include name="all"/> < /run> < /groups> < classes> < class name="test.sample.Test1"/> < /classes> < /test>

其他其他的话就是测试脚本的选择了,有三种方式:
选择一个包
< packages> < package name = "packageName" /> < /packages>

选择一个类
< classes> < class name = "className" /> < /classes>

选择一个方法
< classes> < class name = "className" /> < methods> < include name = "methodName" /> < /methods> < /class> < /classes>

【Java技术指南「TestNG专题」单元测试框架之TestNG使用教程指南(下)】这里也支持正则表达式,例如:
< test name="Test1"> < classes> < class name="example1.Test1"> < methods> < include name=".*enabledTestMethod.*"/> < exclude name=".*brokenTestMethod.*"/> < /methods> < /class> < /classes> < /test>


    推荐阅读