TestNG簡單的學習-TestNG運行

轉載:http://topmanopensource.iteye.com/blog/1983735html

TestNG簡單的學習-TestNG運行java

文檔來自官方地址:mysql

http://testng.org/doc/documentation-main.html#testng-listenerslinux

 

 1. 介紹
    TestNG是一個設計用來簡化普遍的測試需求的測試框架,從單元測試(隔離測試一個類)到集成測試(測試由有多個類多個包甚至多個外部框架組成的整個系統,例如運用服務器)。web

    編寫一個測試的過程有三個典型步驟:正則表達式

    * 編寫測試的 業務邏輯並在代碼中插入TestNG annotation
    * 將測試信息添加到testng.xml文件或者build.xml中
    * 運行TestNGsql

在歡迎頁面上能夠找到快速入門示例。shell

下面是這篇文檔使用的概念:數據庫

    * suite由xml文件描述。它包含一個或多個測試並被定義爲<suite>標籤
    * test由<test>描述幷包含一個或者多個TestNG類
    * TestNG類是包含至少一個TestNG annotation的java類,由<class>標籤描述幷包含一個或多個測試方法
    * 測試方法是源文件中帶有@Testd註釋的java方法編程

    TestNG測試能夠被@BeforeXXX 和 @AfterXXX annotations配置,允許在特定點的先後執行一些java邏輯,這些點上面已經列出。

這份手冊的剩餘部分將講述如下內容:

    * 全部的annotation列表並帶有簡短說明,爲TestNG的多種功能性提供參考, 你可能須要參考爲每一個annotation提供的代碼片斷來學習細節。

     * testng.xml文件描述,它的語法和若是指定它。
    * 多個特性的詳細列表和怎樣結合annotation和testng.xml來使用它們

*******************************************************************************

注:上面的內容很簡短,可是請注意其中的一些細節。

1. TestNG是一個設計用來簡化普遍的測試需求的測試框架,從單元測試到集成測試
    這個是TestNG設計的出發點,不只僅是單元測試,並且能夠用於集成測試。設計目標的不一樣,對比junit的只適合用於單元測試,TestNG無疑走的更遠。
    能夠用於集成測試,這個特性是我選擇TestNG的最重要的緣由。

2. 測試的過程的三個典型步驟,注意和junit(4.0)相比,多了一個將測試信息添加到testng.xml文件或者build.xml
    測試信息尤爲是測試數據再也不寫死在測試代碼中,好處就是修改測試數據時不須要修改代碼/編譯了,從而有助於將測試人員引入單元測試/集成測試。

3. 基本概念,相比junit的TestCase/TestSuite,TestNG有suite/test/test method三個級別,即將test/test method明確區分開了。
    junit中的TestCase將test/test method混合,比較容易讓人概念不清晰,尤爲是新手。

2 - Annotation

這裏是TestNG中用到的annotation的快速預覽,還有它們的屬性。


@BeforeSuite:        被註釋的方法將在全部測試運行前運行
@AfterSuite:        被註釋的方法將在全部測試運行後運行
@BeforeTest:        被註釋的方法將在測試運行前運行
@AfterTest:        被註釋的方法將在測試運行後運行
@BeforeGroups:        被配置的方法將在列表中的gourp前運行。這個方法保證在第一個屬於這些組的測試方法調用前當即執行。
@AfterGroups:        被配置的方法將在列表中的gourp後運行。這個方法保證在最後一個屬於這些組的測試方法調用後當即執行。
@BeforeClass:        被註釋的方法將在當前類的第一個測試方法調用前運行。
@AfterClass:        被註釋的方法將在當前類的全部測試方法調用後運行。
@BeforeMethod:        被註釋的方法將在每個測試方法調用前運行。
@AfterMethod:        被註釋的方法將在每個測試方法調用後運行。
屬性:
    alwaysRun    對於每一個bufore方法(beforeSuite, beforeTest, beforeTestClass 和 beforeTestMethod, 可是不包括 beforeGroups): 
                若是設置爲true,被配置的方法將老是運行而無論它屬於哪一個組。
                對於after方法(afterSuite, afterClass, ...): 若是設置爲true,被配置的方法甚至在一個或多個先調用的方法失敗或被忽略時也將運行。
    dependsOnGroups        這個方法依賴的組列表
    dependsOnMethods    這個方法依賴的方法列表
    enabled            這個類的方法是否激活
    groups            這個類或方法所屬的分組列表
    inheritGroups        若是設置爲true,這個方法被屬於在類級別被@Test annotation指定的組
 
@DataProvider    標記一個方法用於爲測試方法提供數據。
                被註釋的方法必須返回Object[][], 其中每一個Object[]能夠指派爲這個測試方法的參數列表。
                從這個DataProvider接收數據@Test方法須要使用一個和當前註釋相同名稱的dataProvider名稱
    name         這個DataProvider的名稱
 
@Factory    標記方法做爲一個返回對象的工廠,這些對象將被TestNG用於做爲測試類。這個方法必須返回Object[]
 
@Parameters    描述如何傳遞參數給@Test方法
    value    用於填充這個方法的參數的變量列表
 
@Test        標記一個類或方法做爲測試的一部分
    alwaysRun     若是設置爲true,這個測試方法將老是運行,甚至當它依賴的方法失敗時。
    dataProvider     這個測試方法的data provider的名稱
    dataProviderClass     用於查找data provider的類。
                    若是不指定,將在當前測試方法所在的類或者它的基類上查找data provider。
                    若是這個屬性被指定, 則data provider方法須要是指定類的static方法。
    dependsOnGroups     當前方法依賴的組列表
    dependsOnMethods     當前方法依賴的方法列表
    description     當前方法的描述
    enabled     當前類的方法/方法是否被激活
    expectedExceptions     測試方法指望拋出的異常列表。若是沒有異常或者拋出的不是列表中的任何一個,當前方法都將標記爲失敗.
    groups     當前類/方法所屬的組列表
    invocationCount     當前方法被調用的次數
    successPercentage     當前方法指望的成功率
    sequential     若是設置爲true,當前測試類上的全部方法保證按照順序運行。甚至測試們在parallel="true"的狀況下.
            這個屬性只能用於類級別,若是用於方法級別將被忽略。
    timeOut     當前方法允許花費的最大時間,單位毫秒。
    threadPoolSize     當前方法的線程池大小。方法將被多線程調用,次數由invocationCount參數指定
            注意:若是invocationCount沒有指定則這個屬性將被忽略


注:
    上面是TestNG中用到的annotation列表,從中咱們能夠看到TestNG提供的一些特性

1. before方法和after方法    帶來了足夠豐富的測試生命週期控制
2. dependsOnGroups/dependsOnMethods 提供了依賴檢查機制,並能夠嚴格控制執行順序
3. DataProvider 使得對同一個方法的測試覆蓋變的很是輕鬆,很是適合進行邊界測試,只要給出多種測試數據就能夠針對一個測試方法進行覆蓋
4. expectedExceptions 使得異常測試變的很是輕鬆
5. invocationCount/threadPoolSize 終於能夠簡單的直接進行多線程測試了,這個絕對是junit的超級弱項,回想junit中那個萬惡的System.exist(0)...
6. timeOut 終於不用死等而後手工強行關閉測試,TestNG想的太周到了

TestNG官方文檔中文版(3)-testng.xml 
    TestNG的官方文檔的中文翻譯版第3章,原文請見 http://testng.org/doc/documentation-main.html

    3 - testng.xml

    調用TestNG由幾種不一樣方法:

    * 使用testng.xml文件
    * 使用ant
    * 從命令行

    這節描述testng.xml的格式(文檔的後面會講到ant和命令行)。

    當前testng.xml的DTD文件能夠從官方找到:http://testng.org/testng-1.0.dtd。(爲了方便使用,你可能更喜歡瀏覽HTML版本)。
    下面是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="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> 

<!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 annotation的類。

    你一樣能夠指定包含或不包含的組和方法:


<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> 

<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中定義新的組,指定屬性的額外詳細狀況,好比是否並行運行測試,使用多少線程,是否運行junit測試,等等...
    請查看DTD文件瞭解完整的特性列表。

4 - 運行TestNG

TestNG能夠以不一樣的方式調用:

    * Command line
    * ant
    * Eclipse
    * IntelliJ's IDEA

1) 命令行

假設你已經將TestNG加入到class path,調用TestNG最簡單的方法事下面的:

java org.testng.TestNG testng1.xml [testng2.xml testng3.xml ...]

必須指定最少一個描述你試圖測試的TestNG suite的xml文件。另外,下面的命令行參數可使用:

命令行參數列表

選項        參數                文檔說明
-d        一個目錄            生成報告的目錄( test-output)
-sourcedir    分號隔開的目錄列表        帶有javadoc註釋的測試源文件目錄. 這個選項只在使用javadoc類型的annotation時纔有效. 
                        (例如 "src/test" or "src/test/org/testng/eclipse-plugin;src/test/org/testng/testng").
-testclass    能夠在classpath路徑中找到的逗號分隔的類列表。逗號分隔的類文件列表(例如 "org.foo.Test1,org.foo.test2").
-groups        逗號分隔的組列表        要運行的組列表(例如 "windows,linux,regression").
-excludegroups    逗號分隔的組列表        不想包含在此次運行中的組列表
-testrunfactory    能夠在classpath中找到的java類    指定測試的runner.這個類須要實現接口org.testng.ITestRunnerFactory .
-listener    能夠在classpath路徑中找到的逗號分隔的類列表。    指定測試的listener. 這個類須要實現接口org.testng.ITestListener
-parallel    methods|tests            若是指定, 設置運行測試時如何使用併發線程的默認機制.若是不設置,默認機制是徹底不使用併發線程。這個設置能夠被suite定義覆蓋.
-threadcount    併發測試運行時默認使用的線程數    用於設置併發測試時默認的線程數. 只在併發模式被選擇時才生效 (例如, 打開 -parallel 選項). 這個設置能夠被suite定義覆蓋.
-suitename    測試套件使用的默認名稱.        指定在命令行上定義的測試套件的名稱。若是suite.xml文件或源代碼指定了另一個不一樣的套件名稱,這個選項將被忽略。能夠建立帶空格的套件名稱,若是在名稱先後加雙引號如"like this".
-testname    測試使用的默認名稱.        指定在命令行上定義的測試的名稱。若是suite.xml文件或源代碼指定了另一個不一樣的測試名稱,這個選項將被忽略。能夠建立帶空格的測試名稱,若是在名稱先後加雙引號如"like this".
-reporter    擴展配置用於自定義報告listenner.    相似 -listener 選項, 除了允許reporter示例上由javabean形式的配置.
    例如: -reporter com.test.MyReporter:methodFilter=*insert*,enableFiltering=true

能夠經過不帶任何參數直接調用TestNFG來得到這個文檔。

能夠將命令行開關寫到txt文件中,例如c:/command.txt, 而後告訴TestNG使用這個文件類找到參數:

  C:> more c:/command.txt
  -d test-output testng.xml
  C:> java org.testng.TestNG @c:/command.txt

另外,能夠經過jvm的命令行來傳遞參數給TestNG,例如

java -Dtestng.test.classpath="c:/build;c:/java/classes;" org.testng.TestNG testng.xml

TestNG可以理解的參數
屬性             類型                     文檔
testng.test.classpath     分號分隔的包含測試類的一系列目錄     若是這個屬性被設置,TestNG將使用它替代從class path來查找測試類. 若是你正在使用在xml文件裏面的包標籤而且在classpath路徑中由不少類而大部分都不是測試類的時候比較方便

舉例:

java org.testng.TestNG -groups windows,linux -testclass org.test.MyTest

注意 ant 任務和testng.xml允許用更多的參數來啓動TestNG(包含的方法,指定的參數,等等),所以能夠認爲命令行適用於學習TestNG而且想快速入門。


2) Ant

能夠這樣定義TestNG的ant任務:

<taskdef resource="testngtasks"
         classpath="testng.jar"/>

這個任務運行TestNG測試,而且一般是在單獨的jvm中。接受下面的屬性:

屬性名            描述                是否必須
annotations         字符串"JDK"或者"Javadoc". 定義測試適用的註釋類型.若是使用"Javadoc", 則須要同時指定"sourcedir".     不是必須. 若是適用jkd5則默認爲"JDK",若是適用jdk1.4則默認爲"Javadoc"
classfilesetref     要運行的測試類的FileSet結構的引用.      
classpath         要運行的測試的PATH-like 結構.      
classpathref         要運行的測試的PATH-like 結構的引用.      
dumpCommand         打印TestNG啓動命令.     不是必須,默認false
enableAssert         開啓JDK 1.4的斷言.     不是必須,默認true
failureProperty     失敗發生時要設置的屬性的名稱. 只有haltonfailure沒有設置時纔有效.     不是必須.
haltonfailure         若是測試運行期間發生失敗,中止構造過程.     不是必須,默認false
haltonskipped         若是發生至少一次測試跳過,中止構造過程.        不是必須,默認false
groups             要運行的組列表,空格或逗號分隔    
excludedgroups         排除在外的組列表,空格或逗號分隔
jvm             使用的jvm,將被Runtime.exec()運行     java
listeners         逗號或空格分隔的全路徑類列表,須要實現org.testng.ITestListener或org.testng.IReporter     不是必須
outputdir         報告輸出目錄             不是必須,默認輸出到test-output.
skippedProperty     當發生測試被跳過期設置的property的名稱.只有當haltonskipped沒有設置時才使用     不是必須
sourcedir         用於jdk1.4測試的PATH-like結構(使用JavaDoc形式的annotations)      
sourcedirref         用於jdk1.4測試的PATH-like結構的引用(使用JavaDoc形式的annotations)           
suiteRunnerClass     TestNG啓動器的全路徑名稱    不是必須.  默認使用org.testng.TestNG
parallel         運行測試時使用的並行模式 - methods或者tests     不是必須 - 若是沒有指定,並行模式不被選擇
threadCount         運行時使用的線程數量。若是並行模式被同時指定不然忽略。     默認1
testJar         包含測試和套件定義的jar包路徑
timeOut         全部測試必須運行完成的最大超時時間,單位毫秒 
useDefaultListeners     是否使用默認監聽器和報告器.     默認true.
workingDir         運行TestNG前ant任務應該轉移到的目錄。
xmlfilesetref        用於要測試的套件定義的FileSet結構的引用      
suitename         設置測試套件的默認名稱若是在suite的xml文件或者源代碼中都沒有被定義。    不是必須,默認設置爲"Ant suite"
testname        設置測試的默認名稱若是在suite的xml文件或者源代碼中都沒有被定義。    不是必須,默認設置爲"Ant test"


屬性classpath, classpathref或者內嵌的<classpath>必須設置一個,用於提供測試的classpath

屬性xmlfilesetref, classfilesetref 或者內嵌的 <xmlfileset>, 分別的<classfileset>必須使用用來提供測試

注意:若是使用jdk1.4,屬性attributes sourcedir, sourcedirref 或者內嵌的 <sourcedir> 必須提供.

注意:使用<classfileset> 並不自動按添加測試類到classpath: 須要報告這些在classpath中的任務要工做的類

內嵌元素
classpath
 <testng> 任務支持一個內嵌的<classpath> 元素來提供PATH-like的結構.

bootclasspath
bootstrap類文件的位置能夠用這個PATH形式的結構指定-若是fork沒有設置則被忽略

xmlfileset
套餐定義(testng.xml)能夠經過一個FiltSet結構傳遞給任務

classfileset
TestNG能夠直接在類上運行,一樣支持FiltSet結構

sourcedir
PATH形式的結構,用於jdk1.4的測試,使用javadoc annotation

jvmarg
經過內嵌的<jvmarg>元素將額外的參數傳遞給新的虛擬機,例如:

<testng>
   <jvmarg value="-Djava.compiler=NONE" />
   <!-- ... -->
</testng>

sysproperty
使用內嵌的<sysproperty>元素來指定類須要的系統屬性。在測試的執行期間虛擬機能夠獲取這些屬性。 這個元素的屬性和環境變量相同。


<testng>  
   <sysproperty key="basedir" value="${basedir}"/>  
   <!-- ... -->  
</testng> 

<testng>  
   <sysproperty key="basedir" value="${basedir}"/>  
   <!-- ... -->  
</testng> 

將運行測試而且使得測試能夠訪問basedir屬性
reporter

內部的<reporter>元素是一個可選的方式,用於注入自定義的報告監聽器,允許用戶爲調整運行時的報告期行爲而
這個元素強制要求設置classname屬性,指示自定義監聽器的類。爲了設置報告期屬性,<reporter>元素能夠包含多個內嵌的<property>元素來提供name和value屬性,以下所示:

 

請注意這裏僅僅支持有限的屬性類型:String, int, boolean, byte, char, double, float, long, short.

env
能夠經過內嵌的 <env>元素給TestNG的單獨的虛擬機傳遞指定的環境變量。
要查閱<env> 元素屬性的詳細描述,請查看ant的exec任務的描述。

舉例:
Suite xml


<testng classpathref="run.cp"  
        outputDir="${testng.report.dir}"  
        sourcedir="${test.src.dir}"  
        haltOnfailure="true">  
   
   <xmlfileset dir="${test14.dir}" includes="testng.xml"/>  
</testng> 

<testng classpathref="run.cp"  
        outputDir="${testng.report.dir}"  
        sourcedir="${test.src.dir}"  
        haltOnfailure="true">  
   
   <xmlfileset dir="${test14.dir}" includes="testng.xml"/>  
</testng>  
 
Class FileSet

<testng classpathref="run.cp"
        outputDir="${testng.report.dir}"
        haltOnFailure="true"M verbose="2">
    <classfileset dir="${test.build.dir}" includes="**/*.class" />
</testng>

5 - Test methods, Test classes and Test groups
5.1 - Test groups

TestNG允許執行復雜的測試方法分組。不只能夠申明方法屬於組,並且能夠指定分組包含其餘分組。
而後TestNG能夠被調用,並被要求包含某些分組和排除其餘的分組。
這將提供怎樣劃分測試的最大彈性,而且若是想運行兩個不一樣的測試裝置不須要從新編譯。

例如,很是廣泛的須要至少兩個種類的測試

    * Check-in tests.  這些測試將在提交新代碼以前運行. 它們典型的被要求快速並且僅僅確認沒有基礎功能被破壞。 
    * Functional tests.  這些測試將覆蓋全部的軟件功能,而且必須運行至少1天,儘管理想的是連續運行.

表明性的,check-in測試是功能性測試的子集。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() {  
  }  

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> 

<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() {  
  }  

@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方法:


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

<test name="Test1">  
  <groups>  
    <run>  
      <include name="windows.*"/>  
    </run>  
  </groups>  
  <classes>  
    <class name="example1.Test1"/>  
  </classes>  
</test>  
 
注意:TestNG使用正則表達,而不是wildmats。注意這個差異。

Method groups
一樣能夠包含或排除個別方法:


<test name="Test1">  
  <classes>  
    <class name="example1.Test1">  
      <methods>  
        <include name=".*enabledTestMethod.*"/>  
        <exclude name=".*brokenTestMethod.*"/>  
      </methods>  
     </class>  
  </classes>  
</test> 

<test name="Test1">  
  <classes>  
    <class name="example1.Test1">  
      <methods>  
        <include name=".*enabledTestMethod.*"/>  
        <exclude name=".*brokenTestMethod.*"/>  
      </methods>  
     </class>  
  </classes>  
</test>  
 
這在須要使莫個單獨的方法失效而不想從新編譯時很是方便,可是不建議太多的使用這個機制,由於這將可能破壞你的測試框架 若是你開始重構你的java代碼(標籤中使用的正則表達式可能再也不匹配你的方法)
5.2 - Groups of groups

"functest" itself will contain the groups "windows" and "linux" while "checkintest will only contain "windows".  Here is how you would define this in your property file:
組能夠包含其餘組。這些組被稱爲"MetaGroups"。例如,你可能想定義一個"all"組,包括"checkintest"和"functest"。"functest"自身將包含組 "windows" 和 "linux",而"checkintest"將包含"windows".


<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> 

<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>  
 
5.3 - Exclusion groups

TestNG 允許包含組也允許排除組.

例如,當由由於最近的修改而臨時破壞的測試而又沒有時間去修復它們時很是有用。不管如何,你想要乾淨的運行功能性測試,所以你想要是這些測試失效,可是記住它們從新被激活。
一個簡單的解決這個問題的方法是建立一個稱爲"broken"的組並讓這些測試方法歸屬它。例如,在上面的例子中,我知道testMethod2() 如今被破壞了,全部我想關閉它:


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

@Test(groups = {"checkintest", "broken"} )  
public void testMethod2() {  
}  
 
如今我所想要作的只是在運行中排除這個組:


<test name="Simple example">  
  <groups>  
    <run>  
      <include name="checkintest"/>  
      <exclude name="broken"/>  
    </run>  
  </groups>  
   
  <classes>  
    <class name="example1.Test1"/>  
  </classes>  
</test> 

<test name="Simple example">  
  <groups>  
    <run>  
      <include name="checkintest"/>  
      <exclude name="broken"/>  
    </run>  
  </groups>  
   
  <classes>  
    <class name="example1.Test1"/>  
  </classes>  
</test>  
 
用這種方法,我將獲得一個乾淨的測試運行,同時記錄了那些被破壞並想要後續修復的測試。
注意:你也能夠經過使用在@Test and @Before/After annotations上的"enabled"屬性在個體的層面上關閉測試,

5.4 - Partial groups
你能夠在類的級別上定義組,而後在方法的層次上添加組:


@Test(groups = { "checkin-test" })  
public class All {  
  @Test(groups = { "func-test" )  
  public void method1() { ... }  
  public void method2() { ... }  

@Test(groups = { "checkin-test" })  
public class All {  
  @Test(groups = { "func-test" )  
  public void method1() { ... }  
  public void method2() { ... }  
}  
 
在這個類中,method2() 屬於組"checkin-test",在類的級別定義。而method1() 同時屬於 "checkin-test" 和 "func-test".
5.5 - Parameters

測試方法不要求是無參數的。你能夠在每一個測試方法上使用任意數量的參數,並指示testNG傳遞正確的參數。
有兩種方式用於設置參數:使用testng.xml或者編程式。

  5.5.1 - Parameters from testng.xml
若是你要爲你的參數使用簡單值,你能夠在你的testng.xml中明確指定:


@Parameters({ "first-name" })  
@Test  
public void testSingleString(String firstName) {  
  System.out.println("Invoked testString " + firstName);  
  assert "Cedric".equals(firstName);  

@Parameters({ "first-name" })  
@Test  
public void testSingleString(String firstName) {  
  System.out.println("Invoked testString " + firstName);  
  assert "Cedric".equals(firstName);  

在這個代碼中,咱們明確指定java方法的參數「firstName」應該接收名爲「first-name」xml參數的值。 這個xml參數在testng.xml中定義:

<suite name="My suite">
  <parameter name="first-name"  value="Cedric"/>
  <test name="Simple example">
  <--  -->
一樣的方法能夠用於註解@Before/After和@Factory:


@Parameters({ "datasource", "jdbcDriver" })  
@BeforeMethod  
public void beforeTest(String ds, String driver) {  
  m_dataSource = ;                              // look up the value of datasource  
  m_jdbcDriver = driver;  

@Parameters({ "datasource", "jdbcDriver" })  
@BeforeMethod  
public void beforeTest(String ds, String driver) {  
  m_dataSource = ;                              // look up the value of datasource  
  m_jdbcDriver = driver;  

此次,兩個java參數ds和driver將分別接收被設置給屬性datasource和jdbc-driver的值。
參數能夠經過可選註解來聲明爲可選:
@Parameters("db")
@Test
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>標籤下定義的參數優先。很是適用於這樣的場合:須要指定一個應用於全部測試的參數,可是又但願在特定測試用覆蓋它的值。

  5.5.2 - Parameters with DataProviders

在testng.xml中指定參數,對於如下狀況是不夠的:
    * 不使用testng.xml
    * 須要傳遞複雜參數,或者參數須要從java中建立(複雜對象,從屬性文件或者數據庫中讀取的對象)在這種狀況下,你可使用Data Provider來提供你測試須要的數值。Data Provider是類中的一個返回對象數組的數組的方法。這個方法帶有@DataProvider註解:

//這個方法將提供數據給任何聲明它的Data Provider名爲"test1"的測試方法


@DataProvider(name = "test1")  
public Object[][] createData1() {  
 return new Object[][] {  
   { "Cedric", new Integer(36) },  
   { "Anne", new Integer(37)},  
 };  

@DataProvider(name = "test1")  
public Object[][] createData1() {  
 return new Object[][] {  
   { "Cedric", new Integer(36) },  
   { "Anne", new Integer(37)},  
 };  
}  
 
//這個方法聲明它的數據將由名爲"test1"的Data Provider提供


@Test(dataProvider = "test1")  
public void verifyData1(String n1, Integer n2) {  
 System.out.println(n1 + " " + n2);  

@Test(dataProvider = "test1")  
public void verifyData1(String n1, Integer n2) {  
 System.out.println(n1 + " " + n2);  
}  
 
將打印
    Cedric 36
    Anne 37 
@Test方法用dataProvider屬性來指定它的Data Provider。這個名字必須符合同一個類中用@DataProvider(name="...")註解的方法,它們要使用同一個匹配的名字。
默認,將在當前類或者它的基類中查找data provider。若是你想將data provider放置到另外一個類中,須要將這個data provider方法設置爲靜態方法,並在dataProviderClass屬性中指定在哪一個類中能夠找到這個方法。


public static class StaticProvider {  
  @DataProvider(name = "create")  
  public static Object[][] createData() {  
    return new Object[][] {  
      new Object[] { new Integer(42) }  
    }  
  }  

public static class StaticProvider {  
  @DataProvider(name = "create")  
  public static Object[][] createData() {  
    return new Object[][] {  
      new Object[] { new Integer(42) }  
    }  
  }  
}  
 
public class MyTest {
  @Test(dataProvider = "create", dataProviderClass = StaticProvider.class)
  public void test(Integer n) {
    // 
  }
}
Data Provider方法將返回下面兩個類型中的一種:
The Data Provider method can return one of the following two types:
    * 對象數組的數組(Object[][]) ,外圍數據的大小是測試方法將被調用的次數,而內層數組的大小和類型必須和測試方法的參數列表匹配。如同上面舉例說明的。
    * <Object[]>的Iterator,和Object[][]的惟一差異在於Iterator允許延遲建立測試數據。testNG將一個接一個的調用iterator,再用iterator返回的參數調用測試方法。若是有不少參數集合須要傳遞給方法而又不想一開始就建立全部參數,會很是有用。

Here is an example of this feature for both JDK 1.4 and JDK5 (note that the JDK 1.4 example does not use Generics):
這裏有一個同時適用於JDK 1.4和JDK5的例子(注意JDK 1.4的例子不使用註解):


/** 
 * @testng.data-provider name="test1" 
 */  
public Iterator createData() {  
  return new MyIterator(DATA);  
)  
@DataProvider(name = "test1")  
public Iterator createData() {  
  return new MyIterator(DATA);  

/** 
 * @testng.data-provider name="test1" 
 */  
public Iterator createData() {  
  return new MyIterator(DATA);  
)  
@DataProvider(name = "test1")  
public Iterator createData() {  
  return new MyIterator(DATA);  
}  
 
若是將測試方法的第一個參數申明爲java.lang.reflect.Method,TestNG將使用這個第一個參數來傳遞當前測試方法。當多個測試方法使用同一個@DataProvider而須要依當前申請數據的方法而定來返回不一樣值時特別有用。
舉例說明,下面的代碼在@DataProvider中打印測試方法的名字:


@DataProvider(name = "dp")  
public Object[][] createData(Method m) {  
  System.out.println(m.getName());  // print test method name  
  return new Object[][] { new Object[] { "Cedric" }};  
}  
@Test(dataProvider = "dp")  
public void test1(String s) {  
}  
@Test(dataProvider = "dp")  
public void test2(String s) {  

@DataProvider(name = "dp")  
public Object[][] createData(Method m) {  
  System.out.println(m.getName());  // print test method name  
  return new Object[][] { new Object[] { "Cedric" }};  
}  
@Test(dataProvider = "dp")  
public void test1(String s) {  
}  
@Test(dataProvider = "dp")  
public void test2(String s) {  
}  
 
將會顯示:
    test1
    test2

5.6 - Dependent methods

有些時候,你須要你的測試方法按照一個特定的順序被調用。這很是有用,好比:
    * 在運行更多測試方法前確認特定數量的測試方法調用完成而且成功
    * 初始化測試並但願這個初始化方法也做爲測試方法(被標記爲@Before/After的方法將不做爲最終報告的一部分)

爲了作到這點,須要使用@Test註解的dependsOnMethods屬性或者dependsOnGroups屬性。
有兩種依賴:
    * 強依賴。在運行你的測試方法前全部依賴方法必須運行而且成功。哪怕有一個依賴方法失敗,測試方法都不會被調用,在報告中將被標記爲SKIP。
    * 軟依賴。測試方法在依賴方法運行後老是會被運行,即便某些依賴方法失敗。對於只想確認測試方法是按照特定順序運行,而測試方法並不真正依賴其餘方法是否成功的狀況,很是有用。軟依賴經過在@Test註解中增長"alwaysRun=true"來實現。

這裏有一個強依賴的例子:

@Test
public void serverStartedOk() {}

@Test(dependsOnMethods = { "serverStartedOk" })
public void method1() {}

在這個例子中,method1()被申明依賴於方法serverStartedOk(),這保證serverStartedOk() 方法將老是首先被調用。
也可讓方法依賴於完整的測試組:

@Test(groups = { "init" })
public void serverStartedOk() {}

@Test(groups = { "init" })
public void initEnvironment() {}

@Test(dependsOnGroups = { "init.* })
public void method1() {}

在這裏例子中,method1()被申明依賴於任何匹配正則表達式"init.*"的組,這保證了方法serverStartedOk()和initEnvironment()老是在method1()前被調用。

注意:前面說明說,在測試運行期間,屬於同一個組的方法的調用順序並不保證相同。若是一個方法的依賴失敗了,並且是強依賴(默認alwaysRun=false),這個方法將不被標記爲FAIL而是SKIP。被跳過的方法在最終的報告中報告(在HTML中用紅和綠以外的其餘顏色),這很重要,由於被跳過的方法並不必定是失敗。

dependsOnGroups和dependsOnMethods都接受正則表達式做爲參數。對於dependsOnMethods, 若是你依賴的方法巧合有多個重載的版本,全部裝載的方法都將被調用。若是你只想調用重載的方法中的一個,請使用dependsOnGroups。

有關方法依賴的更高級的例子,請參考本文檔,將使用繼承來提供一個優雅的解決方案來處理多重依賴的問題。

5.7 - Factories

工廠類允許你動態建立測試案例。例如,想象你須要建立一個測試方法,訪問一個web站點上的頁面不少次,而你但願用不一樣的值來調用它:

 


public class TestWebServer {  
  @Test(parameters = { "number-of-times" })  
  public void accessPage(int numberOfTimes) {  
    while (numberOfTimes-- > 0) {  
     // access the web page  
    }  
  }  

public class TestWebServer {  
  @Test(parameters = { "number-of-times" })  
  public void accessPage(int numberOfTimes) {  
    while (numberOfTimes-- > 0) {  
     // access the web page  
    }  
  }  
}  
 
testng.xml:


<test name="T1">  
  <parameter name="number-of-times" value="10"/>  
  <class name= "TestWebServer" />  
</test>  
<test name="T2">  
  <parameter name="number-of-times" value="20"/>  
  <class name= "TestWebServer"/>  
</test>  
<test name="T3">  
  <parameter name="number-of-times" value="30"/>  
  <class name= "TestWebServer"/>  
</test> 

<test name="T1">  
  <parameter name="number-of-times" value="10"/>  
  <class name= "TestWebServer" />  
</test>  
<test name="T2">  
  <parameter name="number-of-times" value="20"/>  
  <class name= "TestWebServer"/>  
</test>  
<test name="T3">  
  <parameter name="number-of-times" value="30"/>  
  <class name= "TestWebServer"/>  
</test>  
 
這種方式很快就會變的難於管理,因此做爲替換品,你可使用factory:

 


public class WebTestFactory {  
  @Factory  
  public Object[] createInstances() {  
   Object[] result = new Object[10];   
   for (int i = 0; i < 10; i++) {  
      result[i] = new WebTest(i * 10);  
    return result;  
  }  

public class WebTestFactory {  
  @Factory  
  public Object[] createInstances() {  
   Object[] result = new Object[10];   
   for (int i = 0; i < 10; i++) {  
      result[i] = new WebTest(i * 10);  
    return result;  
  }  
}  
 
而新的測試類是這樣:


public class WebTest {  
  private int m_numberOfTimes;  
  public WebTest(int numberOfTimes) {  
    m_numberOfTimes = numberOfTimes;  
  }  
  @Test  
  public void testServer() {  
   for (int i = 0; i < m_numberOfTimes; i++) {  
     // access the web page  
    }  
  }  

public class WebTest {  
  private int m_numberOfTimes;  
  public WebTest(int numberOfTimes) {  
    m_numberOfTimes = numberOfTimes;  
  }  
  @Test  
  public void testServer() {  
   for (int i = 0; i < m_numberOfTimes; i++) {  
     // access the web page  
    }  
  }  
}  
 
testng.xml只須要引用簡單引用這個包含factory方法的類,由於測試實例將在運行時被建立。

<class name="WebTestFactory" />
工廠類將像@Test和@Before/After同樣接收參數,必須返回Object[]。返回的對象能夠是任何類(不必定要求是和factory類同樣),而且他們甚至都不須要包含TestNG的註解(這種狀況下他們將被testNG忽略)。

5.8 - Class level annotations

@Test註解能夠放置在類上:


@Test  
public class Test1 {  
  public void test1() {  
  }  
  public void test2() {  
  }  

@Test  
public class Test1 {  
  public void test1() {  
  }  
  public void test2() {  
  }  
}  
 
類級別註解的效果是將這個類的全部的public方法都變成測試方法,即便他們沒有被註解。還能夠在須要增長屬性的方法上重複@Test註解。

例如:


@Test  
public class Test1 {  
  public void test1() {  
  }  
  @Test(groups = "g1")  
  public void test2() {  
  }  

@Test  
public class Test1 {  
  public void test1() {  
  }  
  @Test(groups = "g1")  
  public void test2() {  
  }  
}  
 
將方法test1()和test2()都變成測試方法,可是在此之上,test2()如今屬於組"g1".

5.9 - Parallel running and time-outs

能夠經過使用parallel屬性要求TestNG在單獨的線程中運行測試。這個屬性能夠在兩個值中取其一:

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

<suite name="My suite" parallel="tests" thread-count="5">
    * parallel="methods": TestNG將在單獨的線程中運行測試方法,除了那些依賴其餘測試方法的,這些將在同一個線程中運行,以保證他們的執行順序。

    * parallel="tests": TestNG將在一個線程中運行全部在同一個<test>標籤中的測試方法,可是每一個<test>標籤將在單獨的線程中運行。這種方式允許把全部不是線程安全的類分組到相同的<test>標籤中,保證他們將在相同的線程中運行,有利於TestNG使用盡量多的線程來運行測試。

    此外,thread-count屬性允許指定運行時將分配多少線程。
    
    注意:@Test的屬性timeOut在併發和非併發模型下均可以工做。

    也能夠指定@Test方法在不一樣的線程中被調用。可使用threadPoolSize屬性來實現這樣的結果:

@Test(threadPoolSize = 3, invocationCount = 10,  timeOut = 10000)
public void testServer() {
}
在這個例子中,方法testServer將被3個不一樣線程調用10次。此外,10秒種的time-out屬性保證任何線程都不會長時間阻塞。


5.10 - Rerunning failed tests

套件中的測試失敗時,每次testNG都會在輸出目錄中建立一個名爲testng-failed.xml的文件。這個xml文件包含只從新運行這些失敗的測試方法的必要信息,允許只運行這些失敗的測試而沒必要運行所有測試。所以,一種典型的狀況將是這樣:

java -classpath testng.jar;%CLASSPATH% org.testng.TestNG -d test-outputs testng.xml
java -classpath testng.jar;%CLASSPATH% org.testng.TestNG -d test-outputs test-outputs/testng-failed.xml
注意testng-failed.xml將包含全部必要的依賴方法,因此能夠保證運行失敗的方法而不運行任何被跳過的(失敗)方法。

5.11 - JUnit tests

TestNG能夠運行junit測試。所須要的只是在testng.classNames屬性中指定junit測試類,並設置testng.junit屬性爲true。

<test name="Test1"   junit="true">
  <classes>
    <!--  -->
這種狀況下TestNG的行爲相似jnit:

    * 類中全部以test*開頭的方法將被運行。
    * 若是測試類中有方法setUp(), 將在每次測試方法調用前被執行。
    * 若是測試類中有方法tearDown(),將在每次測試方法調用後被執行。

5.12 - JDK 1.4

TestNG也能夠在JDK1.4下工做。在這種狀況下,須要使用發佈的jdk1.4的jar文件(名爲testng-...-jdk14.jar)。惟一的差異是在於註解,jdk1.4下使用流行的XDoclet javadoc註解語法:

public class SimpleTest {


 /** 
  * @testng.before-class = "true" 
  */  
  public void setUp() {  
    // code that will be invoked when this test is instantiated  
 }  
 /** 
  * @testng.test groups = "functest" dependsOnGroups = "group1,group2" 
  */  
  public void testItWorks() {  
    // your test code  
 }  

 /** 
  * @testng.before-class = "true" 
  */  
  public void setUp() {  
    // code that will be invoked when this test is instantiated  
 }  
 /** 
  * @testng.test groups = "functest" dependsOnGroups = "group1,group2" 
  */  
  public void testItWorks() {  
    // your test code  
 }  

javadoc語法的規則很是簡潔,和jdk1.5註解的惟一差異是數組串數組須要特別寫成單獨的,逗號或空格分隔的字符串。雖然值周圍的雙引號是可選的,但仍是建議在任何狀況下都使用雙引號,以保證未來遷移到jdk1.5時能夠比較容易。
一樣須要在<testng>的ant任務中指明sourcedir屬性(或者在命令行中使用-sourcedir),以便testNG能夠找到你的測試文件的源代碼來解析javadoc註解。

這裏是jdk1.4和jdk5註解的語法對照表:

    (表格在blog中很差排版,不在這裏發了,詳細內容請參考官方文檔的原文:http://testng.org/doc/documentation-main.html#jdk-14。)

更多jdk1.4的支持範例,請參考發行包中的test-14文件夾,這裏包含所有的JDK 1.5測試對應的使用javadoc註解的內容。


5.13 - Running TestNG programmatically

在本身的程序中調用testNG也很簡單:

TestListenerAdapter tla = new TestListenerAdapter();
TestNG testng = new TestNG();
testng.setTestClasses(new Class[] { Run2.class });
testng.addListener(tla);
testng.run();

這個範例建立了一個TestNG對象並運行測試類Run2。還增長了一個TestListener。你可使用適配器類org.testng.TestListenerAdapter或本身實現org.testng.ITestListener。這個接口包含多個回調方法,使得能夠追蹤測試的開始,成功,失敗等等。

相似的,可使用testng.xml文件調用TestNG或者本身建立一個虛擬的testng.xml文件。爲了作到這點,須要使用org.testng.xml包的類:XmlClass, XmlTest, 等等。每一個類對應他們xml標籤。

例如,假設你想建立下面的虛擬文件:

<suite name="TmpSuite" >
  <test name="TmpTest" >
    <classes>
      <class name="test.failures.Child"  />
    <classes>
    </test>
</suite>
你將使用下面的代碼:

XmlSuite suite = new XmlSuite();
suite.setName("TmpSuite");

XmlTest test = new XmlTest(suite);
test.setName("TmpTest");
List<XmlClass> classes = new ArrayList<XmlClass>();
classes.add(new XmlClass("test.failures.Child"));
test.setXmlClasses(classes) ;
而後你能夠將XmlSuite傳遞給TestNG:

List<XmlSuite> suites = new ArrayList<XmlSuite>();
suites.add(suite);
TestNG tng = new TestNG();
tng.setXmlSuites(suites);
tng.run();

完整的API請參考javadoc。


5.14 - BeanShell and advanced group selection

若是testng.xml中的<include>和<exclude>標籤還不足夠知足你的須要,你可使用BeanShell表達式來決定是否須要將一個特定的測試方法包含在測試操做中。只須要在<test>標籤下指定這個表達式:


<test name="BeanShell test">  
 <method-selectors>  
   <method-selector>  
     <mce:script language="beanshell"><!-- 
       groups.containsKey("test1") 
 --></mce:script>  
   </method-selector>  
 </method-selectors>  
<!--  --> 

<test name="BeanShell test">  
 <method-selectors>  
   <method-selector>  
     <mce:script language="beanshell"><!-- 
       groups.containsKey("test1") 
 --></mce:script>  
   </method-selector>  
 </method-selectors>  
<!--  --> 

當發現testng.xml中有<script>標籤,TestNG將忽略當前<test>標籤中的之後的組和方法的<include>和<exclude>標籤:BeanShell表達式將是決定一個測試方法是否包含的惟一方法。
這裏有一些BeanShell腳本的額外信息:

    * 必須返回boolean值。除了這個約束,任何有效的BeanShell代碼都被允許.(例如,你可能想在工做日返回true而在週末返回false,這將允許你更加日期不一樣差別性的運行測試。

    * TestNG爲了便利定義瞭如下變量:

        java.lang.reflect.Method method:  當前測試方法
        org.testng.ITestNGMethod testngMethod:  當前測試方法的描述
        java.util.Map<String, String> groups:  當前測試方法所屬組的Map

    * 你可能須要在你的表達式先後增長CDATA聲明(如上面所示)以免討厭的xml轉義字符

相關文章
相關標籤/搜索