【接口自動化系列】2-走進Java接口測試之測試框架TestNG【7DGroup】

一、簡介:

TestNG 是一個受 JUnit 和 NUnit 啓發的測試框架測試框架,旨在簡化廣泛的測試需求,從單元測試到接口測試。 但引入了一些新功能,使其更強大,更易於使用,例如:

  • 註釋。

  • 在線程池中運行測試,並提供各種可用策略(單線程,多線程等等)

  • 測試的代碼是多線程安全的

  • 靈活的測試配置

  • 支持數據驅動的測試(使用 @DataProvider)

  • 支持參數化

  • 強大的執行模型(不再是 TestSuite)

  • 由各種工具和插件(Eclipse,IDEA,Maven 等)支持。

  • 嵌入 BeanShell 腳本以獲得更大的靈活性

  • 用於運行時和日誌記錄的缺省 JDK 函數(無依賴項)

  • 應用服務器測試的依賴方法

  • TestNG旨在涵蓋所有類別的測試:單元,接口,端到端,集成等......

 

二、快速 Demo

編寫測試通常需要三個步驟:

  • 編寫測試代碼插入TestNG註釋。

  • 在 testng.xml 中添加有關測試的信息(例如:類名,要運行的組等)。

  • 運行TestNG。

一個快速示例

package com.test.tools;

import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;

/**
 * @author dumts
 * @date 2020/7/2 7:44 下午
 */
public class Test1 {
    @BeforeClass
    public void setUp(){
        //初始化內容塊,實例化時調用此代碼
        System.out.println("test=====");
    }

    @Test(groups = {"fast"})
    public void test1(){
        System.out.println("test fast");
    }

    @Test(groups = {"slow"})
    public void test2(){
        System.out.println("test slow");
    }
}


在構建測試類之後和運行任何測試方法之前,將調用 方法 setUp()。在這個例子中,我們將快速運行組,所以 aFastTest() 將被調用,而 aSlowTest() 將被跳過。

注意事項:

  • 無需擴展類或實現接口。

  • 儘管上面的示例使用了JUnit 約定,但我們的方法可以被稱爲任何名稱,它是告訴 TestNG 它們是什麼的註釋。

  • 測試方法可以屬於一個或多個組。

  • 將測試類編譯到構建目錄後,可以使用命令行,ant 任務(如下所示)或 XML 文件調用測試

<project default="test">

<path id="cp">
    <pathelement location="lib/testng-testng-5.13.1.jar"/>
    <pathelement location="build"/>
</path>


<taskdef name="testng" classpathref="cp"
    classname="org.testng.TestNGAntTask" />
<target name="test">
    <testng classpathref="cp" groups="fast">
        <classfileset dir="build" includes="example1/*.class"/>
    </testng>
</target>

</project>

使用用 ant 調用它

c:> ant
Buildfile: build.xml

test:
[testng] Fast test
[testng] ===============================================
[testng] Suite for Command line test
[testng] Total tests run: 1, Failures: 0, Skips: 0
[testng] ===============================================

BUILD SUCCESSFUL
Total time: 4 seconds

然後,可以瀏覽測試結果:

start test-output\index.html (on Windows)

本文檔中使用的概念如下:

  • 測試套件由一個 XML 文件表示。它可以包含一個或多個測試,並由 < suite > 標記定義。

  • 測試由 < test > 表示,可以包含一個或多個 TestNG 類。

  • TestNG 類是一個包含至少一個 TestNG 註釋的 Java 類。它由 < class > 標記表示,可以包含一個或多個測試方法。

  • 測試方法是由源中的 @Test 註釋的 Java 方法。

可以通過 @BeforeXXX 和 @AfterXXX 註釋來配置 TestNG 測試,該註釋允許在某個點之前和之後執行某些 Java 邏輯,這些點是上面列出的項目之一。

 

三、基本註釋

以下是 TestNG 中可用註釋及其屬性的概述表。

註解

描述

@BeforeSuite

在該套件的所有測試都運行在註釋的方法之前,僅運行一次。

@AfterSuite

在該套件的所有測試都運行在註釋方法之後,僅運行一次。

@BeforeClass

在調用當前類的第一個測試方法之前運行,註釋方法僅運行一次。

@AfterClass

在調用當前類的第一個測試方法之後運行,註釋方法僅運行一次

@BeforeTest

註釋的方法將在屬於 < test > 標籤內的類的所有測試方法運行之前運行。

@AfterTest

註釋的方法將在屬於< test >標籤內的類的所有測試方法運行之後運行。

@BeforeGroups

配置方法將在之前運行組列表。 此方法保證在調用屬於這些組中的任何一個的第一個測試方法之前不久運行。

@AfterGroups

此配置方法將在之後運行組列表。該方法保證在調用屬於任何這些組的最後一個測試方法之後不久運行。

@BeforeMethod

註釋方法將在每個測試方法之前運行。

@AfterMethod

註釋方法將在每個測試方法之後運行。

alwaysRun

對於 before 方法(beforeSuite,beforeTest,beforeTestClass和beforeTestMethod,但不是beforeGroups):如果設置爲true,則無論它屬於哪個組,都將運行此配置方法。 對於after方法(afterSuite,afterClass,...):如果設置爲true,即使先前調用的一個或多個方法失敗或被跳過,也將運行此配置方法。

dependsOnGroups

此方法所依賴的組列表。

dependsOnMethods

此方法所依賴的方法列表。

enabled

是否啓用此類 / 方法上的方法。

groups

此類/方法所屬的組列表。

inheritGroups

如果爲true,則此方法將屬於類級別的@Test註釋中指定的組。

onlyForGroups

僅適用於 @BeforeMethod 和 @AfterMethod。如果指定,則僅當相應的測試方法屬於列出的組之一時,纔會調用此 setup / teardown 方法。

當放置在 TestNG 類的超類上時,上述註釋也將被繼承。例如,這對於在公共超類中集中多個測試類的測試設置非常有用。

在這種情況下,TestNG保證“@Before”方法以繼承順序執行(首先是最高超類,然後是繼承),而“@After”方法則按相反的順序執行(向上繼承鏈)。

@dataProvider: 將方法標記爲爲測試方法提供數據。 記一種方法來提供測試方法的數據。 註釋方法必須返回一個Object [] [],其中每個Object [] 可以被分配給測試方法的參數列表。 要從該DataProvider接收數據的 @Test 方法需要使用與此註釋名稱相等的dataProvider名稱。

屬性 描述
name 此數據提供者的名稱。如果未提供,則此數據提供程序的名稱將自動設置爲方法的名稱。
parallel 如果設置爲 true,則使用此數據提供程序生成的測試將並行運行。默認值爲 false。

@Factory: 將方法標記爲工廠,返回將由 TestNG 用作 Test 類的對象。該方法必須返回 Object []。

@Listeners :在測試類上定義偵聽器。

屬性 描述
value 擴展org.testng.ITestNGListener的類數組。

@Parameters: 描述如何將參數傳遞給 @Test 方法。

屬性 描述
value 用於填充此方法參數的變量列表。

@Test : 將類或方法標記爲測試的一部分。

屬性 描述
alwaysRun 如果設置爲 true,則即使依賴於失敗的方法,也始終會運行此測試方法。
dataProvider 此測試方法的數據提供程序的名稱。
dataProviderClass 查找數據提供程序的類。如果未指定,則將在當前測試方法的類或其基類之一上查找數據提供程序。如果指定了此屬性,則數據提供程序方法必須在指定的類上是靜態的。
dependsOnGroups 此方法所依賴的組列表。
dependsOnMethods 此方法所依賴的方法列表。
description 此方法的描述。
enabled 是否啓用此類/方法上的方法。
expectedExceptions 預期測試方法拋出的異常列表。如果拋出此列表中沒有異常或不同異常,則此測試將標記爲失敗。
groups 此類/方法所屬的組列表。
invocationCount 應該調用此方法的次數。
invocationTimeOut 此測試應對所有調用計數的累計時間應採用的最大毫秒數。如果未指定 invocationCount,則將忽略此屬性。
priority 此測試方法的優先級。將優先安排較低的優先事項。
successPercentage 此方法預期的成功百分比
singleThreaded 如果設置爲 true,則此測試類上的所有方法都保證在同一個線程中運行,即使當前正在使用 parallel =“methods” 運行測試。此屬性只能在類級別使用,如果在方法級別使用,它將被忽略。注意:此屬性曾被稱爲順序(現已棄用)。
timeOut 此測試應採用的最大毫秒數。
threadPoolSize 此方法的線程池大小。該方法將從 invocationCount 指定的多個線程調用。
   

注意:如果未指定 invocationCount,則忽略此屬性

常用斷言方法

爲了方便判斷測試用例是否執行成功,TestNG 特定提供了一個斷言類,裏面含有多種形式的斷言方法。

方法 描述
assertTrue 判斷是否爲 true
assertFalse 判斷是否爲 false
assertSame 判斷引用地址是否相同
assertNotSame 判斷引用地址是否不相同
assertNull 判斷是否爲 null
assertNotNull 判斷是否不爲 null
assertEquals 判斷是否相等,Object 類型的對象需要實現 hashCode 及 equals 方法
assertNotEquals 判斷是否不相等
assertNoOrder 判斷忽略順序相等

testng.xml

您可以通過幾種不同的方式調用 TestNG:

  • 使用 testng.xml 文件

  • ant

  • maven,如 mvn clean test-U-Dxml=xmlFileName

  • 命令行

本節介紹 testng.xml 的格式(您將在下面找到有關ant和命令行的文檔)。

這是一個示例 testng.xml 文件

<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >

<suite name="Suite1" verbose="1" >
    <test name="Nopackage" >
        <classes>
            <class name="NoPackageTest" />
        </classes>
    </test>

    <test name="Regression1">
        <classes>
            <class name="test.sample.ParameterSample"/>
            <class name="test.sample.ParameterTest"/>
        </classes>
    </test>
</suite>

指定包名

<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >

<suite name="Suite1" verbose="1" >
    <test name="Regression1"   >
        <packages>
            <package name="test.sample" />
        </packages>
    </test>

</suite>

在此示例中,TestNG 將執行包 test.sample 中的所有類, 並僅保留具有 TestNG 註釋的類。

指定要包含和排除的組和方法

<test name="Regression1">
    <groups>
        <run>
            <exclude name="brokenTests"  />
            <include name="checkinTests"  />
        </run>
    </groups>

    <classes>
        <class name="test.IndividualMethodsTest">
            <methods>
                <include name="testMethod" />
            </methods>
        </class>
    </classes>
</test>

在 testng.xml 中定義新組,並在屬性中指定其他詳細信息,例如是否並行運行測試,使用多少線程,是否運行測試等等... 默認情況下,TestNG 將按照 XML 文件中的順序運行測試。如果希望此文件中列出的類和方法以不可預測的順序運行,請將 preserve-order 屬性設置爲 false
<test name="Regression1" preserve-order="false">
    <classes>
        <class name="test.Test1">
            <methods>
                <include name="m1" />
                 <include name="m2" />
            </methods>
        </class>
        <class name="test.Test2" />
    </classes>
</test>

 

四、測試方法,測試類和測試組

測試方法

測試方法用 @Test 註釋。除非在 testng.xml 中將 allow-return-values 設置爲 true,否則將忽略使用 @Test 註釋恰好返回值的方法:

<suite allow-return-values="true">or<test allow-return-values="true">

測試組

TestNG 允許執行復雜的測試方法分組。不僅可以聲明方法屬於組,還可以指定包含其他組的組。然後可以調用 TestNG 並要求包括一組特定的組(或正則表達式),同時排除另一組。這爲分區測試提供了最大的靈活性,如果想要連續運行兩組不同的測試,則不需要重新編譯任何內容。

組在 testng.xml 文件中指定,可以在 < test > 或 < suite > 標記下找到。標記中指定的組適用於下面的所有 < test > 標記。請注意,組在這些標記中是累積的:如果在< suite >中指定組 “a”,在< test >中指定“b” ,則將包括“a”和“b”。

例如,至少有兩類測試是很常見的

  • 辦理登機手續的測試。應在提交新代碼之前運行這些測試。它們通常應該很快,並確保沒有基本功能被破壞。

  • 功能測試。這些測試應涵蓋軟件的所有功能,並且每天至少運行一次,儘管理想情況下希望連續運行它們。

通常,簽入測試是功能測試的子集。TestNG 允許以非常直觀的方式使用測試組指定。例如,可以通過整個測試類屬於 “functest” 組來構建測試,另外還有一些方法屬於 “checkintest” 組:

public class Test1 {

    @Test(groups = { "functest", "checkintest" })
    public void testMethod1() {
    }


    @Test(groups = {"functest", "checkintest"} )
    public void testMethod2() {
    }


    @Test(groups = { "functest" })
    public void testMethod3() {
    }

}

TestNG 調用

<test name="Test1">
    <groups>
        <run>
            <include name="functest"/>
        </run>
    </groups>
    
    <classes>
        <class name="example1.Test1"/>
    </classes>

</test>

將運行該類中的所有測試方法,而使用 checkintest 調用它將只運行 testMethod1() 和 testMethod2()。這是另一個例子,這次使用正則表達式。假設某些測試方法不應該在 Linux 上運行,測試將如下所示

@Test

public class Test1 {
    @Test(groups = { "windows.checkintest" })
    public void testWindowsOnly() {
    }

    @Test(groups = {"linux.checkintest"} )
    public void testLinuxOnly() {
    }
    
    @Test(groups = { "windows.functest" )
    public void testWindowsToo() {
    }

}


可以使用以下 testng.xml 僅啓動 Windows 方法:


 
  1. <test name="Test1">

  2.  <groups>

  3.    <run>

  4.      <include name="windows.*"/>

  5.    </run>

  6.  </groups>

  7.  

  8.  <classes>

  9.    <class name="example1.Test1"/>

  10.  </classes>

  11. </test>

注意:TestNG 使用正則表達式,而不是 wildmats

方法組 還可以排除或包含單個方法


 
  1. <test name="Test1">

  2.  <classes>

  3.    <class name="example1.Test1">

  4.      <methods>

  5.        <include name=".*enabledTestMethod.*"/>

  6.        <exclude name=".*brokenTestMethod.*"/>

  7.      </methods>

  8.     </class>

  9.  </classes>

  10. </test>

這可以派上用來停用單個方法而不必重新編譯任何東西,但是不建議過多地使用這種技術,因爲如果開始重構你的 Java 代碼(正則表達式中使用的正則表達式),它會使你的測試框架崩潰。標籤可能不再符合您的方法)。

羣組

組還可以包括其他組。這些組稱爲 “MetaGroups”。例如,您可能希望定義包含 “checkintest” 和 “functest” 的組 “all”。“functest” 本身將包含 “windows” 和 “linux” 組,而 “checkintest” 將只包含 ”windows“。以下是如何在屬性文件中定義它:


 
  1. <test name="Regression1">

  2.  <groups>

  3.    <define name="functest">

  4.      <include name="windows"/>

  5.      <include name="linux"/>

  6.    </define>

  7.  

  8.    <define name="all">

  9.      <include name="functest"/>

  10.      <include name="checkintest"/>

  11.    </define>

  12.  

  13.    <run>

  14.      <include name="all"/>

  15.    </run>

  16.  </groups>

  17.  

  18.  <classes>

  19.    <class name="test.sample.Test1"/>

  20.  </classes>

  21. </test>

排除組

TestNG 允許包括組以及排除它們。

例如,由於最近的更改而暫時中斷測試通常很常見,而還沒有時間修復破損。但是,確實想要進行功能測試的乾淨運行,因此需要停用這些測試,但請記住需要重新激活它們。 解決此問題的一種簡單方法是創建一個名爲 “broken” 的組,並使這些測試方法屬於它。 例如,在上面的例子中,我知道 testMethod2() 現在已經壞了所以我想禁用它:


 
  1. @Test(groups = {"checkintest", "broken"} )

  2. public void testMethod2() {

  3. }

我現在需要做的就是從運行中排除這個組:


 
  1. <test name="Simple example">

  2.  <groups>

  3.    <run>

  4.      <include name="checkintest"/>

  5.      <exclude name="broken"/>

  6.    </run>

  7.  </groups>

  8.  

  9.  <classes>

  10.    <class name="example1.Test1"/>

  11.  </classes>

  12. </test>

這樣將獲得一個乾淨的測試運行,同時跟蹤哪些測試被破壞,需要稍後修復。

注意:還可以使用 @Test 和 @Before / After 註釋上的 “enabled” 屬性逐個禁用測試。

部分組

可以在類級別定義組,然後在方法級別添加組:


 
  1. @Test(groups = { "checkin-test" })

  2. public class All {

  3.  

  4.  @Test(groups = { "func-test" )

  5.  public void method1() { ... }

  6.  

  7.  public void method2() { ... }

  8. }

在這個類中,method2() 是 “checkin-test” 組的一部分,它在類級定義,而 method1() 屬於 “checkin-test” 和 “func-test”。

參數化

測試方法不必是無參數的。可以在每個測試方法上使用任意數量的參數,並指示 TestNG 使用 @Parameters 註釋傳遞正確的參數。

有兩種方法可以設置這些參數:

  • 使用 testng.xml

  • 以編程方式。

testng.xml 中的參數

如果對參數使用簡單值,則可以在 testng.xml 中指定它們 :


 
  1. @Parameters({ "first-name" })

  2. @Test

  3. public void testSingleString(String firstName) {

  4.  System.out.println("Invoked testString " + firstName);

  5.  assert "Cedric".equals(firstName);

  6. }

在此代碼中,我們指定Java方法的參數 firstName 應該接收名爲 first-name 的 XML 參數的值。 此 XML 參數在 testng.xml 中 定義:


 
  1. <suite name="My suite">

  2.  <parameter name="first-name"  value="Cedric"/>

  3.  <test name="Simple example">

  4.  <-- ... -->

@Before / After 和 @Factory 註釋可以使用相同的技術:


 
  1. @Parameters({ "datasource", "jdbcDriver" })

  2. @BeforeMethod

  3. public void beforeTest(String ds, String driver) {

  4.  m_dataSource = ...;                              // 查詢數據源值

  5.  m_jdbcDriver = driver;

  6. }

這次,兩個 Java 參數 ds 和驅動程序將分別接收賦予屬性 datasource 和 jdbc-driver 的值。 可以使用 Optional 註釋將參數聲明爲可選:


 
  1. @Parameters("db")

  2. @Test

  3. public void testNonExistentParameter(@Optional("mysql") String db) { ... }

如果在 testng.xml 文件中找不到名爲 “db” 的參數,則測試方法將接收 @Optional 註釋中指定的默認值:“mysql” 。 在 @Parameters 可以被放置在下列位置:

  • 在任何已經有 @Test,@Before / After 或 @Factory 註釋的方法上。

  • 最多隻有一個測試類的構造函數。在這種情況下,TestNG 將調用此特定構造函數,並在需要實例化測試類時將參數初始化爲 testng.xml 中指定的值。此功能可用於將類中的字段初始化爲測試方法隨後將使用的值。

注意:

  • XML參數按照與註釋中相同的順序映射到 Java 參數,如果數字不匹配,TestNG 將發出錯誤。

  • 參數是作用域的。在 testng.xml 中,您可以在< suite >標記下或< test >下聲明它們 。如果兩個參數具有相同的名稱,則它是< test >中定義的具有優先權的參數。如果您需要指定適用於所有測試的參數並僅爲某些測試覆蓋其值,這將非常方便。

使用 DataProviders 的參數

如果需要傳遞複雜參數或需要從 Java 創建的參數(複雜對象,從屬性文件或數據庫讀取的對象等等),則在 testng.xml 中指定參數可能不夠。在這種情況下,您可以使用數據提供程序提供測試所需的值。數據提供程序是類上的一個方法,它返回一組對象數組。此方法使用 @DataProvider 註釋:


 
  1. //This method will provide data to any test method that declares that its Data Provider

  2. //is named "test1"

  3. @DataProvider(name = "test1")

  4. public Object[][] createData1() {

  5. return new Object[][] {

  6.   { "Cedric", new Integer(36) },

  7.   { "Anne", new Integer(37)},

  8. };

  9. }

  10.  

  11. //This test method declares that its data should be supplied by the Data Provider

  12. //named "test1"

  13. @Test(dataProvider = "test1")

  14. public void verifyData1(String n1, Integer n2) {

  15. System.out.println(n1 + " " + n2);

  16. }

將打印


 
  1. Cedric 36

  2. Anne 37

@Test 方法指定了與數據提供數據提供程序屬性。此名稱必須對應於 使用匹配名稱的 @DataProvider(name =“...”)註釋的同一類上的方法。

默認情況下,將在當前測試類或其中一個基類中查找數據提供程序。如果要將數據提供程序放在不同的類中,則需要使用靜態方法或具有非 arg 構造函數的類,並指定可在 dataProviderClass 屬性中找到的類:


 
  1. public class StaticProvider {

  2.  @DataProvider(name = "create")

  3.  public static Object[][] createData() {

  4.    return new Object[][] {

  5.      new Object[] { new Integer(42) }

  6.    };

  7.  }

  8. }

  9.  

  10. public class MyTest {

  11.  @Test(dataProvider = "create", dataProviderClass = StaticProvider.class)

  12.  public void test(Integer n) {

  13.    // ...

  14.  }

  15. }

數據提供者也支持注入。TestNG 將使用測試上下文進行注射。Data Provider方法可以返回以下兩種類型之一: 一組對象數組(Object [] []),其中第一個維度的大小是調用測試方法的次數,第二個維度大小包含必須與測試的參數類型兼容的對象數組方法。這是上述示例所示的情況。

 一個迭代< Object [] [] > 與Object [] []的唯一區別在於 Iterator 允許您懶惰地創建測試數據。TestNG 將調用迭代器,然後使用此迭代器返回的參數逐個調用測試方法。如果您有許多參數集要傳遞給方法,並且您不想預先創建所有參數集,則此功能特別有用。 以下是此功能的示例:


 
  1. @DataProvider(name = "test1")

  2. public Iterator<Object[]> createData() {

  3.  return new MyIterator(DATA);

  4. }

如果您將 @DataProvider 聲明爲將 java.lang.reflect.Method作爲第一個參數,則 TestNG 將爲此第一個參數傳遞當前測試方法。

當多個測試方法使用相同的 @DataProvider 並且您希望它根據爲其提供數據的測試方法返回不同的值時,這尤其有用。 例如,以下代碼在其 @DataProvider 中打印測試方法的名稱:


 
  1. @DataProvider(name = "dp")

  2. public Object[][] createData(Method m) {

  3.  System.out.println(m.getName());  // print test method name

  4.  return new Object[][] { new Object[] { "Cedric" }};

  5. }

  6.  

  7. @Test(dataProvider = "dp")

  8. public void test1(String s) {

  9. }

  10.  

  11. @Test(dataProvider = "dp")

  12. public void test2(String s) {

  13. }

因此將顯示:


 
  1. test1

  2. test2

數據提供程序可以與並行屬性並行運行:


 
  1. @DataProvider(parallel = true)

  2. // ...

從 XML 文件運行的並行數據提供程序共享相同的線程池,默認情況下大小爲 10。您可以在 XML 文件的< suite >標記中修改此值:


 
  1. <suite name="Suite1" data-provider-thread-count="20" >

如果要在不同的線程池中運行幾個特定的數據提供程序,則需要從其他XML文件運行它們。

依賴性

有時,您需要按特定順序調用測試方法。這裏有一些例子: 在運行更多測試方法之前,確保已完成併成功執行一定數量的測試方法。 要初始化測試,同時希望這個初始化方法也是測試方法(使用 @Before / After 標記的方法不會成爲最終報告的一部分)。 TestNG 允許您使用註釋或 XML 指定依賴項。

帶註釋的依賴關係

您可以使用屬性 dependsOnMethods 或 dependsOnGroups,對發現的@Test註解。

有兩種依賴關係:

  • 硬依賴。您依賴的所有方法必須運行併成功運行。如果您的依賴項中至少發生一次故障,則不會在報告中調用並將其標記爲 SKIP。

  • 軟依賴。您將始終在您依賴的方法之後運行,即使其中一些方法失敗了。當您只是想確保您的測試方法按特定順序運行時,這很有用,但它們的成功並不真正取決於其他人的成功。通過在 @Test 註釋中添加 “alwaysRun = true” 來獲得軟依賴關係。

以下是硬依賴的示例:


 
  1. @Test

  2. public void serverStartedOk() {}

  3.  

  4. @Test(dependsOnMethods = { "serverStartedOk" })

  5. public void method1() {}

在此示例中,method1() 聲明爲依賴於方法 serverStartedOk() ,這保證始終首先調用 serverStartedOk() 。

您還可以擁有依賴於整個組的方法:


 
  1. @Test(groups = { "init" })

  2. public void serverStartedOk() {}

  3.  

  4. @Test(groups = { "init" })

  5. public void initEnvironment() {}

  6.  

  7. @Test(dependsOnGroups = { "init.*" })

  8. public void method1() {}

在此示例中,method1()聲明爲依賴於與正則表達式“init。*”匹配的任何組,這保證了方法serverStartedOk() 和initEnvironment()將始終在method1()之前調用。

注意:如前所述,對於屬於同一組的方法,調用順序不保證在測試運行中是相同的。

如果依賴的方法失敗並且您對它有一個硬依賴( alwaysRun = false,這是默認值),依賴它的方法不會 標記爲 FAIL 而是標記爲 SKIP。跳過的方法將在最終報告中報告(在 HTML中顏色既不是紅色也不是綠色),這很重要,因爲跳過的方法不一定是失敗的。

無論 dependsOnGroups 和 dependsOnMethods 接受正則表達式作爲參數。對於 dependsOnMethods,如果您依賴於碰巧有多個重載版本的方法,則將調用所有重載的方法。如果您只想調用其中一個重載方法,則應使用 dependsOnGroups。

默認情況下,依賴方法按類分組。

例如,如果方法b()依賴於方法a(),並且您有幾個包含這些方法的類的實例(因爲數據提供程序的工廠),則調用順序如下:


 
  1. a(1)

  2. a(2)

  3. b(2)

  4. b(2)

在所有實例調用其 a() 方法之前, TestNG 不會運行 b() 。 

在某些情況下可能不希望出現這種情況,例如測試登錄和退出各個國家/地區的Web瀏覽器。在這種情況下,您需要以下訂購:


 
  1. signIn("us")

  2. signOut("us")

  3. signIn("uk")

  4. signOut("uk")

對於此排序,可以逐個實例使用 XML 屬性。此屬性在 < suite > 或 < test > 上有效:


 
  1.  <suite name="Factory" group-by-instances="true">

  2. or

  3.  <test name="Factory" group-by-instances="true">

XML 中的依賴關係

可以在 testng.xml 文件中指定組依賴項。使用 < dependencies > 標記來實現此目的:


 
  1. <test name="My suite">

  2.  <groups>

  3.    <dependencies>

  4.      <group name="c" depends-on="a  b" />

  5.      <group name="z" depends-on="c" />

  6.    </dependencies>

  7.  </groups>

  8. </test>

以上所述 < depends-on > 屬性包含一個以空格分隔的組列表。

工廠

工廠允許動態創建測試。 例如,假設要創建一個將多次訪問網站上的頁面的測試方法,並且希望使用不同的值調用它:


 
  1. public class TestWebServer {

  2.  @Test(parameters = { "number-of-times" })

  3.  public void accessPage(int numberOfTimes) {

  4.    while (numberOfTimes-- > 0) {

  5.     // access the web page

  6.    }

  7.  }

  8. }


 
  1. <test name="T1">

  2.  <parameter name="number-of-times" value="10"/>

  3.  <classes>

  4.    <class name= "TestWebServer" />

  5.  </classes>

  6. </test>

  7.  

  8. <test name="T2">

  9.  <parameter name="number-of-times" value="20"/>

  10.  <classes>

  11.    <class name= "TestWebServer"/>

  12.  </classes>

  13. </test>

  14.  

  15. <test name="T3">

  16.  <parameter name="number-of-times" value="30"/>

  17.  <classes>

  18.    <class name= "TestWebServer"/>

  19.  </classes>

  20. </test>

這很快就無法管理,所以你應該使用工廠


 
  1. public class WebTestFactory {

  2.  @Factory

  3.  public Object[] createInstances() {

  4.   Object[] result = new Object[10];

  5.   for (int i = 0; i < 10; i++) {

  6.      result[i] = new WebTest(i * 10);

  7.    }

  8.    return result;

  9.  }

  10. }

現在新的測試類


 
  1. public class WebTest {

  2.  private int m_numberOfTimes;

  3.  public WebTest(int numberOfTimes) {

  4.    m_numberOfTimes = numberOfTimes;

  5.  }

  6.  

  7.  @Test

  8.  public void testServer() {

  9.   for (int i = 0; i < m_numberOfTimes; i++) {

  10.     // access the web page

  11.    }

  12.  }

  13. }

您的 testng.xml 只需要引用包含工廠方法的類,因爲測試實例本身將在運行時創建


 
  1. <class name="WebTestFactory" />

或者,如果以編程方式構建測試套件實例,則可以按照與測試相同的方式添加工廠


 
  1. TestNG testNG = new TestNG();

  2. testNG.setTestClasses(WebTestFactory.class);

  3. testNG.run();

工廠方法可以像 @Test 和 @Before / After 一樣接收參數,它必須返回 Object [] 。返回的對象可以是任何類(不一定是與工廠類相同的類),它們甚至不需要包含 TestNG 註釋(在這種情況下,它們將被 TestNG 忽略)。

工廠也可以與數據提供者一起使用,您可以通過將 @Factory 註釋放在常規方法或構造函數上來利用此功能。 以下是構造函數工廠的示例:


 
  1. @Factory(dataProvider = "dp")

  2. public FactoryDataProviderSampleTest(int n) {

  3.  super(n);

  4. }

  5.  

  6. @DataProvider

  7. static public Object[][] dp() {

  8.  return new Object[][] {

  9.    new Object[] { 41 },

  10.    new Object[] { 42 },

  11.  };

  12. }

該示例將使TestNG創建兩個測試類,使用值41調用構造函數,另一個調用42。

忽略測試

TestNG允許您忽略所有@Test方法:

  • 一個類(或)

  • 特定包(或)

  • 一個包及其所有子包中

使用新註釋 @Ignore。 在方法級別使用 @Ignore 註釋在功能上等同於 @Test(enabled = false)。這是一個示例,顯示如何忽略類中的所有測試。


 
  1. import org.testng.annotations.Ignore;

  2. import org.testng.annotations.Test;

  3.  

  4. @Ignore

  5. public class TestcaseSample {

  6.  

  7.    @Test

  8.    public void testMethod1() {

  9.    }

  10.  

  11.    @Test

  12.    public void testMethod2() {

  13.    }

  14. }

該 @Ignore 註釋具有比個人更高的優先級 @Test 方法的註釋。當 @Ignore 放在一個類上時,該類中的所有測試都將被禁用。 

要忽略特定包中的所有測試,只需創建 package-info.java 並將 @Ignore 註釋添加到其中。這是一個示例:


 
  1. @Ignore

  2. package com.testng.master;

  3.  

  4. import org.testng.annotations.Ignore;

這會導致 com.testng.master 包及其所有子包中的所有 @Test 方法都被忽略。

並行和超時

可以指示 TestNG 以各種方式在單獨的線程中運行測試。

並行套件

如果您運行多個套件文件(例如“ java org.testng.TestNGtestng1.xml testng2.xml”)並且希望每個套件都在一個單獨的線程中運行,這將非常有用。您可以使用以下命令行標誌來指定線程池的大小:


 
  1. java org.testng.TestNG -suitethreadpoolsize 3 testng1.xml testng2.xml testng3.xml

相應的 ant 任務名稱是 suitethreadpoolsize。

並行測試,類和方法

在平行於 < suite > 屬性標籤可以採取以下值之一:


 
  1. <suite name="My suite" parallel="methods" thread-count="5">

  2. <suite name="My suite" parallel="tests" thread-count="5">

  3. <suite name="My suite" parallel="classes" thread-count="5">

  4. <suite name="My suite" parallel="instances" thread-count="5">

  • parallel =“methods”:TestNG將在不同的線程中運行所有測試方法。依賴方法也將在單獨的線程中運行,但它們將遵循您指定的順序。

  • parallel =“tests”:TestNG將在同一個線程中運行相同 < test > 標記中的所有方法,但每個< test > 標記將位於一個單獨的線程中。這允許您在同一個 < test > 中對所有非線程安全的類進行分組,並保證它們將在同一個線程中運行,同時利用 TestNG 使用盡可能多的線程來運行測試。

  • parallel =“classes”:TestNG 將在同一個線程中運行同一個類中的所有方法,但每個類將在一個單獨的線程中運行

  • parallel =“instances”:TestNG 將在同一個線程中運行同一實例中的所有方法,但兩個不同實例上的兩個方法將在不同的線程中運行。

此外,屬性 thread-count 允許指定應爲此執行分配的線程數。 

注意:@Test 屬性 timeOut 在並行和非並行模式下都有效。

您還可以指定應從不同的線程調用 @Test 方法。您可以使用 threadPoolSize 屬性來實現此結果:


 
  1. @Test(threadPoolSize = 3, invocationCount = 10,  timeOut = 10000)

  2. public void testServer() {

在此示例中,函數 testServer 將從三個不同的線程調用十次。此外,超時十秒可確保所有線程都不會永久阻塞此線程。

重新運行失敗的測試

每次測試在套件中失敗時,TestNG 都會在輸出目錄中創建一個名爲 testng-failed.xml 的文件。此 XML 文件包含僅重新運行失敗的這些方法的必要信息,使您可以快速重現故障,而無需運行整個測試。因此,典型的會話將如下所示:


 
  1. java -classpath testng.jar;%CLASSPATH% org.testng.TestNG -d test-outputs testng.xml

  2. java -classpath testng.jar;%CLASSPATH% org.testng.TestNG -d test-outputs test-outputs\testng-failed.xml

請注意, testng-failed.xml 將包含所有必需的依賴方法,以便您可以保證在沒有任何 SKIP 故障的情況下運行失敗的方法。

有時,您可能希望TestNG在失敗時自動重試測試。在這些情況下,您可以使用重試分析器。當您將重試分析器綁定到測試時,TestNG會自動調用重試分析器以確定TestNG是否可以再次重試測試用例,以嘗試查看現在剛剛失敗的測試是否通過。

以下是使用重試分析器的方法: 構建 org.testng.IRetryAnalyzer 接口的實現 將此實現綁定到 @Test 註釋,例如 @Test(retryAnalyzer=LocalRetry.class) 以下是重試分析器的示例實現,重試測試最多三次。


 
  1. import org.testng.IRetryAnalyzer;

  2. import org.testng.ITestResult;

  3.  

  4. public class MyRetry implements IRetryAnalyzer {

  5.  

  6.  private int retryCount = 0;

  7.  private static final int maxRetryCount = 3;

  8.  

  9.  @Override

  10.  public boolean retry(ITestResult result) {

  11.    if (retryCount < maxRetryCount) {

  12.      retryCount++;

  13.      return true;

  14.    }

  15.    return false;

  16.  }

  17. }

  18. import org.testng.Assert;

  19. import org.testng.annotations.Test;

  20.  

  21. public class TestclassSample {

  22.  

  23.  @Test(retryAnalyzer = MyRetry.class)

  24.  public void test2() {

  25.    Assert.fail();

  26.  }

  27. }

YAML文件

TestNG 支持 YAM L作爲指定套件文件的替代方法。例如,以下 XML 文件:


 
  1. <suite name="SingleSuite" verbose="2" thread-count="4">

  2.  

  3.  <parameter name="n" value="42" />

  4.  

  5.  <test name="Regression2">

  6.    <groups>

  7.      <run>

  8.        <exclude name="broken" />

  9.      </run>

  10.    </groups>

  11.  

  12.    <classes>

  13.      <class name="test.listeners.ResultEndMillisTest" />

  14.    </classes>

  15.  </test>

  16. </suite>

這是它的YAML版本:


 
  1. name: SingleSuite

  2. threadCount: 4

  3. parameters: { n: 42 }

  4.  

  5. tests:

  6.  - name: Regression2

  7.    parameters: { count: 10 }

  8.    excludedGroups: [ broken ]

  9.    classes:

  10.      - test.listeners.ResultEndMillisTest

這是 TestNG 自己的套件文件,以及它的 YAML 對應文件。 您可能會發現 YAML 文件格式更易於閱讀和維護。TestNG Eclipse 插件也可以識別 YAML 文件。

注意: 默認情況下,TestNG 不會將 YAML 相關庫引入您的類路徑。因此,根據您的構建系統(Gradle / Maven),您需要在構建文件中添加對 YAML 庫的顯式引用。

例如,如果使用的是 Maven,則需要在 pom.xml文件中添加如下依賴項:


 
  1. <dependency>

  2.  <groupid>org.yaml</groupid>

  3.  <artifactid>snakeyaml</artifactid>

  4.  <version>1.23</version>

  5. </dependency>

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章