之前的一篇文章中,是把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 中。