首頁>Program>source

TestNG生成可通過電子郵件發送的報告.我已经看到可以使用侦听器自定義此報告.但無法得到我想要的.我的要求是在此報告的摘要部分中包含其他详细資訊.我希望能够添加一个新表或額外的列来顯示測試執行的環境详细資訊。

尝試附加螢幕截圖,但顯然缺少某些內容,並且無法顯示。

最新回復
  • 11天前
    1 #

    這就是我在框架上所拥有的.我会尽力解釋(抱歉我的英語)

    複製ReporterListenerAdapter.java並重命名為MyReporterListenerAdapter.java,將其放在您的Java專案中(例如,/ listener檔案夹)

    public class MyReporterListenerAdapter implements IReporter {
    public void generateReport(List<XmlSuite> xml, List<ISuite> suites, String outdir) {}
    }
    

    接下来,複製ReporterListener.java並重命名為MyReporterListener.java

    在此處粘贴太多代碼,但是在createwriter函式上更改報告名稱.例如:" emailable-MyFramework-report"。

    MyReporterListener.java

    public class MyReporterListener extends MyReporterListenerAdapter {
        private static final Logger L = Logger.getLogger(MyReporterListener.class);
        // ~ Instance fields ------------------------------------------------------
        private PrintWriter m_out;
        private int m_row;
        private Integer m_testIndex;
        private int m_methodIndex;
        private Scanner scanner;
        // ~ Methods --------------------------------------------------------------
        /** Creates summary of the run */
        @Override
        public void generateReport(List<XmlSuite> xml, List<ISuite> suites,
                String outdir) {
            try {
                m_out = createWriter(outdir);
            } catch (IOException e) {
                L.error("output file", e);
                return;
            }
            startHtml(m_out);
            generateSuiteSummaryReport(suites);
            generateMethodSummaryReport(suites);
            generateMethodDetailReport(suites);
            endHtml(m_out);
            m_out.flush();
            m_out.close();
        }
        protected PrintWriter createWriter(String outdir) throws IOException {
            java.util.Date now = new Date();
            new File(outdir).mkdirs();
            return new PrintWriter(new BufferedWriter(new FileWriter(new File(
                    outdir, "emailable-FON-report"
                            + DateFunctions.dateToDayAndTimeForFileName(now)
                            + ".html"))));
        }
        /**
         * Creates a table showing the highlights of each test method with links to
         * the method details
         */
        protected void generateMethodSummaryReport(List<ISuite> suites) {
            m_methodIndex = 0;
            startResultSummaryTable("methodOverview");
            int testIndex = 1;
            for (ISuite suite : suites) {
                if (suites.size() > 1) {
                    titleRow(suite.getName(), 5);
                }
                Map<String, ISuiteResult> r = suite.getResults();
                for (ISuiteResult r2 : r.values()) {
                    ITestContext testContext = r2.getTestContext();
                    String testName = testContext.getName();
                    m_testIndex = testIndex;
                    resultSummary(suite, testContext.getFailedConfigurations(),
                            testName, "failed", " (configuration methods)");
                    resultSummary(suite, testContext.getFailedTests(), testName,
                            "failed", "");
                    resultSummary(suite, testContext.getSkippedConfigurations(),
                            testName, "skipped", " (configuration methods)");
                    resultSummary(suite, testContext.getSkippedTests(), testName,
                            "skipped", "");
                    resultSummary(suite, testContext.getPassedTests(), testName,
                            "passed", "");
                    testIndex++;
                }
            }
            m_out.println("</table>");
        }
        /** Creates a section showing known results for each method */
        protected void generateMethodDetailReport(List<ISuite> suites) {
            m_methodIndex = 0;
            for (ISuite suite : suites) {
                Map<String, ISuiteResult> r = suite.getResults();
                for (ISuiteResult r2 : r.values()) {
                    ITestContext testContext = r2.getTestContext();
                    if (r.values().size() > 0) {
                        m_out.println("<h1>" + testContext.getName() + "</h1>");
                    }
                    resultDetail(testContext.getFailedConfigurations());
                    resultDetail(testContext.getFailedTests());
                    resultDetail(testContext.getSkippedConfigurations());
                    resultDetail(testContext.getSkippedTests());
                    resultDetail(testContext.getPassedTests());
                }
            }
        }
        /**
         * @param tests
         */
        private void resultSummary(ISuite suite, IResultMap tests, String testname,
                String style, String details) {
            if (tests.getAllResults().size() > 0) {
                StringBuffer buff = new StringBuffer();
                String lastClassName = "";
                int mq = 0;
                int cq = 0;
                for (ITestNGMethod method : getMethodSet(tests, suite)) {
                    m_row += 1;
                    m_methodIndex += 1;
                    ITestClass testClass = method.getTestClass();
                    String className = testClass.getName();
                    if (mq == 0) {
                        String id = (m_testIndex == null ? null : "t"
                                + Integer.toString(m_testIndex));
                        titleRow(testname + " &#8212; " + style + details, 5, id);
                        m_testIndex = null;
                    }
                    if (!className.equalsIgnoreCase(lastClassName)) {
                        if (mq > 0) {
                            cq += 1;
                            m_out.print("<tr class=\"" + style
                                    + (cq % 2 == 0 ? "even" : "odd") + "\">"
                                    + "<td");
                            if (mq > 1) {
                                m_out.print(" rowspan=\"" + mq + "\"");
                            }
                            m_out.println(">" + lastClassName + "</td>" + buff);
                        }
                        mq = 0;
                        buff.setLength(0);
                        lastClassName = className;
                    }
                    Set<ITestResult> resultSet = tests.getResults(method);
                    long end = Long.MIN_VALUE;
                    long start = Long.MAX_VALUE;
                    for (ITestResult testResult : tests.getResults(method)) {
                        if (testResult.getEndMillis() > end) {
                            end = testResult.getEndMillis();
                        }
                        if (testResult.getStartMillis() < start) {
                            start = testResult.getStartMillis();
                        }
                    }
                    mq += 1;
                    if (mq > 1) {
                        buff.append("<tr class=\"" + style
                                + (cq % 2 == 0 ? "odd" : "even") + "\">");
                    }
                    String description = method.getDescription();
                    String testInstanceName = resultSet
                            .toArray(new ITestResult[] {})[0].getTestName();
                    buff.append("<td><a href=\"#m"
                            + m_methodIndex
                            + "\">"
                            + qualifiedName(method)
                            + " "
                            + (description != null && description.length() > 0 ? "(\""
                                    + description + "\")"
                                    : "")
                            + "</a>"
                            + (null == testInstanceName ? "" : "<br>("
                                    + testInstanceName + ")") + "</td>"
                            + "<td class=\"numi\">" + resultSet.size() + "</td>"
                            + "<td>" + start + "</td>" + "<td class=\"numi\">"
                            + (end - start) + "</td>" + "</tr>");
                }
                if (mq > 0) {
                    cq += 1;
                    m_out.print("<tr class=\"" + style
                            + (cq % 2 == 0 ? "even" : "odd") + "\">" + "<td");
                    if (mq > 1) {
                        m_out.print(" rowspan=\"" + mq + "\"");
                    }
                    m_out.println(">" + lastClassName + "</td>" + buff);
                }
            }
        }
        /** Starts and defines columns result summary table */
        private void startResultSummaryTable(String style) {
            tableStart(style, "summary");
            m_out.println("<tr><th>Class</th>"
                    + "<th>Method</th><th># of<br/>Scenarios</th><th>Start</th><th>Time<br/>(ms)</th></tr>");
            m_row = 0;
        }
        private String qualifiedName(ITestNGMethod method) {
            StringBuilder addon = new StringBuilder();
            String[] groups = method.getGroups();
            int length = groups.length;
            if (length > 0 && !"basic".equalsIgnoreCase(groups[0])) {
                addon.append("(");
                for (int i = 0; i < length; i++) {
                    if (i > 0) {
                        addon.append(", ");
                    }
                    addon.append(groups[i]);
                }
                addon.append(")");
            }
            return "<b>" + method.getMethodName() + "</b> " + addon;
        }
        private void resultDetail(IResultMap tests) {
            for (ITestResult result : tests.getAllResults()) {
                ITestNGMethod method = result.getMethod();
                m_methodIndex++;
                String cname = method.getTestClass().getName();
                m_out.println("<h2 id=\"m" + m_methodIndex + "\">" + cname + ":"
                        + method.getMethodName() + "</h2>");
                Set<ITestResult> resultSet = tests.getResults(method);
                generateForResult(result, method, resultSet.size());
                m_out.println("<p class=\"totop\"><a href=\"#summary\">back to summary</a></p>");
            }
        }
        /**
         * Write the first line of the stack trace
         * 
         * @param tests
         */
        private void getShortException(IResultMap tests) {
            for (ITestResult result : tests.getAllResults()) {
                m_methodIndex++;
                Throwable exception = result.getThrowable();
                List<String> msgs = Reporter.getOutput(result);
                boolean hasReporterOutput = msgs.size() > 0;
                boolean hasThrowable = exception != null;
                if (hasThrowable) {
                    boolean wantsMinimalOutput = result.getStatus() == ITestResult.SUCCESS;
                    if (hasReporterOutput) {
                        m_out.print("<h3>"
                                + (wantsMinimalOutput ? "Expected Exception"
                                        : "Failure") + "</h3>");
                    }
                    // Getting first line of the stack trace
                    String str = Utils.stackTrace(exception, true)[0];
                    scanner = new Scanner(str);
                    String firstLine = scanner.nextLine();
                    m_out.println(firstLine);
                }
            }
        }
        /**
         * Write all parameters
         * 
         * @param tests
         */
        private void getParameters(IResultMap tests) {
            for (ITestResult result : tests.getAllResults()) {
                m_methodIndex++;
                Object[] parameters = result.getParameters();
                boolean hasParameters = parameters != null && parameters.length > 0;
                if (hasParameters) {
                    for (Object p : parameters) {
                        m_out.println(Utils.escapeHtml(Utils.toString(p)) + " | ");
                    }
                }
            }
        }
        private void generateForResult(ITestResult ans, ITestNGMethod method,
                int resultSetSize) {
            Object[] parameters = ans.getParameters();
            boolean hasParameters = parameters != null && parameters.length > 0;
            if (hasParameters) {
                tableStart("result", null);
                m_out.print("<tr class=\"param\">");
                for (int x = 1; x <= parameters.length; x++) {
                    m_out.print("<th>Param." + x + "</th>");
                }
                m_out.println("</tr>");
                m_out.print("<tr class=\"param stripe\">");
                for (Object p : parameters) {
                    m_out.println("<td>" + Utils.escapeHtml(Utils.toString(p))
                            + "</td>");
                }
                m_out.println("</tr>");
            }
            List<String> msgs = Reporter.getOutput(ans);
            boolean hasReporterOutput = msgs.size() > 0;
            Throwable exception = ans.getThrowable();
            boolean hasThrowable = exception != null;
            if (hasReporterOutput || hasThrowable) {
                if (hasParameters) {
                    m_out.print("<tr><td");
                    if (parameters.length > 1) {
                        m_out.print(" colspan=\"" + parameters.length + "\"");
                    }
                    m_out.println(">");
                } else {
                    m_out.println("<div>");
                }
                if (hasReporterOutput) {
                    if (hasThrowable) {
                        m_out.println("<h3>Test Messages</h3>");
                    }
                    for (String line : msgs) {
                        m_out.println(line + "<br/>");
                    }
                }
                if (hasThrowable) {
                    boolean wantsMinimalOutput = ans.getStatus() == ITestResult.SUCCESS;
                    if (hasReporterOutput) {
                        m_out.println("<h3>"
                                + (wantsMinimalOutput ? "Expected Exception"
                                        : "Failure") + "</h3>");
                    }
                    generateExceptionReport(exception, method);
                }
                if (hasParameters) {
                    m_out.println("</td></tr>");
                } else {
                    m_out.println("</div>");
                }
            }
            if (hasParameters) {
                m_out.println("</table>");
            }
        }
        protected void generateExceptionReport(Throwable exception,
                ITestNGMethod method) {
            m_out.print("<div class=\"stacktrace\">");
            m_out.print(Utils.stackTrace(exception, true)[0]);
            m_out.println("</div>");
        }
        /**
         * Since the methods will be sorted chronologically, we want to return the
         * ITestNGMethod from the invoked methods.
         */
        private Collection<ITestNGMethod> getMethodSet(IResultMap tests,
                ISuite suite) {
            List<IInvokedMethod> r = Lists.newArrayList();
            List<IInvokedMethod> invokedMethods = suite.getAllInvokedMethods();
            for (IInvokedMethod im : invokedMethods) {
                if (tests.getAllMethods().contains(im.getTestMethod())) {
                    r.add(im);
                }
            }
            Arrays.sort(r.toArray(new IInvokedMethod[r.size()]), new TestSorter());
            List<ITestNGMethod> result = Lists.newArrayList();
            // Add all the invoked methods
            for (IInvokedMethod m : r) {
                result.add(m.getTestMethod());
            }
            // Add all the methods that weren't invoked (e.g. skipped) that we
            // haven't added yet
            for (ITestNGMethod m : tests.getAllMethods()) {
                if (!result.contains(m)) {
                    result.add(m);
                }
            }
            return result;
        }
        @SuppressWarnings("unused")
        public void generateSuiteSummaryReport(List<ISuite> suites) {
            tableStart("testOverview", null);
            m_out.print("<tr>");
            tableColumnStart("Test");
            tableColumnStart("Methods<br/>Passed");
            tableColumnStart("Scenarios<br/>Passed");
            tableColumnStart("# skipped");
            tableColumnStart("# failed");
            tableColumnStart("Error messages");
            tableColumnStart("Parameters");
            tableColumnStart("Start<br/>Time");
            tableColumnStart("End<br/>Time");
            tableColumnStart("Total<br/>Time");
            tableColumnStart("Included<br/>Groups");
            tableColumnStart("Excluded<br/>Groups");
            m_out.println("</tr>");
            NumberFormat formatter = new DecimalFormat("#,##0.0");
            int qty_tests = 0;
            int qty_pass_m = 0;
            int qty_pass_s = 0;
            int qty_skip = 0;
            int qty_fail = 0;
            long time_start = Long.MAX_VALUE;
            long time_end = Long.MIN_VALUE;
            m_testIndex = 1;
            for (ISuite suite : suites) {
                if (suites.size() > 1) {
                    titleRow(suite.getName(), 8);
                }
                Map<String, ISuiteResult> tests = suite.getResults();
                for (ISuiteResult r : tests.values()) {
                    qty_tests += 1;
                    ITestContext overview = r.getTestContext();
                    startSummaryRow(overview.getName());
                    int q = getMethodSet(overview.getPassedTests(), suite).size();
                    qty_pass_m += q;
                    summaryCell(q, Integer.MAX_VALUE);
                    q = overview.getPassedTests().size();
                    qty_pass_s += q;
                    summaryCell(q, Integer.MAX_VALUE);
                    q = getMethodSet(overview.getSkippedTests(), suite).size();
                    qty_skip += q;
                    summaryCell(q, 0);
                    q = getMethodSet(overview.getFailedTests(), suite).size();
                    qty_fail += q;
                    summaryCell(q, 0);
                    // NEW
                    // Insert error found
                    m_out.print("<td class=\"numi" + (true ? "" : "_attn") + "\">");
                    getShortException(overview.getFailedTests());
                    getShortException(overview.getSkippedTests());
                    m_out.println("</td>");
                    // NEW
                    // Add parameters for each test case (failed or passed)
                    m_out.print("<td class=\"numi" + (true ? "" : "_attn") + "\">");
                    // Write OS and Browser
                    // m_out.println(suite.getParameter("os").substring(0, 3) +
                    // " | "
                    // + suite.getParameter("browser").substring(0, 3) + " | ");
                    getParameters(overview.getFailedTests());
                    getParameters(overview.getPassedTests());
                    getParameters(overview.getSkippedTests());
                    m_out.println("</td>");
                    // NEW
                    summaryCell(
                            DateFunctions.dateToDayAndTime(overview.getStartDate()),
                            true);
                    m_out.println("</td>");
                    summaryCell(
                            DateFunctions.dateToDayAndTime(overview.getEndDate()),
                            true);
                    m_out.println("</td>");
                    time_start = Math.min(overview.getStartDate().getTime(),
                            time_start);
                    time_end = Math.max(overview.getEndDate().getTime(), time_end);
                    summaryCell(
                            formatter.format((overview.getEndDate().getTime() - overview
                                    .getStartDate().getTime()) / 1000.)
                                    + " seconds", true);
                    summaryCell(overview.getIncludedGroups());
                    summaryCell(overview.getExcludedGroups());
                    m_out.println("</tr>");
                    m_testIndex++;
                }
            }
            if (qty_tests > 1) {
                m_out.println("<tr class=\"total\"><td>Total</td>");
                summaryCell(qty_pass_m, Integer.MAX_VALUE);
                summaryCell(qty_pass_s, Integer.MAX_VALUE);
                summaryCell(qty_skip, 0);
                summaryCell(qty_fail, 0);
                summaryCell(" ", true);
                summaryCell(" ", true);
                summaryCell(" ", true);
                summaryCell(" ", true);
                summaryCell(
                        formatter.format(((time_end - time_start) / 1000.) / 60.)
                                + " minutes", true);
                m_out.println("<td colspan=\"3\">&nbsp;</td></tr>");
            }
            m_out.println("</table>");
        }
        private void summaryCell(String[] val) {
            StringBuffer b = new StringBuffer();
            for (String v : val) {
                b.append(v + " ");
            }
            summaryCell(b.toString(), true);
        }
        private void summaryCell(String v, boolean isgood) {
            m_out.print("<td class=\"numi" + (isgood ? "" : "_attn") + "\">" + v
                    + "</td>");
        }
        private void startSummaryRow(String label) {
            m_row += 1;
            m_out.print("<tr"
                    + (m_row % 2 == 0 ? " class=\"stripe\"" : "")
                    + "><td style=\"text-align:left;padding-right:2em\"><a href=\"#t"
                    + m_testIndex + "\">" + label + "</a>" + "</td>");
        }
        private void summaryCell(int v, int maxexpected) {
            summaryCell(String.valueOf(v), v <= maxexpected);
        }
        private void tableStart(String cssclass, String id) {
            m_out.println("<table cellspacing=\"0\" cellpadding=\"0\""
                    + (cssclass != null ? " class=\"" + cssclass + "\""
                            : " style=\"padding-bottom:2em\"")
                    + (id != null ? " id=\"" + id + "\"" : "") + ">");
            m_row = 0;
        }
        private void tableColumnStart(String label) {
            m_out.print("<th>" + label + "</th>");
        }
        private void titleRow(String label, int cq) {
            titleRow(label, cq, null);
        }
        private void titleRow(String label, int cq, String id) {
            m_out.print("<tr");
            if (id != null) {
                m_out.print(" id=\"" + id + "\"");
            }
            m_out.println("><th colspan=\"" + cq + "\">" + label + "</th></tr>");
            m_row = 0;
        }
        /** Starts HTML stream */
        protected void startHtml(PrintWriter out) {
            out.println("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">");
            out.println("<html xmlns=\"http://www.w3.org/1999/xhtml\">");
            out.println("<head>");
            out.println("<title>Hector Flores - TestNG Report</title>");
            out.println("<style type=\"text/css\">");
            out.println("table {margin-bottom:10px;border-collapse:collapse;empty-cells:show}");
            out.println("td,th {border:1px solid #009;padding:.25em .5em}");
            out.println(".result th {vertical-align:bottom}");
            out.println(".param th {padding-left:1em;padding-right:1em}");
            out.println(".param td {padding-left:.5em;padding-right:2em}");
            out.println(".stripe td,.stripe th {background-color: #E6EBF9}");
            out.println(".numi,.numi_attn {text-align:right}");
            out.println(".total td {font-weight:bold}");
            out.println(".passedodd td {background-color: #0A0}");
            out.println(".passedeven td {background-color: #3F3}");
            out.println(".skippedodd td {background-color: #CCC}");
            out.println(".skippedodd td {background-color: #DDD}");
            out.println(".failedodd td,.numi_attn {background-color: #F33}");
            out.println(".failedeven td,.stripe .numi_attn {background-color: #D00}");
            out.println(".stacktrace {white-space:pre;font-family:monospace}");
            out.println(".totop {font-size:85%;text-align:center;border-bottom:2px solid #000}");
            out.println("</style>");
            out.println("</head>");
            out.println("<body>");
        }
        /** Finishes HTML stream */
        protected void endHtml(PrintWriter out) {
            out.println("<center> Report customized by Hector Flores [[email protected]] </center>");
            out.println("</body></html>");
        }
        // ~ Inner Classes --------------------------------------------------------
        /** Arranges methods by classname and method name */
        private class TestSorter implements Comparator<IInvokedMethod> {
            // ~ Methods
            // -------------------------------------------------------------
            /** Arranges methods by classname and method name */
            @Override
            public int compare(IInvokedMethod o1, IInvokedMethod o2) {
                // System.out.println("Comparing " + o1.getMethodName() + " " +
                // o1.getDate()
                // + " and " + o2.getMethodName() + " " + o2.getDate());
                return (int) (o1.getDate() - o2.getDate());
                // int r = ((T) o1).getTestClass().getName().compareTo(((T)
                // o2).getTestClass().getName());
                // if (r == 0) {
                // r = ((T) o1).getMethodName().compareTo(((T) o2).getMethodName());
                // }
                // return r;
            }
        }
    }
    

    通過這些步骤,您已经準備好让听众听。

    How to call it?

    如果使用testng.xml,請添加以下行:

    <listeners>
             <listener class-name='[your_class_path].MyReporterListener'/>
     </listeners>
    

    如果从Java類執行測試,請添加以下行:

    private final static MyReporterListener frl = new MyReporterListener();
    TestNG testng = new TestNG();
    testng.addListener(frl);
    

    通過這些步骤,在執行測試時,您將获得两个可通過電子郵件發送的報告:自定義報告和原始報告。

    現在是時候整理報告了。

    對於我来說,我必须添加錯誤訊息,引數和時間(開始和結束),因為如果要粘贴到excel檔案中,這非常有用。

    我的自定義報告:

    您必须主要修改generateSuiteSummaryReport(List suites)函式。

    玩這个,問我是否有問题。

  • 11天前
    2 #

    更好地使用擴充套件報告html報告庫jar檔案.但是我正在使用extentreport1.4.jar jar檔案.因此,您將在報告的右上角获得摘要详细資訊

  • 11天前
    3 #

    製作一个CSS並將其嵌入到EmailableReporter.class中.可以在TestNG檔案夹>org.testNg.reporters>EmailableReporter.class中找到此類檔案。

    您可以在其中編輯以

    開頭的TestNG報告HTML檔案的樣式。
    protected void startHtml(PrintWriter out)
    

相似問題

  • javascript:在整个站點範圍內防止XSS攻击
  • macos:點突然使用錯誤的Python版本