- 加入相關的依賴
<!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java --> <dependency> <groupId>org.seleniumhq.selenium</groupId> <artifactId>selenium-java</artifactId> <version>2.53.1</version> </dependency> <!-- https://mvnrepository.com/artifact/org.testng/testng --> <dependency> <groupId>org.testng</groupId> <artifactId>testng</artifactId> <version>6.9.10</version> <!-- <scope>test</scope> --> </dependency> <!-- https://mvnrepository.com/artifact/com.relevantcodes/extentreports --> <dependency> <groupId>com.relevantcodes</groupId> <artifactId>extentreports</artifactId> <version>2.41.2</version> </dependency>
-
- 分別創建 ExtentReport.html,BaseTestForExtentReport.java,ExtentReportFactory.java
- ExtentReport.html可放置在項目根目錄下(報告中的部分內容會根據生成的具體內容而改變,不礙事)
<!DOCTYPE html> <html> <head> <!-- ExtentReports Library 2.41.1 | http://relevantcodes.com/extentreports-for-selenium/ | https://github.com/anshooarora/ Copyright (c) 2015, Anshoo Arora (Relevant Codes) | Copyrights licensed under the New BSD License | http://opensource.org/licenses/BSD-3-Clause Documentation: http://extentreports.relevantcodes.com --> <meta charset='UTF-8' /> <meta name='description' content='ExtentReports (by Anshoo Arora) is a reporting library for automation testing for .NET and Java. It creates detailed and beautiful HTML reports for modern browsers. ExtentReports shows test and step summary along with dashboards, system and environment details for quick analysis of your tests.' /> <meta name='robots' content='noodp, noydir' /> <meta name='viewport' content='width=device-width, initial-scale=1' /> <meta name='extentx' id='extentx' content='' /> <title> ExtentReports 2.0 </title> <link href='https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,600' rel='stylesheet' type='text/css'> <link href='https://cdn.rawgit.com/anshooarora/extentreports/6032d73243ba4fe4fb8769eb9c315d4fdf16fe68/cdn/extent.css' type='text/css' rel='stylesheet' /> <style> </style> </head> <body class='extent default standard hide-overflow'> <!-- nav --> <nav> <div class='logo-container blue darken-2'> <a class='logo-content' href='http://extentreports.relevantcodes.com'> <span>ExtentReports</span> </a> <a href='#' data-activates='slide-out' class='button-collapse hide-on-large-only'><i class='mdi-navigation-apps'></i></a> </div> <ul id='slide-out' class='side-nav fixed hide-on-med-and-down'> <li class='analysis waves-effect active'><a href='#!' class='test-view' onclick="_updateCurrentStage(0)"><i class='mdi-action-dashboard'></i>Test Details</a></li> <li class='analysis waves-effect'> <a href='#!' onclick="_updateCurrentStage(-1)" class='dashboard-view'><i class='mdi-action-track-changes'></i></i>Analysis</a> </li> </ul> <span class='report-name'>Automation Report</span> <span class='report-headline'></span> <ul class='right hide-on-med-and-down nav-right'> <li class='theme-selector' alt='Click to toggle dark theme. To enable by default, use js configuration $("body").addClass("dark");' title='Click to toggle dark theme. To enable by default, use js configuration $("body").addClass("dark");'> <i class='mdi-hardware-desktop-windows'></i> </li> <li> <span class='suite-started-time'>2017-07-28 10:44:39</span> </li> <li> <span>v2.41.1</span> </li> </ul> </nav> <!-- /nav --> <!-- container --> <div class='container'> <!-- dashboard --> <div id='dashboard-view' class='row'> <div class='time-totals'> <div class='col l2 m4 s6'> <div class='card suite-total-tests'> <span class='panel-name'>Total Tests</span> <span class='total-tests'> <span class='panel-lead'></span> </span> </div> </div> <div class='col l2 m4 s6'> <div class='card suite-total-steps'> <span class='panel-name'>Total Steps</span> <span class='total-steps'> <span class='panel-lead'></span> </span> </div> </div> <div class='col l2 m4 s12'> <div class='card suite-total-time-current'> <span class='panel-name'>Total Time Taken (Current Run)</span> <span class='suite-total-time-current-value panel-lead'>0h 0m 2s+599ms</span> </div> </div> <div class='col l2 m4 s12'> <div class='card suite-total-time-overall'> <span class='panel-name'>Total Time Taken (Overall)</span> <span class='suite-total-time-overall-value panel-lead'>0h 0m 2s+599ms</span> </div> </div> <div class='col l2 m4 s6 suite-start-time'> <div class='card accent green-accent'> <span class='panel-name'>Start</span> <span class='panel-lead suite-started-time'>2017-07-28 10:44:36</span> </div> </div> <div class='col l2 m4 s6 suite-end-time'> <div class='card accent pink-accent'> <span class='panel-name'>End</span> <span class='panel-lead suite-ended-time'>2017-07-28 10:44:39</span> </div> </div> </div> <div class='charts'> <div class='col s12 m6 l4 fh'> <div class='card-panel'> <div> <span class='panel-name'>Tests View</span> </div> <div class='panel-setting modal-trigger test-count-setting right'> <a href='#test-count-setting'><i class='mdi-navigation-more-vert text-md'></i></a> </div> <div class='chart-box'> <canvas class='text-centered' id='test-analysis'></canvas> </div> <div> <span class='weight-light'><span class='t-pass-count weight-normal'></span> test(s) passed</span> </div> <div> <span class='weight-light'><span class='t-fail-count weight-normal'></span> test(s) failed, <span class='t-others-count weight-normal'></span> others</span> </div> </div> </div> <div class='col s12 m6 l4 fh'> <div class='card-panel'> <div> <span class='panel-name'>Steps View</span> </div> <div class='panel-setting modal-trigger step-status-filter right'> <a href='#step-status-filter'><i class='mdi-navigation-more-vert text-md'></i></a> </div> <div class='chart-box'> <canvas class='text-centered' id='step-analysis'></canvas> </div> <div> <span class='weight-light'><span class='s-pass-count weight-normal'></span> step(s) passed </span> </div> <div> <span class='weight-light'><span class='s-fail-count weight-normal'></span> step(s) failed, <span class='s-others-count weight-normal'></span> others</span> </div> </div> </div> <div class='col s12 m12 l4 fh'> <div class='card-panel'> <span class='panel-name'>Pass Percentage</span> <span class='pass-percentage panel-lead'></span> <div class='progress light-blue lighten-3'> <div class='determinate light-blue'></div> </div> </div> </div> </div> <div class='system-view'> <div class='col l4 m12 s12'> <div class='card-panel'> <span class='label info outline right'>Environment</span> <table> <thead> <tr> <th>Param</th> <th>Value</th> </tr> </thead> <tbody> <tr> <td>User Name</td> <td>Administrator</td> </tr> <tr> <td>OS</td> <td>Windows 7</td> </tr> <tr> <td>Java Version</td> <td>1.8.0_31</td> </tr> <tr> <td>Host Name</td> <td>USER-20160621RS</td> </tr> </tbody> </table> </div> </div> </div> </div> <!-- /dashboard --> <!-- tests --> <div id='test-view' class='row _addedTable'> <div class='col _addedCell1'> <div class='contents'> <div class='card-panel heading'> <h5>Tests</h5> </div> <div class='card-panel filters'> <div> <a class='dropdown-button btn-floating btn-small waves-effect waves-light grey tests-toggle' data-activates='tests-toggle' data-constrainwidth='true' data-beloworigin='true' data-hover='true' href='#'> <i class='mdi-action-reorder'></i> </a> <ul id='tests-toggle' class='dropdown-content'> <li class='pass'><a href='#!'>Pass</a></li> <li class='fail'><a href='#!'>Fail</a></li> <li class='skip'><a href='#!'>Skip</a></li> <li class='divider'></li> <li class='clear'><a href='#!'>Clear Filters</a></li> </ul> </div> <div> <a class='btn-floating btn-small waves-effect waves-light grey' id='clear-filters' alt='Clear Filters' title='Clear Filters'> <i class='mdi-navigation-close'></i> </a> </div> <div> <a class='btn-floating btn-small waves-effect waves-light grey' id='enableDashboard' alt='Enable Dashboard' title='Enable Dashboard'> <i class='mdi-action-track-changes'></i> </a> </div> <div> <a class='btn-floating btn-small waves-effect waves-light blue enabled' id='refreshCharts' alt='Refresh Charts on Filters' title='Refresh Charts on Filters'> <i class='mdi-navigation-refresh'></i> </a> </div> <div class='search' alt='Search Tests' title='Search Tests'> <div class='input-field left'> <input id='searchTests' type='text' class='validate' placeholder='Search Tests...'> </div> <a href="#" class='btn-floating btn-small waves-effect waves-light grey'> <i class='mdi-action-search'></i> </a> </div> </div> <div class='card-panel no-padding-h no-padding-v no-margin-v'> <div class='wrapper'> <ul id='test-collection' class='test-collection'> <li class='collection-item test displayed active fail ' extentid='6e942abd-51ee-4fea-98c7-c55051c26086'> <div class='test-head'> <span class='test-name'>testLogin() </span> <span class='test-status label right outline capitalize fail'>fail</span> <span class='category-assigned hide '></span> </div> <div class='test-body'> <div class='test-info'> <span title='Test started time' alt='Test started time' class='test-started-time label green lighten-1 text-white'>2017-07-28 10:44:36</span> <span title='Test ended time' alt='Test ended time' class='test-ended-time label red lighten-1 text-white'>2017-07-28 10:44:38</span> <span title='Time taken to finish' alt='Time taken to finish' class='test-time-taken label blue-grey lighten-3 text-white'>0h 0m 2s+60ms</span> </div> <div class='test-desc'>登錄QQ郵箱</div> <div class='test-attributes'> </div> <div class='test-steps'> <table class='bordered table-results'> <thead> <tr> <th>Status</th> <th>Timestamp</th> <th>Details</th> </tr> </thead> <tbody> <tr> <td class='status info' title='info' alt='info'><i class='mdi-action-info-outline'></i></td> <td class='timestamp'>10:44:36</td> <td class='step-details'>開始測試 :testLogin()</td> </tr> <tr> <td class='status info' title='info' alt='info'><i class='mdi-action-info-outline'></i></td> <td class='timestamp'>10:44:38</td> <td class='step-details'>結束測試:testLogin()</td> </tr> <tr> <td class='status fail' title='fail' alt='fail'><i class='mdi-navigation-cancel'></i></td> <td class='timestamp'>10:44:38</td> <td class='step-details'>測試失敗: Unable to locate element: {"method":"xpath","selector":".//*[@id='SetInfo']/div[1]/a[3]"} Command duration or timeout: 29 milliseconds For documentation on this error, please visit: http://seleniumhq.org/exceptions/no_such_element.html Build info: version: '2.53.1', revision: 'a36b8b1cd5757287168e54b817830adce9b0158d', time: '2016-06-30 19:26:09' System info: host: 'USER-20160621RS', ip: '169.254.149.235', os.name: 'Windows 7', os.arch: 'amd64', os.version: '6.1', java.version: '1.8.0_31' Driver info: org.openqa.selenium.firefox.FirefoxDriver Capabilities [{applicationCacheEnabled=true, rotatable=false, handlesAlerts=true, databaseEnabled=true, version=46.0, platform=WINDOWS, nativeEvents=false, acceptSslCerts=true, webStorageEnabled=true, locationContextEnabled=true, browserName=firefox, takesScreenshot=true, javascriptEnabled=true, cssSelectorsEnabled=true}] Session ID: 976828ac-1caa-46a1-8368-b6a5f375e85d *** Element info: {Using=xpath, value=.//*[@id='SetInfo']/div[1]/a[3]}</td> </tr> </tbody> </table> <ul class='collapsible node-list' data-collapsible='accordion'> </ul> </div> </div> </li> </ul> </div> </div> </div> </div> <div id='test-details-wrapper' class='col _addedCell2'> <div class='contents'> <div class='card-panel details-view'> <h5 class='details-name'></h5> <div class='step-filters right'> <span class='btn-floating btn-small waves-effect waves-light blue' status='info' alt='info' title='info'><i class='mdi-action-info-outline'></i></span> <span class='btn-floating btn-small waves-effect waves-light green' status='pass' alt='pass' title='pass'><i class='mdi-action-check-circle'></i></span> <span class='btn-floating btn-small waves-effect waves-light red' status='fail' alt='fail' title='fail'><i class='mdi-navigation-cancel'></i></span> <span class='btn-floating btn-small waves-effect waves-light red darken-4' status='fatal' alt='fatal' title='fatal'><i class='mdi-navigation-cancel'></i></span> <span class='btn-floating btn-small waves-effect waves-light red lighten-2' status='error' alt='error' title='error'><i class='mdi-alert-error'></i></span> <span class='btn-floating btn-small waves-effect waves-light orange' alt='warning' status='warning' title='warning'><i class='mdi-alert-warning'></i></span> <span class='btn-floating btn-small waves-effect waves-light cyan' status='skip' alt='skip' title='skip'><i class='mdi-content-redo'></i></span> <span class='btn-floating btn-small waves-effect waves-light grey darken-2' status='clear-step-filter' alt='Clear filters' title='Clear filters'><i class='mdi-content-clear'></i></span> </div> <div class='details-container'> </div> </div> </div> </div> </div> <!-- /tests --> <!-- categories --> <!-- /categories --> <!-- exceptions --> <!-- /exceptions --> <!-- testrunner logs --> <!-- /testrunner logs --> </div> <!-- /container --> <!-- test dashboard counts setting --> <div id='test-count-setting' class='modal bottom-sheet'> <div class='modal-content'> <h5>Configure Tests Count Setting</h5> <input name='test-count-setting' type='radio' id='parentWithoutNodes' class='with-gap'> <label for='parentWithoutNodes'>Parent Tests Only (Does not include child nodes in counts)</label> <br> <input name='test-count-setting' type='radio' id='parentWithoutNodesAndNodes' class='with-gap'> <label for='parentWithoutNodesAndNodes'>Parent Tests Without Child Tests + Child Tests</label> <br> <input name='test-count-setting' type='radio' id='childNodes' class='with-gap'> <label for='childNodes'>Child Tests Only</label> </div> <div class='modal-footer'> <a href='#!' class='modal-action modal-close waves-effect waves-green btn'>Save</a> </div> </div> <!-- /test dashboard counts setting --> <!-- filter for step status --> <div id='step-status-filter' class='modal bottom-sheet'> <div class='modal-content'> <h5>Select status</h5> <input checked class='filled-in' type='checkbox' id='step-dashboard-filter-pass'> <label for='step-dashboard-filter-pass'>Pass</label> <br> <input checked class='filled-in' type='checkbox' id='step-dashboard-filter-fail'> <label for='step-dashboard-filter-fail'>Fail</label> <br> <input checked class='filled-in' type='checkbox' id='step-dashboard-filter-fatal'> <label for='step-dashboard-filter-fatal'>Fatal</label> <br> <input checked class='filled-in' type='checkbox' id='step-dashboard-filter-error'> <label for='step-dashboard-filter-error'>Error</label> <br> <input checked class='filled-in' type='checkbox' id='step-dashboard-filter-warning'> <label for='step-dashboard-filter-warning'>Warning</label> <br> <input checked class='filled-in' type='checkbox' id='step-dashboard-filter-skip'> <label for='step-dashboard-filter-skip'>Skipped</label> <br> <input checked class='filled-in' type='checkbox' id='step-dashboard-filter-info'> <label for='step-dashboard-filter-info'>Info</label> <br> <input checked class='filled-in' type='checkbox' id='step-dashboard-filter-unknown'> <label for='step-dashboard-filter-unknown'>Unknown</label> </div> <div class='modal-footer'> <a href='#!' class='modal-action modal-close waves-effect waves-green btn'>Save</a> </div> </div> <!-- /filter for step status --> <script src='https://cdn.rawgit.com/anshooarora/extentreports/6032d73243ba4fe4fb8769eb9c315d4fdf16fe68/cdn/extent.js' type='text/javascript'></script> <script>$(document).ready(function() { $('.logo span').html('ExtentReports'); });</script> <script> $(document).ready(function() { }); </script> </body> </html>
- BaseTestForExtentReport.java,
package com.lozz.base; import java.lang.reflect.Method; import org.apache.log4j.PropertyConfigurator; import org.openqa.selenium.WebDriver; import org.openqa.selenium.firefox.FirefoxDriver; import org.testng.IHookCallBack; import org.testng.IHookable; import org.testng.ITestResult; import org.testng.annotations.AfterMethod; import org.testng.annotations.AfterSuite; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import com.lozz.utils.Constant; import com.lozz.utils.ExtentReportFactory; import com.relevantcodes.extentreports.ExtentTest; import com.relevantcodes.extentreports.LogStatus; /** * @Title: BaseTestForExtentReport.java * @Package com.lozz.base * @Description: TODO(用一句話描述該文件做什么) * @date 2017年7月28日 上午9:35:36 * @version V1.0 */ public class BaseTestForExtentReport implements IHookable { protected WebDriver driver; final String AUT_URL = Constant.Url; protected ExtentTest testReporter; @BeforeMethod public void initDriver(Method method) { // TODO 配置 // PropertyConfigurator.configure("D:\\seleniumproject\\com.lozz.SeleniumProject\\log4j.properties"); driver = new FirefoxDriver(); driver.manage().window().maximize(); driver.get(AUT_URL); } @AfterMethod(alwaysRun = true) public void cleanUp(ITestResult result, Method method) { // TODO Auto-generated method stub String testName = getTestName(result); testReporter.log(LogStatus.INFO, "結束測試:" + testName); if (result.getStatus() == ITestResult.FAILURE) { testReporter.log(LogStatus.FAIL, "測試失敗: " + result.getThrowable().getMessage()); } else if (result.getStatus() == ITestResult.SUCCESS) { testReporter.log(LogStatus.PASS, "測試通過"); } else if (result.getStatus() == ITestResult.SKIP) { testReporter.log(LogStatus.SKIP, "跳過測試"); } else { testReporter.log(LogStatus.ERROR, "執行測試時出錯"); } testReporter = null; ExtentReportFactory.closeTest(testName); driver.close(); } /** * @param result * @return */ private String getTestName(ITestResult testResult) { // TODO Auto-generated method stub String name = testResult.getName(); Object[] parameters = testResult.getParameters(); StringBuilder testName = new StringBuilder(); testName.append(name); testName.append("("); for (int i = 0; i < parameters.length; i++) { testName.append("[" + parameters[i].toString() + "]"); if (i != parameters.length - 1) { testName.append(","); } } testName.append(")"); return testName.toString(); } @AfterSuite public void afterSuite() { // TODO Auto-generated method stub ExtentReportFactory.closeReport(); } public void run(IHookCallBack callBack, ITestResult testResult){ String description = testResult.getMethod().getConstructorOrMethod().getMethod().getAnnotation(Test.class).description(); String testName = getTestName(testResult); ExtentReportFactory.getTest(testName,description); testReporter = ExtentReportFactory.getTest(); testReporter.log(LogStatus.INFO, "開始測試 :"+ testName); System.out.println("執行的方法: "+ testName); callBack.runTestMethod(testResult); } }
- ExtentReportFactory.java
package com.lozz.utils; import java.util.HashMap; import java.util.Map; import com.relevantcodes.extentreports.DisplayOrder; import com.relevantcodes.extentreports.ExtentReports; import com.relevantcodes.extentreports.ExtentTest; /** * @Title: ExtentReportFactory.java * @Package com.lozz.utils * @Description: TODO(用一句話描述該文件做什么) * @date 2017年7月28日 上午9:16:15 * @version V1.0 */ public class ExtentReportFactory { public static ExtentReports reporter; public static Map<Long, String> threadToExtentTestMap = new HashMap<Long, String>(); public static Map<String, ExtentTest> nameToTestMap = new HashMap<String, ExtentTest>(); private synchronized static ExtentReports getExtentReport() { if (reporter == null) { reporter = new ExtentReports("ExtentReport.html", true, DisplayOrder.NEWEST_FIRST); } return reporter; } public synchronized static ExtentTest getTest(String testName, String testDescription) { if (!nameToTestMap.containsKey(testName)) { Long threadID = Thread.currentThread().getId(); ExtentTest test = getExtentReport().startTest(testName, testDescription); nameToTestMap.put(testName, test); threadToExtentTestMap.put(threadID, testName); } return nameToTestMap.get(testName); } public synchronized static ExtentTest getTest(String testName) { return getTest(testName, ""); } public synchronized static ExtentTest getTest() { Long threadID = Thread.currentThread().getId(); if (threadToExtentTestMap.containsKey(threadID)) { String testName = threadToExtentTestMap.get(threadID); return nameToTestMap.get(testName); } return null; } public synchronized static void closeTest(String testName) { if (!testName.isEmpty()) { ExtentTest test = getTest(testName); getExtentReport().endTest(test); } } public synchronized static void closeTest(ExtentTest test) { if (test != null) { getExtentReport().endTest(test); } } public synchronized static void closeTest() { ExtentTest test = getTest(); closeTest(test); } public synchronized static void closeReport() { if (reporter != null) { reporter.flush(); reporter.close(); } } }
2.另外一種方法:
- 同樣是在maven的pom文件中添加相同的依賴
- 添加extent-config.xml用來配置報告的相關樣式
<?xml version="1.0" encoding="UTF-8"?> <extentreports> <configuration> <theme>standard</theme> <encoding>UTF-8</encoding> <protocal>https</protocal> <documentTitle>自動化測試報告 - v1.0.0</documentTitle> <reportName>api自動化測試報告</reportName> <reportHeadline> - v1.0.0</reportHeadline> <dataFormat>yyyy-MM-dd</dataFormat> <timeFormat>HH:mm:ss</timeFormat> <scripts> <![CDATA[ $(document).ready(function(){ }); ]]> </scripts> <styles> <![CDATA[ ]]> </styles> </configuration> </extentreports>
在類文件中配置報告的相關內容
轉載,還請說明來源