1. 程式人生 > >Java&Selenium&TestNG&ZTestReport 自動化測試並生成HTML自動化測試報告

Java&Selenium&TestNG&ZTestReport 自動化測試並生成HTML自動化測試報告

一、摘要

本篇博文將介紹如何藉助ZTestReport和HTML模版,生成HTML測試報告的ZTestReport 原始碼Clone地址為 https://github.com/zhangfei19841004/ztest,其中ZTestReport.java

和其template是我們需要的關鍵。

二、ZTestReport.java

根據我的需要,在原始碼基礎上進行了稍微修改,其中幾個註釋的地方需要注意,將其整合進自己的自動化框架時需要做相應的修改

package util;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.testng.*; import org.testng.xml.XmlSuite; import java.io.*; import java.text.SimpleDateFormat; import java.util.*; import java.util.regex.Matcher; public class TestReport implements IReporter { private long currentTime = System.currentTimeMillis(); private SimpleDateFormat formatter = new
SimpleDateFormat ("yyyy年-MM月-dd日-HH時mm分ss秒"); private Date date = new Date(currentTime); private String reportdate = formatter.format(date); // 定義生成測試報告的路徑和檔名,為相容Windows和Linux此處使用File.separator代替分隔符 private String path = System.getProperty("user.dir")+File.separator+reportdate+".html";
// 定義html樣式模板所在路徑 private String templatePath = System.getProperty("user.dir")+File.separator+"template"; private int testsPass = 0; private int testsFail = 0; private int testsSkip = 0; private String beginTime; private long totalTime; private String name = "PaaS平臺自動化測試"; /** public TestReport(){ long currentTime = System.currentTimeMillis(); SimpleDateFormat formatter = new SimpleDateFormat ("yyyy年-MM月-dd日-HH時mm分ss秒"); Date date = new Date(currentTime); name = formatter.format(date); } public TestReport(String name){ this.name = name; if(this.name==null){ long currentTime = System.currentTimeMillis(); SimpleDateFormat formatter = new SimpleDateFormat ("yyyy年-MM月-dd日-HH時mm分ss秒"); Date date = new Date(currentTime); this.name = formatter.format(date); } } */ @Override public void generateReport(List<XmlSuite> xmlSuites, List<ISuite> suites, String outputDirectory) { List<ITestResult> list = new ArrayList<ITestResult>(); for (ISuite suite : suites) { Map<String, ISuiteResult> suiteResults = suite.getResults(); for (ISuiteResult suiteResult : suiteResults.values()) { ITestContext testContext = suiteResult.getTestContext(); IResultMap passedTests = testContext.getPassedTests(); testsPass = testsPass + passedTests.size(); IResultMap failedTests = testContext.getFailedTests(); testsFail = testsFail + failedTests.size(); IResultMap skippedTests = testContext.getSkippedTests(); testsSkip = testsSkip + skippedTests.size(); IResultMap failedConfig = testContext.getFailedConfigurations(); list.addAll(this.listTestResult(passedTests)); list.addAll(this.listTestResult(failedTests)); list.addAll(this.listTestResult(skippedTests)); list.addAll(this.listTestResult(failedConfig)); } } this.sort(list); this.outputResult(list); } private ArrayList<ITestResult> listTestResult(IResultMap resultMap) { Set<ITestResult> results = resultMap.getAllResults(); return new ArrayList<ITestResult>(results); } private void sort(List<ITestResult> list) { Collections.sort(list, new Comparator<ITestResult>() { @Override public int compare(ITestResult r1, ITestResult r2) { if (r1.getStartMillis() > r2.getStartMillis()) { return 1; } else { return -1; } } }); } private void outputResult(List<ITestResult> list) { try { List<ReportInfo> listInfo = new ArrayList<ReportInfo>(); int index = 0; for (ITestResult result : list) { String tn = result.getTestContext().getCurrentXmlTest().getParameter("testCase"); if(index==0){ SimpleDateFormat formatter = new SimpleDateFormat ("yyyy-MM-dd HH:mm:ss"); beginTime = formatter.format(new Date(result.getStartMillis())); index++; } long spendTime = result.getEndMillis() - result.getStartMillis(); totalTime += spendTime; String status = this.getStatus(result.getStatus()); List<String> log = Reporter.getOutput(result); for (int i = 0; i < log.size(); i++) { log.set(i, log.get(i).replaceAll("\"", "\\\\\"")); } Throwable throwable = result.getThrowable(); if(throwable!=null){ log.add(throwable.toString().replaceAll("\"", "\\\\\"")); StackTraceElement[] st = throwable.getStackTrace(); for (StackTraceElement stackTraceElement : st) { log.add((" " + stackTraceElement).replaceAll("\"", "\\\\\"")); } } ReportInfo info = new ReportInfo(); info.setName(tn); info.setSpendTime(spendTime+"ms"); info.setStatus(status); info.setClassName(result.getInstanceName()); info.setMethodName(result.getName()); info.setDescription(result.getMethod().getDescription()); info.setLog(log); listInfo.add(info); } Map<String, Object> result = new HashMap<String, Object>(); result.put("testName", name); result.put("testPass", testsPass); result.put("testFail", testsFail); result.put("testSkip", testsSkip); result.put("testAll", testsPass+testsFail+testsSkip); result.put("beginTime", beginTime); result.put("totalTime", totalTime+"ms"); result.put("testResult", listInfo); Gson gson = new GsonBuilder().disableHtmlEscaping().setPrettyPrinting().create(); String template = this.read(templatePath); BufferedWriter output = new BufferedWriter( new OutputStreamWriter(new FileOutputStream(new File(path)),"UTF-8")); template = template.replaceFirst("\\$\\{resultData\\}", Matcher.quoteReplacement(gson.toJson(result))); output.write(template); output.flush(); output.close(); } catch (IOException e) { e.printStackTrace(); } } private String getStatus(int status) { String statusString = null; switch (status) { case 1: statusString = "成功"; break; case 2: statusString = "失敗"; break; case 3: statusString = "跳過"; break; default: break; } return statusString; } public static class ReportInfo { private String name; private String className; private String methodName; private String description; private String spendTime; private String status; private List<String> log; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getClassName() { return className; } public void setClassName(String className) { this.className = className; } public String getMethodName() { return methodName; } public void setMethodName(String methodName) { this.methodName = methodName; } public String getSpendTime() { return spendTime; } public void setSpendTime(String spendTime) { this.spendTime = spendTime; } public String getStatus() { return status; } public void setStatus(String status) { this.status = status; } public List<String> getLog() { return log; } public void setLog(List<String> log) { this.log = log; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } } private String read(String path) { File file = new File(path); InputStream is = null; StringBuffer sb = new StringBuffer(); try { is = new FileInputStream(file); int index = 0; byte[] b = new byte[1024]; while ((index = is.read(b)) != -1) { sb.append(new String(b, 0, index)); } return sb.toString(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { try { if (is != null) { is.close(); } } catch (IOException e) { e.printStackTrace(); } } return null; } }

三、template

template檔案是和ZTestReport.java一起使用的,他可以將TestNG的測試結果按照template的樣式轉換成HTML格式的報告

四、呼叫ZTestReport.java

方式一:在測試類新增監聽

package testscript;
import org.apache.log4j.xml.DOMConfigurator;
import org.openqa.selenium.*;
import org.testng.Assert;
import org.testng.annotations.*;
import util.KeyActionsUtil;
import static util.KeyActionsUtil.*;
import java.util.List;
import static appmodule.MysqlService.linkToMysqlPage;
import static util.KeyBoardUtil.pressTabKey;
import static util.LogUtil.info;
import static pageobject.resourcemanagement.MySQLService.*;
import static util.ScrollBarUtil.scrolltoBottom;
import static util.WaitElementUtil.sleep;
// @Listeners({util.TestReport.class})
public class Test_Mysql {

    static {
        DOMConfigurator.configure("log4j.xml");
    }
    @BeforeClass
    public void setUp()throws Exception {
        WebDriver driver = KeyActionsUtil.initBrowser("chrome");
        linkToMysqlPage(driver, "yangdawei", "alex005x");
        sleep(2000);
    }

    @Test(priority = 0, description = "測試建立mysql資料庫服務1CPU2G")
    public void test_CreateMysqlInstance() throws Exception {
        create_New_Instance_Button(driver).click();
        info("點選建立例項按鈕...");
        sleep(1000);
        info("等待3秒...");
        instance_Name_in_Create_Instance_Dialog(driver).sendKeys("automationtest");
        info("輸入例項名:automationtesta");
        sleep(1000);
        info("等待3秒...");
        //頁面存在相同屬性的元素,取所有放到list裡,用序號操作
        List<WebElement> radios = driver.findElements(By.className("el-radio-button__inner"));
        radios.get(1).click();
        sleep(1000);
        info("選擇資料庫版本5.7...");
        instance_Standard_in_Create_Instance_Dialog(driver).click();
        info("點選例項規格...");
        sleep(2000);
        info("等待2秒...");
        one_Core_two_GB(driver).click();
        info("選擇1CPU2GB...");
        storage_Space_in_Create_Instance_Dialog(driver).clear();
        info("清空儲存空間欄位...");
        storage_Space_in_Create_Instance_Dialog(driver).sendKeys("1");
        info("輸入1G....");
        scrolltoBottom(driver);
        sleep(2000);
        pressTabKey();
        outsideaccess_Checkbox_in_Create_Instance_Dialog(driver).click();
        info("選擇外部連結...");
        password_in_Create_Instance_Dialog(driver).sendKeys("111111");
        info("輸入密碼111111...");
        repassword_in_Create_Instance_Dialog(driver).sendKeys("111111");
        info("確認密碼111111...");
        description_in_Create_Instance_Dialog(driver).sendKeys("automationtest");
        info("描述資訊輸入automationtest");
        sleep(2000);
        submit_Button_in_Create_Instance_Dialog(driver).sendKeys(Keys.ENTER);
        info("確認建立...");
        sleep(2000);
        refresh_Button(driver).click();
        Assert.assertTrue(driver.getPageSource().contains("automationtest"));
        Assert.assertTrue(driver.getPageSource().contains("建立中"));
    }
    @Test(priority = 1, description = "重啟mysql服務")
    public void test_RestartMysqlInstance()throws Exception {
        operation_Button(driver).click();
        info("點選列表裡最後一列的...");
        sleep(2000);
        info("等待3秒...");
        operation_Restart_Button(driver).click();
        info("點選下拉選單中的重啟按鈕...");
        sleep(2000);
        info("等待3秒...");
        restart_Confirm_Button(driver).click();
        info("點選確定按鈕...");
        sleep(2000);
        info("等待3秒...");
        Assert.assertTrue(driver.getPageSource().contains("重啟請求成功"));
        Assert.assertTrue(driver.getPageSource().contains("重啟中"));
    }

    @Test(priority = 2, description = "管理mysql服務頁面")
    public void test_Review_Basic_Mysql_Info()throws Exception{
        operation_Button(driver).click();
        info("點選列表裡最後一列的...");
        sleep(2000);
        info("等待3秒...");
        operation_Manage_Button(driver).click();
        info("點選下拉選單裡的管理按鈕...");
        sleep(2000);
        info("等待三秒");
        assertString(driver,"基本資訊");
    }
    @Test(priority = 3, description = "管理mysql服務頁面")
    public void test_Review_Mysql_Link()throws Exception{
        database_Link_Tab(driver).click();
        sleep(2000);
        Assert.assertTrue(driver.getPageSource().contains("210.13.50.105"));
    }

    @Test(priority = 4,description = "檢視Mysql日誌")
    public void test_ReviewLog()throws Exception{
        operation_Button(driver).click();
        info("點選列表裡最後一列的...");
        sleep(2000);
        info("等待3秒...");
        operation_Log_Button(driver).click();
        info("點選下拉選單中的日誌按鈕...");
        sleep(2000);
        info("等待3秒...");
        extend_Button_in_Log_Page(driver).click();
        info("點選展開按鈕...");
        sleep(2000);
        info("等待3秒...");
        datefrom_in_Log_Page(driver).click();
        info("點選第一個日期空間,彈出下拉...");
        sleep(2000);
        info("等待3秒...");
        datefrom_by_Date_in_Log_Page(driver).clear();
        datefrom_by_Date_in_Log_Page(driver).sendKeys("2018-09-01");
        info("輸入日期”2018-09-01");
        sleep(2000);
        info("等待3秒...");
        datefrom_Sure_Button_in_Log_Page(driver).click();
        info("點選確定按鈕...");
        sleep(2000);
        info("等待3秒...");
        search_Button_in_Log_Page(driver).click();
        info("點選篩選按鈕...");
        sleep(2000);
        info("等待3秒...");
        Assert.assertTrue(driver.getPageSource().contains("Initializing database"));

    }

    @Test(priority = 5, description = "檢視Mysql服務監控")
    public void test_MonitorMysqlService()throws Exception{
        operation_Button(driver).click();
        info("點選列表裡最後一列的...");
        sleep(3000);
        info("等待3秒...");
        operation_Monitor_Button(driver).click();
        info("點選下拉選單裡的監控按鈕...");
        sleep(3000);
        info("等待3秒...");
    }

    @Test(priority = 6, description = "釋放mysql服務")
    public void test_ReleaseMysqlService()throws Exception{
        operation_Button(driver).click();
        info("點選列表裡最後一列的...");
        sleep(3000);
        info("等待3秒...");
        operation_Release_Button(driver).click();
        info("點選下拉選單裡的釋放按鈕...");
        sleep(3000);
        info("等待3秒...");
        release_Confirm_Button(driver).click();
        info("點選確定按鈕...");
        sleep(3000);
        info("等待3秒...");
        Assert.assertTrue(driver.getPageSource().contains("操作成功"));
        Assert.assertTrue(driver.getPageSource().contains("刪除中"));
    }

    @AfterClass
    public void afterMethod(){
        driver.quit();
    }
}

方式二:在testng.xml中新增監聽

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="All Test Suite" preserve-order="true" verbose="2" allow-return-values="true">
    <listeners>
        <listener class-name="org.uncommons.reportng.HTMLReporter" />
        <listener class-name="org.uncommons.reportng.JUnitXMLReporter" />
        <listener class-name="util.TestReport"/>
    </listeners>
    <suite-files>
        <suite-file path="testng-spacemanagement.xml"/>
        <suite-file path="testng-mysql.xml"/>
    </suite-files>
</suite>

 五、報告樣式