監聽(Listeners),捕捉Testng的行爲,並支持修改,用於定製化,如日誌輸出、自定義報告html
監聽器以下:java
實現IAnnotationTransformer的transform方法ide
參數含義:函數
需求:以2結尾的方法執行2次測試
public class MyTransformer implements IAnnotationTransformer { @Override public void transform(ITestAnnotation iTestAnnotation, Class aClass, Constructor constructor, Method method) { if (method.getName().endsWith("2")) { iTestAnnotation.setInvocationCount(2); } } }
public class App { @Test public void test_1() { System.out.println("Just run once"); } @Test public void test_2() { System.out.println("Run twice"); } } --------------------------- Just run once Run twice Run twice
testng.xml配置ui
<suite name="Suite1" verbose="1" > <listeners> <listener class-name="MyTransformer"/> </listeners> <test name="Test1"> <classes> <class name="App" /> </classes> </test> </suite>
@Listeners不支持IAnnotationTransformer 和 IAnnotationTransformer2,因此只能在testng.xml上配置監聽器,固然命令行也可行
實現IHookable的run方法命令行
調用IHookCallBack的runTestMethod方法,能夠回調原測試方法日誌
需求:只執行以2結尾的方法code
public class MyHookable implements IHookable { @Override public void run(IHookCallBack callBack, ITestResult testResult) { if (testResult.getMethod().getMethodName().endsWith("2")) { callBack.runTestMethod(testResult); } } }
@Listeners({MyHookable.class}) public class App { @Test public void test_1() { System.out.println("Just run once"); } @Test public void test_2() { System.out.println("Run twice"); } } ----------------------------- Run twice
適用於configuration(suit, test, class),以及testorm
配合log4j,能夠記錄詳細的執行過程
public class MyInvokedMethodListener implements IInvokedMethodListener { @Override public void beforeInvocation(IInvokedMethod method, ITestResult testResult) { System.out.println("begin to run " + testResult.getName()); } @Override public void afterInvocation(IInvokedMethod method, ITestResult testResult) { System.out.println("end to run " + testResult.getName() + ", result code is " + testResult.getStatus()); } }
@Listeners({MyInvokedMethodListener.class}) public class App { @BeforeClass public void setup() { System.out.println("initial env"); } @Test public void test_1() { System.out.println("test 1"); Assert.assertTrue(true); } @Test public void test_2() { System.out.println("test 2"); Assert.assertTrue(false); } } --------------------- begin to run setup initial env end to run setup, result code is 1 begin to run test_1 test 1 end to run test_1, result code is 1 begin to run test_2 test 2 end to run test_2, result code is 2
4 IMethodInterceptor
需求:優先執行fast組成員方法
public class MyMethodInterceptor implements IMethodInterceptor { @Override public List<IMethodInstance> intercept(List<IMethodInstance> methods, ITestContext context) { List<IMethodInstance> result = new ArrayList<>(); methods.forEach(method -> { Test test = method.getMethod().getConstructorOrMethod().getMethod().getAnnotation(Test.class); Set<String> groups = new HashSet<>(); Arrays.stream(test.groups()).forEach(group -> groups.add(group)); if (groups.contains("fast")) { result.add(0, method); } else { result.add(method); } }); return result; } }
public class App { @Test public void test_1() { System.out.println("first to run"); } @Test(groups = {"fast"}) public void test_2() { System.out.println("second to run"); } @Test void test_3() { System.out.println("third to run"); } } --------------------------------- second to run first to run third to run
覆寫onStart 和 onFinish方法,分別對應suite開始階段和結束階段
對應測試方法的7種狀態:
實現ITestListener接口,須要覆寫上述7種方法,比較麻煩
所以實際偏向於繼承TestListenerAdapter
獲取testng執行結果,與html模板結合能夠定製測試報告
public class MyReporter implements IReporter { @Override public void generateReport(List<XmlSuite> xmlSuites, List<ISuite> suites, String outputDirectory) { suites.forEach(suite -> { System.out.println("測試方法以下:"); suite.getAllMethods().forEach(iTestNGMethod -> System.out.println("\t" + iTestNGMethod.getMethodName())); System.out.println("報告輸出路徑:" + suite.getOutputDirectory()); suite.getResults().values().forEach(iSuiteResult -> { ITestContext iTestContext = iSuiteResult.getTestContext(); Set<ITestResult> passedTests = iTestContext.getPassedTests().getAllResults(); System.out.println("執行成功的方法:" + passedTests.size()); passedTests.forEach(iTestResult -> { System.out.println("\t" + iTestResult.getName()); System.out.println("\t\t開始時間:" + iTestResult.getStartMillis()); System.out.println("\t\t結束時間:" + iTestResult.getEndMillis()); }); Set<ITestResult> failedTests = iTestContext.getFailedTests().getAllResults(); System.out.println("執行失敗的方法:" + failedTests.size()); failedTests.forEach(iTestResult -> { System.out.println("\t" + iTestResult.getName()); System.out.println("\t\t開始時間:" + iTestResult.getStartMillis()); System.out.println("\t\t結束時間:" + iTestResult.getEndMillis()); }); }); }); } }
@Listeners({MyReporter.class}) public class App { @Test public void test_1() { System.out.println("first to run"); } @Test public void test_2() { System.out.println("second to run"); } @Test public void test_3() { Assert.assertTrue(false); } } ------------------------ 測試方法以下: test_1 test_2 test_3 報告輸出路徑:E:\code\java\lab\test-output\Default Suite 執行成功的方法:2 test_2 開始時間:1541921094204 結束時間:1541921094204 test_1 開始時間:1541921094188 結束時間:1541921094188 執行失敗的方法:1 test_3 開始時間:1541921094204 結束時間:1541921094204