之前的一篇文章中,是把extentreports 的報告的初始方法寫在driver的初始方法中,寫報告的方法在testng的 onTest中,這次將這些方法全都拆出來,寫在一個方法類中,這個類重現實現了 testng IReporter接口中的 generateReport 方法同時加入了失敗自動截圖方法。
1.首先說一下自動截圖方法的實現
截圖實現類:
package seleniumstudy.utils; import java.io.File; import java.io.IOException; import org.apache.commons.io.FileUtils; import org.openqa.selenium.OutputType; import org.openqa.selenium.TakesScreenshot; public class ScreenScr { public static void getScreen(TakesScreenshot driver,String filename){ String cyrPatn=System.getProperty("user.dir"); File scrfile=driver.getScreenshotAs(OutputType.FILE); try { FileUtils.copyFile(scrfile, new File(cyrPatn+"\\img\\"+filename+".png")); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); System.out.println("GetScreenshot Fail"); }finally{ System.out.println("GetScreenshot Successful"+cyrPatn+"\\img\\"+filename+".png"); } } }
為了在testng 的監聽中調用截圖方法,所以封裝了一個BaseTestcase類 。
BaseTestcase類:
import seleniumstudy.utils.ScreenScr; import io.appium.java_client.AppiumDriver; import io.appium.java_client.TouchAction; public class BaseTestcase { public AppiumDriver driver; public void setdriver(AppiumDriver driver){ this.driver=driver; } public void takescreen(String filename){ ScreenScr.getScreen(driver, filename); } }
重寫的testnglistener類:
package seleniumstudy.utils; import org.apache.log4j.Logger; import org.testng.ITestContext; import org.testng.ITestResult; import org.testng.TestListenerAdapter; import seleniumstudy.testcase.BaseTestcase; import seleniumstudy.testcase.InitDriverCase; import com.relevantcodes.extentreports.ExtentReports; import com.relevantcodes.extentreports.ExtentTest; import com.relevantcodes.extentreports.LogStatus; public class TestngListener extends TestListenerAdapter { private Logger logger = Logger.getLogger(TestngListener.class); // protected ExtentReports extent; // protected ExtentTest test; @Override public void onTestStart(ITestResult tr) { super.onTestStart(tr); logger.info("【" + tr.getName() + " Start】"); // extent=InitDriverCase.getextent(); // test= extent.startTest(tr.getName()); } @Override public void onTestFailure(ITestResult tr) { super.onTestFailure(tr); logger.info("【" + tr.getName() + " Failure】"); takeScreenShot(tr); // test.log(LogStatus.INFO,"TakesScreenshot ",test.addScreenCapture("../img/"+tr.getName()+".png")); // test.log(LogStatus.FAIL, tr.getThrowable()); // extent.endTest(test); } public void takeScreenShot(ITestResult tr){ BaseTestcase baseTestcase=(BaseTestcase)tr.getInstance(); baseTestcase.takescreen(tr.getName()); } @Override public void onTestSkipped(ITestResult tr) { super.onTestSkipped(tr); takeScreenShot(tr); logger.info("【" + tr.getName() + " Skipped】"); // test.log(LogStatus.SKIP, "SKIP"); // extent.endTest(test); } @Override public void onTestSuccess(ITestResult tr) { super.onTestSuccess(tr); logger.info("【" + tr.getName() + " Success】"); // test.log(LogStatus.PASS, "Pass"); // extent.endTest(test); } @Override public void onFinish(ITestContext testContext) { super.onFinish(testContext); } }
實現extentreports生成的監聽類ExtentReporterNGListener:
package seleniumstudy.utils; import java.io.File; import java.util.Calendar; import java.util.Date; import java.util.List; import java.util.Map; import org.testng.IReporter; import org.testng.IResultMap; import org.testng.ISuite; import org.testng.ISuiteResult; import org.testng.ITestContext; import org.testng.ITestResult; import org.testng.xml.XmlSuite; import com.relevantcodes.extentreports.DisplayOrder; import com.relevantcodes.extentreports.ExtentReports; import com.relevantcodes.extentreports.ExtentTest; import com.relevantcodes.extentreports.LogStatus; import com.relevantcodes.extentreports.ReporterType; public class ExtentReporterNGListener implements IReporter{ private ExtentReports extent; @Override public void generateReport(List<XmlSuite> xmlSuites, List<ISuite> suites, String outputDirectory){ // true為覆蓋已經生成的報告 extent = new ExtentReports(outputDirectory + File.separator + "Extent.html", true // true為覆蓋已經生成的報告,false 在已有的報告上面生成,不會覆蓋舊的結果 ,DisplayOrder.NEWEST_FIRST // 最新運行的用例結果在第一個 ); extent.startReporter(ReporterType.DB, outputDirectory + File.separator + "Extent.html"); //生成本地的DB數據文件 for (ISuite suite : suites) { Map<String, ISuiteResult> result = suite.getResults(); for (ISuiteResult r : result.values()) { ITestContext context = r.getTestContext(); buildTestNodes(context.getPassedTests(), LogStatus.PASS); buildTestNodes(context.getFailedTests(), LogStatus.FAIL); buildTestNodes(context.getSkippedTests(), LogStatus.SKIP); } } extent.flush(); extent.close(); } private void buildTestNodes(IResultMap tests, LogStatus status) { ExtentTest test; if (tests.size() > 0) { for (ITestResult result : tests.getAllResults()) { test = extent.startTest(result.getMethod().getMethodName()); test.setStartedTime(getTime(result.getStartMillis())); test.setEndedTime(getTime(result.getEndMillis())); for (String group : result.getMethod().getGroups()) test.assignCategory(group); if (result.getThrowable() != null) { test.log(status, test.addScreenCapture("../img/"+result.getMethod().getMethodName()+".png")); test.log(status, result.getThrowable()); } else { test.log(status, "Test " + status.toString().toLowerCase() + "ed"); } extent.endTest(test); } } } private Date getTime(long millis) { Calendar calendar = Calendar.getInstance(); calendar.setTimeInMillis(millis); return calendar.getTime(); } }
testng.xml 文件配置:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd"> <suite name="Suite"> <listeners> <listener class-name="seleniumstudy.utils.TestngListener"></listener> <listener class-name="seleniumstudy.utils.ExtentReporterNGListener"></listener> </listeners> <test name="Test"> <classes> <class name="seleniumstudy.testcase.ExtenseReport"></class> </classes> </test> </suite>
最后生成的的報告會在 test-output 目錄下 Extent.html 中。