初識TestNg測試框架和reportng

一、TestNg官網

https://testng.org/doc/documentation-main.html

二、TestNg特性

TestNg集成了JUnit和NUnit測試框架,也引入了新功能,使其功能更強大,更易於使用。具體TestNg的特性有如下幾點:
1.註解
2.基於線程池運行測試
3.多線程運行代碼是安全的
4.靈活的測試配置
5.支持數據驅動測試 @DataProvider
6.強大的執行模型,不需要較多的TestSuite
7.支持Eclipse、maven、IDEA等
8、可以嵌入BeanShell

三、運行一個TestNg測試case

1.Write the business logic of your test and insert TestNG annotations in your code.
2.Add the information about your test (e.g. the class name, the groups you wish to run, etc...) in a testng.xml file or in build.xml.
3.Run TestNG.

四、maven工程pom.xml 配置

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

五、詳解TestNg中註解(非全部)

在這裏插入圖片描述

5.1 特殊注意點:

1、@DataProvider註解下name屬性如果不指定,則方法名被自動指定為數據驅動名,關聯到@Test註解下的dataprovider屬性;如果指定name屬性,則指定名即為數據驅動名。
2、@DataProvider註解下的parallel屬性默認為false,即數據驅動非並行;如果設置為true意思為並行,即至少2個線程以上,不建議使用並行,具體要根據實際業務場景定。
3、@Test註解下的dataprovider屬性與@DataProvider註解下name屬性保持一致;數據驅動返回類型一定是一個二維數組型,二維數組有n列,則被關聯的@Test方法就有n個入參,二維數組有m行,則@Test方法就運行m次。
4、@Test註解下的dataproviderclass屬性稱為數據驅動測試類。測試類下有多個static屬性的數據驅動方法。如果業務場景中存在多個數據源,則需要定義數據驅動類。
5、@Test註解下的groups和dependsOnGroups是組合使用的。一個@Test方法下可以有多個groups分組,寫法是:
	@Test(groups={"peopel","students"})
dependsOnGroups屬性下可以添加多個groups。且@Test註釋的方法名需要人工干預排序。這兩個屬性可以解決方法之間的依賴。
6、@Test註解下dependsOnMethods屬性也可以解決方法之間的依賴,可以添加依賴多個方法。且@Test註釋的方法名需要人工干預排序。
7、@Test註解下priority屬性可以控制方法的運行順序,屬性值越小則優先運行。也可以解決方法之間的依賴問題。
8、@Test註解下enable屬性,設置為true則方法運行;設置為false則跳過該方法。
9、其中@Test註解下的invocationCount、invocationTimeOut、threadPoolSize、timeOut、successPercentage這些屬性多少和性能沾點邊,可以組合使用,分別代表的含義是:
	invocationCount 指定的@Test方法運行的次數;
	invocationTimeOut 需要和invocationCount一起使用,否則不生效。指在規定的invocationTimeOut時間內完成invocationCount運行次數,否則報超時錯誤;
	threadPoolSize 需要和invocationCount一起使用,否則不生效。用threadPoolSize的值的線程數量完成invocationCount指定的運行次數;
	timeOut 指@Test方法最長運行耗時時間,若在規定時間範圍內沒有完成運行,則報超時錯誤;
	successPercentage 指@Test方法運行成功百分比,建議和invocationCount一起使用。

5.2 示例

1、數據驅動類
class StaticProvider{
	  @DataProvider(name = "111")
	  public static Object[][] dp1() {
		  Object[][] data = {{1,"a","wwww"},{2,"b","eeeeeee"},{3,"c","kkkkkk"}};
		  return data;
	  }
	  
	  @DataProvider(name = "222")
	  public static Object[][] dp2() {
		  Object[][] data = {{11,"a","wwww"},{2,"b","eeeeeee"},{3,"c","kkkkkk"}};
		  return data;
	  }
	  
	  @DataProvider(name = "333")
	  public static Object[][] dp3() {
		  Object[][] data = {{111,"a","wwww"},{2,"b","eeeeeee"},{3,"c","kkkkkk"}};
		  return data;
	  }
}
public class TestProvider {
  @Test(dataProviderClass=StaticProvider.class,dataProvider = "222")
  public void f(Integer n, String s, String k) {
	  System.out.println(n + " " + k);
  }
2、groups和dependsOnGroups
public class TestDependsGroup {
  @Test(groups={"init1"})
  public void a_serverInitStatus() {
	  System.out.println("1");
  }
  @Test(groups={"init2"})
  public void b_serverStarStatus(){
	  System.out.println("2");
  }
  @Test(groups={"init3"})
  public void c_serverAfterStatus(){
	  System.out.println("3");
  }
  @Test(dependsOnGroups={"init3", "init1"}) 
  public void d_monitor(){
	  System.out.println("4");
  }
  /**
   * 總結
   * 1、方法的執行順序根據方法名首字母先後順序執行;
   * 2、groups中寫的是啥組,dependsOnGroups就寫啥組;
   * 3、解決接口測試用例之間的接口依賴問題。
   */
}
3、dependsOnMethods
public class TestDependsOnMethods {
  @Test
  public void a_login() {
	  System.out.println("1");
  }
  @Test
  public void b_addShoppingCart(){
	  System.out.println("2");
  }
  @Test(dependsOnMethods={"a_login", "b_addShoppingCart"})
  public void c_addOrder(){
	  System.out.println("3");
  }
  /**
   * 總結
   * 1、可以解決用例前後依賴問題;
   * 2、測試方法運行順序受方法名的首字母排序影響,正序排列;
   * 3、dependsOnMethods中的名稱要和依賴的方法名保持一致。
   */
}
4、invocationCount
public class TestInvocationCount {
  @Test(invocationCount=1000, invocationTimeOut=10000, threadPoolSize=4, successPercentage=100)
  public void f() {
	  System.out.println("1");
  }
}
5、priority
public class TestPriority {
  @Test(priority=1)
  public void f() {
	  System.out.println("2");
  }
  @Test(priority=2, enabled=false, description="測試case的描述")
  public void a() throws Exception{
	  System.out.println("1");
  }
  /**
   * 總結:
   * priority 屬性的優先級要高於方法名首字母順序的優先級
   */
}
6、執行順序
public class TestRun {
  @Test(dataProvider = "dp")
  public void f(Integer n, String s, String k) {
	  System.out.println("@test");
  }
  @BeforeMethod
  public void beforeMethod() {
	  System.out.println("@BeforeMethod");
  }

  @AfterMethod
  public void afterMethod() {
	  System.out.println("@AfterMethod");
  }


  @DataProvider
  public Object[][] dp() {
    System.out.println("@DataProvider");
    Object[][] data = {{11,"a","wwww"},{2,"b","eeeeeee"},{3,"c","kkkkkk"}};
    return data;
  }
  @BeforeClass
  public void beforeClass() {
	  System.out.println("@BeforeClass");
  }

  @AfterClass
  public void afterClass() {
	  System.out.println("@AfterClass");
  }

  @BeforeTest
  public void beforeTest() {
	  System.out.println("@BeforeTest");
  }

  @AfterTest
  public void afterTest() {
	  System.out.println("@AfterTest");
  }

  @BeforeSuite
  public void beforeSuite() {
	  System.out.println("@BeforeSuite");
  }

  @AfterSuite
  public void afterSuite() {
	  System.out.println("@AfterSuite");
  }

}
運行結果如下:
[RemoteTestNG] detected TestNG version 6.14.3
[TestNGContentHandler] [WARN] It is strongly recommended to add "<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >" at the top of your file, otherwise TestNG may fail or not work as expected.
@BeforeSuite
@BeforeTest
@BeforeClass
@DataProvider
@BeforeMethod
@test
@AfterMethod
@BeforeMethod
@test
@AfterMethod
@BeforeMethod
@test
@AfterMethod
@AfterClass
@AfterTest
PASSED: f(11, "a", "wwww")
PASSED: f(2, "b", "eeeeeee")
PASSED: f(3, "c", "kkkkkk")

===============================================
    Default test
    Tests run: 3, Failures: 0, Skips: 0
===============================================

@AfterSuite

===============================================
Default suite
Total tests run: 3, Failures: 0, Skips: 0
===============================================

六、testng.xml文件配置

6.1 name解析
<?xml version="1.0" encoding="UTF-8"?>
<suite parallel="false" name="defaultsuit">
  <test name="Test">
    <classes>
      <class name="com.xxxxx.testng.TestRun"/>
    </classes>
  </test> <!-- Test -->
</suite> <!-- Suite -->

在這裏插入圖片描述

6.2 suite下parallel屬性 解析
首先明確suite下的parallel屬性是針對classes下的所有java文件(中的@Test方法,即測試case)而言的,如果只有一個java類且只有一個測試方法,則就沒有並行的意義。官方解釋如下:

在這裏插入圖片描述

<suite name="My suite" parallel="methods" thread-count="5">
以methods為實例去併發執行,每個方法一個線程([email protected]測試方法數);
<suite name="My suite" parallel="tests" thread-count="5">
以tests為實例去併發執行,所有方法使用一個線程,TestNg線程;
<suite name="My suite" parallel="classes" thread-count="5">
以classes為實例去併發執行,同一個類下的所有方法用同一個線程,不同類使用不同線程;
<suite name="My suite" parallel="instances" thread-count="5">
以classes為實例去併發執行,同一個類下的所有方法用同一個線程,不同類使用不同線程(同上面);
6.3 執行配置
基於classes配置;
基於packages;
排除類下的某些方法,關鍵詞exclude;

七、reportng替換testng報告

7.1 pom.xml 配置
<dependency>
    <groupId>org.uncommons</groupId>
    <artifactId>reportng</artifactId>
    <version>1.1.4</version>
    <scope>test</scope>
    <exclusions>
      <exclusion>
        <groupId>org.testng</groupId>
        <artifactId>testng</artifactId>
      </exclusion>
    </exclusions>
 </dependency>
7.2 testng.xml文件配置選項
<?xml version="1.0" encoding="UTF-8"?>
<suite name="xxxxxxx" parallel="false">
  <test name="interfaceAuto">
    <classes>
      <class name="com.xxxxxxxxxxxx.interf.test.TestUtil"/>
    </classes>
    <listeners>
    	<listener class-name="org.uncommons.reportng.HTMLReporter" />
    	<listener class-name="org.uncommons.reportng.JUnitXMLReporter" />
    </listeners>
  </test> <!-- Test -->
</suite> <!-- Suite -->
7.3 reportng 輸出的報告路徑
當前工程下\test-output\html文件夾\index.html,使用瀏覽器打開即可。

八、testng.xml參數化

8.1 testng.xml 文件配置
<?xml version="1.0" encoding="UTF-8"?>
<suite name="xxx" parallel="false">

  <parameter name="filename" value="D:\\TestData\\app_testcase.xlsx" /> 

  <test name="interfaceAuto">
    <classes>
      <class name="com.xxxxxx.interf.test.TestUtil"/>
    </classes>
    <listeners>
    	<listener class-name="org.uncommons.reportng.HTMLReporter" />
    	<listener class-name="org.uncommons.reportng.JUnitXMLReporter" />
    </listeners>
  </test> <!-- Test -->
</suite> <!-- Suite -->
8.2 測試類中優化
private String filePath = null;
@Parameters({"filename"})
@BeforeTest
public void beforeTest(String filename){
    this.filePath =filename;
}