zoukankan      html  css  js  c++  java
  • ☕【Java技术指南】「TestNG专题」单元测试框架之TestNG使用教程指南(上)

    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测试用例的步骤

    • 使用 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放置在其他文件夹,不和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");
      }
    }
    
    运行结果如下:
    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 = {"方法名称"})
    

    特定顺序执行测试用例(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>
    

    我们还可以定义参数在级别。假设我们已经定义在两个级别myName,在这种情况下,常规的作用域规则适用。这意味着,任何类里面标签将查看值参数定义在,而testng.xml文件中的类的其余部分将看到定义在中值

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

    现在,运行testng.xml,其中将运行parameterTest方法。TestNG的将试图找到一个命名myName的第一标签的参数,然后,如果它不能找到它,它会搜索包围在的标签。

    验证输出。

    Parameterized value is : manisha
     
    ===============================================
    Suite1
    Total tests run: 1, Failures: 0, Skips: 0
    ===============================================
    
    数据驱动(@DataProvider)
    • 当你需要通过复杂的参数或参数需要创建从Java(复杂的对象,对象读取属性文件或数据库等..),在这种情况下,可以将参数传递使用数据提供者。数据提供者@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 true
    6 false
    19 true
    22 false
    23 true
     
    ===============================================
    Suite1
    Total 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
     
    ===============================================
    Suite1
    Total 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:UsersAdministratorAppDataLocalTemp	estng-eclipse--754789457	estng-customsuite.xml
    
    PASSED: 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忽略测试

    有时候我们写的用例没准备好,或者该次测试不想运行此用例,那么删掉显然不明智,那么就可以通过注解@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 case2
    PASSED: 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: 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)
    

    未完待续

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

    极限就是为了超越而存在的
  • 相关阅读:
    CodeForces 681D Gifts by the List (树上DFS)
    UVa 12342 Tax Calculator (水题,纳税)
    CodeForces 681C Heap Operations (模拟题,优先队列)
    CodeForces 682C Alyona and the Tree (树上DFS)
    CodeForces 682B Alyona and Mex (题意水题)
    CodeForces 682A Alyona and Numbers (水题,数学)
    Virtualizing memory type
    页面跳转
    PHP Misc. 函数
    PHP 5 Math 函数
  • 原文地址:https://www.cnblogs.com/liboware/p/15196384.html
Copyright © 2011-2022 走看看