TestNG默認情況下,會生產兩種類型的測試報告HTML的和XML的。 測試報告位于 "test-output" 目錄下。
TestNG的還允許用戶自己寫的報告凭戴,并用它使用TestNG。還有一個選項來寫你自己的記錄器炕矮,在運行時通過TestNG的通知
監(jiān)聽器: 為了實現(xiàn)一個監(jiān)聽類么夫,實現(xiàn)一個 ITestListener接口或者其它接口者冤。這些類在運行時通知了TestNG測試開始時,結束后档痪,失敗涉枫,跳過或傳遞。
記錄器: 為了實現(xiàn)一個報表類腐螟,實現(xiàn)一個org.testng.IReporter接口愿汰。這些類一整套運行結束時調用。調用時乐纸,該對象包含整個測試運行的信息傳遞到這個類衬廷。
IAnnotationTransformer
IAnnotationTransformer 監(jiān)聽器只能用來修改 @Test 注釋
IAnnotationTransformer 要求實現(xiàn) transform 方法,其方法簽名如下:
void transform(ITest annotation, Class testClass, Constructor testConstructor, Method testMethod);
annotation 代表就是為 testMethod 定義的 @Test 注釋
調用其方法可以更改 @Test 注釋屬性
例如汽绢,下面的代碼在運行時將屬性 enabled 改為 false 從而禁用了當前的測試方法
annotation.setEnabled(false);
IAnnotationTransformer2
IAnnotationTransformer2 監(jiān)聽器修改其他 TestNG 的注釋(比如吗跋,@DataProvider, @Factory )
該監(jiān)聽器要求實現(xiàn)的方法:
void transform(IConfigurationAnnotation annotation, java.lang.Class testClass,
java.lang.reflect.Constructor testConstructor,
java.lang.reflect.Method testMethod)
void transform(IDataProviderAnnotation annotation, java.lang.reflect.Method method)
void transform(IFactoryAnnotation annotation, java.lang.reflect.Method method)
IHookable
IHookable 監(jiān)聽器提供了類似與面向q切面編程(AOP)中的 Around Advice 的功能
它在測試方法執(zhí)行前后提供了切入點,從而使用戶在測試方法運行前后注入特定的功能
例如: 用戶可以在當前測試方法運行前加入特定的驗證邏輯以決定測試方法是否運行或者跳過宁昭,甚至覆蓋測試方法的邏輯
IHookable 監(jiān)聽器要求實現(xiàn)的方法簽名
void run(IHookCallBack callBack, ITestResult testResult)
運行原始測試方法邏輯跌宛,需要調用 runTestMethod 方法
callBack.runTestMethod(testResult);
用JAAS(Java驗證和授權API)一個例子:
public class MyHook implements IHookable {
public void run(final IHookCallBack icb, ITestResult testResult) {
// Preferably initialized in a @Configuration method
mySubject = authenticateWithJAAs();
Subject.doAs(mySubject, new PrivilegedExceptionAction() {
public Object run() {
icb.callback(testResult);
}
};
}
}
IInvokedMethodListener
與 IHookable 類似,IInvokedMethodListener 提供了類似與面向方面編程(AOP)中的 Before Advice 和 After Advice 的功能
IInvokedMethodListener監(jiān)聽器允許用戶在當前測試方法被執(zhí)行前和執(zhí)行后注入特定的邏輯
比如: 可以加入日志方法积仗,無論何時TestNG即將調用一個測試(被@Test注解的)或者配置(任何使用@Beforeor@After注解標注的方法)秩冈,監(jiān)聽器 IInvokedMethodListener都可以讓你得到通知
public interface IInvokedMethodListener extends ITestNGListener {
void beforeInvocation(IInvokedMethod method, ITestResult testResult);
void afterInvocation(IInvokedMethod method, ITestResult testResult);
}
IMethodInterceptor
TestNG 啟動之后,第一件要做的事情是將所有的測試方法分成兩類:
一類是順序運行的測試方法斥扛;
一類是沒有特定運行順序的測試方法
第一類
TestNG 通過 @Test
注釋中的 dependsOnGroups
和 dependsOnMethods
使用戶能夠定義測試方法之間的依賴關系。這種依賴關系也就決定這些測試方法必須按著怎樣的順序運行
第二類
除了第一類有依賴關系的剩下的全部歸于第二類丹锹,盡管默認 TestNG 會嘗試用類名將它們分組稀颁,但是理論上,它們的運行順序是隨機的楣黍,甚至每次運行的順序都可能不同
IMethodInterceptor 監(jiān)聽器使用戶擁有對第二類測試方法更大的控制權
實現(xiàn)的方法:
public interface IMethodInterceptor {
List<IMethodInstance> intercept(List<IMethodInstance> methods, ITestContext context);
}
intercept 方法在所有測試方法被分類后以及所有測試方法被執(zhí)行前被調用匾灶。所有的測試方法將按照 intercept 返回值列表中的順序被執(zhí)行。因此租漂,用戶在 intercept 方法中可以對列表進行修改阶女,比如重新排序,甚至增加或者減少測試方法哩治。
intercept方法也要返回一個IMethodInstance列表秃踩,它可能是下面情況之一:
- 內容與參數(shù)中接收的一致,但是順序不同
- 一組IMethodInstance對象
- 更大的一組IMethodInstance對象
定義了攔截器业筏,就把它傳遞個TestNG憔杨,用下面的方式:
java -classpath "testng-jdk15.jar:test/build" org.testng.TestNG -listener test.methodinterceptors.NullMethodInterceptor
-testclass test.methodinterceptors.FooTest
例如,下面是個方法攔截器會重新給方法排序蒜胖,一遍“fast”組中的方法總是先執(zhí)行:
public List<IMethodInstance> intercept(List<IMethodInstance> methods, ITestContext context) {
List<IMethodInstance> result = new ArrayList<IMethodInstance>();
for (IMethodInstance m : methods) {
Test test = m.getMethod().getConstructorOrMethod().getAnnotation(Test.class);
Set<String> groups = new HashSet<String>();
for (String group : test.groups()) {
groups.add(group);
}
if (groups.contains("fast")) {
result.add(0, m);
}
else {
result.add(m);
}
}
return result;
}
ISuiteListener
ISuiteListener 類似于 IInvokedMethodListener消别,區(qū)別是 IInvokedMethodListener 針對的是測試方法抛蚤,而 ISuiteListener 針對的是測試套件
ISuiteListener 監(jiān)聽器使用戶有機會在測試套件開始執(zhí)行以及執(zhí)行結束之后嵌入自己的邏輯。
實現(xiàn)的方法 :
void onFinish(ISuite suite)
void onStart(ISuite suite)
ITestListener
ITestListener 監(jiān)聽器要求實現(xiàn)的方法中包含如下三個
void onTestFailure(ITestResult result)
void onTestSkipped(ITestResult result)
void onTestSuccess(ITestResult result)
TestListenerAdapter 已經實現(xiàn) ITestListener寻狂,并且提供了一些有用的方法岁经,比如分別獲取所有成功失敗跳過三種測試結果的測試方法的方法,并且 ITestListner 中有很多方法而 TestListenerAdapter 已給出了默認實現(xiàn)
擴展TestListenerAdapter蛇券,它使用空方法實現(xiàn)了ITestListener
對每個傳遞進來的測試顯示"."的監(jiān)聽器缀壤,如果測試失敗則顯示 "F" ,跳過則是"S":
public class DotTestListener extends TestListenerAdapter {
private int m_count = 0;
@Override
public void onTestFailure(ITestResult tr) {
log("F");
}
@Override
public void onTestSkipped(ITestResult tr) {
log("S");
}
@Override
public void onTestSuccess(ITestResult tr) {
log(".");
}
private void log(String string) {
System.out.print(string);
if (++m_count % 40 == 0) {
System.out.println("");
}
}
}
IReporter
TestNG 提供了默認的測試報表
IReporter 監(jiān)聽器接口只有一個方法:
public void generateReport(List<ISuite> suites, String outputDirectory)
該方法在所有測試方法執(zhí)行結束后被調用,outputDirectory
是默認的測試報表生成路徑怀读,當然可以指定其他路徑生成報表
JUnitReport
TestNG 包含了一個可以讓TestNG的結果和輸出的XML能夠被JUnitReport所使用的監(jiān)聽器诉位。
例子: 并且ant任務創(chuàng)建了這個報告:
<target name="reports">
<junitreport todir="test-report">
<fileset dir="test-output">
<include name="*/*.xml"/>
</fileset>
<report format="noframes" todir="test-report"/>
</junitreport>
</target>
監(jiān)聽器的使用方法
在 testng.xml 中使用 TestNG 監(jiān)聽器
TestNG 通過 testng.xml 配置所有的測試方法。
Testng.xml 提供了 listeners 和 listener 標簽用來添加自定義的監(jiān)聽器菜枷。
<suite name="TestNGSample">
<listeners>
<listener class-name="listeners.OSFilter" />
<listener class-name="listeners.ProgressTracker" />
</listeners>
<test name="ProgressTracker Demo">
<classes>
<class name="tests.SampleTest" />
</classes>
</test>
</suite>
在源代碼中使用 TestNG 監(jiān)聽器
通過 @Listeners 注釋苍糠,可以直接在 Java 源代碼中添加 TestNG 監(jiān)聽器。
@Listeners({ OSFilter.class, ProgressTracker.class })
public class SampleTest {
@Test(groups = { OSNames.OS_LINUX })
public void test1() {
sleep(5000);
System.out.println(">>>test1");
}
注意:
在 @Listeners 中添加監(jiān)聽器跟在 testng.xml 添加監(jiān)聽器一樣啤誊,將被應用到整個測試套件中的測試方法岳瞭。如果需要控制監(jiān)聽器的應用范圍(比如添加的監(jiān)聽器僅使用于某些測試測試類或者某些測試方法),則必須在監(jiān)聽器類中編寫適當?shù)呐袛噙壿嫛?/p>
在 @Listeners 中添加監(jiān)聽器跟在 testng.xml 添加監(jiān)聽器的不同之處在于蚊锹,它不能添加 IAnnotationTransformer 和 IAnnotationTransformer2 監(jiān)聽器瞳筏。原因是因為這兩種監(jiān)聽器必須在更早的階段添加到 TestNG 中才能實施修改注釋的操作,所以它們只能在 testng.xml 添加牡昆。
TestNG 對添加的監(jiān)聽器不做去重判斷姚炕。因此,如果 testng.xml 和源代碼中添加了相同的監(jiān)聽器丢烘,該監(jiān)聽器的方法會被調用兩次柱宦。不要通過多種方式重復添加監(jiān)聽器。
通過 ServiceLoader 使用 TestNG 監(jiān)聽器
JDK中提供了一個非常優(yōu)雅的機制播瞳,通過ServiceLoader類的借口路徑來實現(xiàn)監(jiān)聽掸刊。
通過 ServiceLoader 的方式使用 TestNG 監(jiān)聽器,簡單來說赢乓,就是創(chuàng)建一個 jar 文件忧侧,里面包含 TestNG 監(jiān)聽器的實現(xiàn)類已經 ServiceLoader 需要的配置信息,并在運行 TestNG 時把該 jar 文件加載到類路徑中
這樣做的好處是:
- 可以輕松地與其他人分享 TestNG 監(jiān)聽器牌芋。
- 當有很多 testng.xml 文件時蚓炬,不需要重復把監(jiān)聽器添加到每個文件中。
具體例子
先創(chuàng)建一個偵聽器(所有的TetstNG監(jiān)聽都應該響應):
package test.tmp;
public class TmpSuiteListener implements ISuiteListener {
@Override
public void onFinish(ISuite suite) {
System.out.println("Finishing");
}
@Override
public void onStart(ISuite suite) {
System.out.println("Starting");
}
}
編譯這個文件躺屁,然后在當前文件位置創(chuàng)建一個文件META-INF/services/org.testng.ITestNGListener
這個名字就是要實現(xiàn)的接口
目錄結構试吁,只有僅僅兩個文件:
$ tree
|____META-INF
| |____services
| | |____org.testng.ITestNGListener
|____test
| |____tmp
| | |____TmpSuiteListener.class
在這個目錄創(chuàng)建一個jar文件:
jar cvf ../sl.jar .
將jar文件放入調用TestNG的類路徑下:
java -classpath sl.jar:testng.jar org.testng.TestNG testng-single.yaml
報表 API
要在HTML報告中顯示日志信息,那么就要用到類 org.testng.Reporter:Reporter.log("M3 WAS CALLED");
XML 報表
TestNG 提供一種XML報表器,使得能夠捕捉到只適用于TestNG而不適用與JUnit報表的那些特定的信息熄捍。
這在用戶的測試環(huán)境必須要是用TestNG特定信息的XML烛恤,而JUnit又不能夠提供這些信息的時候非常有用。