1、reportNG之ReportNGUtils修改后的源码如下
//============================================================================= // Copyright 2006-2013 Daniel W. Dyer // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //============================================================================= package org.uncommons.reportng; import java.awt.*; import java.awt.image.BufferedImage; import java.io.File; import java.io.FileOutputStream; import java.io.FilenameFilter; import java.nio.channels.NonWritableChannelException; import java.text.DecimalFormat; import java.text.NumberFormat; import java.text.SimpleDateFormat; import java.util.*; import java.util.List; import org.testng.IInvokedMethod; import org.testng.ISuite; import org.testng.ISuiteResult; import org.testng.ITestContext; import org.testng.ITestNGMethod; import org.testng.ITestResult; import org.testng.Reporter; import org.testng.SkipException; import javax.imageio.ImageIO; /** * Utility class that provides various helper methods that can be invoked * from a Velocity template. * @author Daniel Dyer */ public class ReportNGUtils { private static final NumberFormat DURATION_FORMAT = new DecimalFormat("#0.000"); private static final NumberFormat PERCENTAGE_FORMAT = new DecimalFormat("#0.00%"); private static final String path = "./test-output/html/img"; /** * Returns the aggregate of the elapsed times for each test result. * @param context The test results. * @return The sum of the test durations. */ public long getDuration(ITestContext context) { long duration = getDuration(context.getPassedConfigurations().getAllResults()); duration += getDuration(context.getPassedTests().getAllResults()); // You would expect skipped tests to have durations of zero, but apparently not. duration += getDuration(context.getSkippedConfigurations().getAllResults()); duration += getDuration(context.getSkippedTests().getAllResults()); duration += getDuration(context.getFailedConfigurations().getAllResults()); duration += getDuration(context.getFailedTests().getAllResults()); return duration; } /** * Returns the aggregate of the elapsed times for each test result. * @param results A set of test results. * @return The sum of the test durations. */ private long getDuration(Set<ITestResult> results) { long duration = 0; for (ITestResult result : results) { duration += (result.getEndMillis() - result.getStartMillis()); } return duration; } public String formatDuration(long startMillis, long endMillis) { long elapsed = endMillis - startMillis; return formatDuration(elapsed); } public String formatDuration(long elapsed) { double seconds = (double) elapsed / 1000; return DURATION_FORMAT.format(seconds); } /** * Convert a Throwable into a list containing all of its causes. * @param t The throwable for which the causes are to be returned. * @return A (possibly empty) list of {@link Throwable}s. */ public List<Throwable> getCauses(Throwable t) { List<Throwable> causes = new LinkedList<Throwable>(); Throwable next = t; while (next.getCause() != null) { next = next.getCause(); causes.add(next); } return causes; } /** * Retrieves all log messages associated with a particular test result. * @param result Which test result to look-up. * @return A list of log messages. */ public List<String> getTestOutput(ITestResult result) { return Reporter.getOutput(result); } /** * Retieves the output from all calls to {@link org.testng.Reporter#log(String)} * across all tests. * @return A (possibly empty) list of log messages. */ public List<String> getAllOutput() { return Reporter.getOutput(); } public boolean hasArguments(ITestResult result) { return result.getParameters().length > 0; } public String getArguments(ITestResult result) { Object[] arguments = result.getParameters(); List<String> argumentStrings = new ArrayList<String>(arguments.length); for (Object argument : arguments) { argumentStrings.add(renderArgument(argument)); } return commaSeparate(argumentStrings); } /** * Decorate the string representation of an argument to give some * hint as to its type (e.g. render Strings in double quotes). * @param argument The argument to render. * @return The string representation of the argument. */ private String renderArgument(Object argument) { if (argument == null) { return "null"; } else if (argument instanceof String) { return "\"" + argument + "\""; } else if (argument instanceof Character) { return "\'" + argument + "\'"; } else { return argument.toString(); } } /** * @param result The test result to be checked for dependent groups. * @return True if this test was dependent on any groups, false otherwise. */ public boolean hasDependentGroups(ITestResult result) { return result.getMethod().getGroupsDependedUpon().length > 0; } /** * @return A comma-separated string listing all dependent groups. Returns an * empty string it there are no dependent groups. */ public String getDependentGroups(ITestResult result) { String[] groups = result.getMethod().getGroupsDependedUpon(); return commaSeparate(Arrays.asList(groups)); } /** * @param result The test result to be checked for dependent methods. * @return True if this test was dependent on any methods, false otherwise. */ public boolean hasDependentMethods(ITestResult result) { return result.getMethod().getMethodsDependedUpon().length > 0; } /** * @return A comma-separated string listing all dependent methods. Returns an * empty string it there are no dependent methods. */ public String getDependentMethods(ITestResult result) { String[] methods = result.getMethod().getMethodsDependedUpon(); return commaSeparate(Arrays.asList(methods)); } public boolean hasSkipException(ITestResult result) { return result.getThrowable() instanceof SkipException; } public String getSkipExceptionMessage(ITestResult result) { return hasSkipException(result) ? result.getThrowable().getMessage() : ""; } public boolean hasGroups(ISuite suite) { return !suite.getMethodsByGroups().isEmpty(); } /** * Takes a list of Strings and combines them into a single comma-separated * String. * @param strings The Strings to combine. * @return The combined, comma-separated, String. */ private String commaSeparate(Collection<String> strings) { StringBuilder buffer = new StringBuilder(); Iterator<String> iterator = strings.iterator(); while (iterator.hasNext()) { String string = iterator.next(); buffer.append(string); if (iterator.hasNext()) { buffer.append(", "); } } return buffer.toString(); } /** * Replace any angle brackets, quotes, apostrophes or ampersands with the * corresponding XML/HTML entities to avoid problems displaying the String in * an XML document. Assumes that the String does not already contain any * entities (otherwise the ampersands will be escaped again). * @param s The String to escape. * @return The escaped String. */ public String escapeString(String s) { if (s == null) { return null; } StringBuilder buffer = new StringBuilder(); for(int i = 0; i < s.length(); i++) { buffer.append(escapeChar(s.charAt(i))); } return buffer.toString(); } /** * Converts a char into a String that can be inserted into an XML document, * replacing special characters with XML entities as required. * @param character The character to convert. * @return An XML entity representing the character (or a String containing * just the character if it does not need to be escaped). */ private String escapeChar(char character) { switch (character) { case '<': return "<"; case '>': return ">"; case '"': return """; case '\'': return "'"; case '&': return "&"; default: return String.valueOf(character); } } /** * Works like {@link #escapeString(String)} but also replaces line breaks with * <br /> tags and preserves significant whitespace. * @param s The String to escape. * @return The escaped String. */ public String escapeHTMLString(String s) { if (s == null) { return null; } StringBuilder buffer = new StringBuilder(); for(int i = 0; i < s.length(); i++) { char ch = s.charAt(i); switch (ch) { case ' ': // All spaces in a block of consecutive spaces are converted to // non-breaking space ( ) except for the last one. This allows // significant whitespace to be retained without prohibiting wrapping. char nextCh = i + 1 < s.length() ? s.charAt(i + 1) : 0; buffer.append(nextCh==' ' ? " " : " "); break; case '\n': buffer.append("<br/>\n"); break; default: buffer.append(escapeChar(ch)); } } return buffer.toString(); } /** * TestNG returns a compound thread ID that includes the thread name and its numeric ID, * separated by an 'at' sign. We only want to use the thread name as the ID is mostly * unimportant and it takes up too much space in the generated report. * @param threadId The compound thread ID. * @return The thread name. */ public String stripThreadName(String threadId) { if (threadId == null) { return null; } else { int index = threadId.lastIndexOf('@'); return index >= 0 ? threadId.substring(0, index) : threadId; } } /** * Find the earliest start time of the specified methods. * @param methods A list of test methods. * @return The earliest start time. */ public long getStartTime(List<IInvokedMethod> methods) { long startTime = System.currentTimeMillis(); for (IInvokedMethod method : methods) { startTime = Math.min(startTime, method.getDate()); } return startTime; } public long getEndTime(ISuite suite, IInvokedMethod method, List<IInvokedMethod> methods) { boolean found = false; for (IInvokedMethod m : methods) { if (m == method) { found = true; } // Once a method is found, find subsequent method on same thread. else if (found && m.getTestMethod().getId().equals(method.getTestMethod().getId())) { return m.getDate(); } } return getEndTime(suite, method); } /** * Returns the timestamp for the time at which the suite finished executing. * This is determined by finding the latest end time for each of the individual * tests in the suite. * @param suite The suite to find the end time of. * @return The end time (as a number of milliseconds since 00:00 1st January 1970 UTC). */ private long getEndTime(ISuite suite, IInvokedMethod method) { // Find the latest end time for all tests in the suite. for (Map.Entry<String, ISuiteResult> entry : suite.getResults().entrySet()) { ITestContext testContext = entry.getValue().getTestContext(); for (ITestNGMethod m : testContext.getAllTestMethods()) { if (method == m) { return testContext.getEndDate().getTime(); } } // If we can't find a matching test method it must be a configuration method. for (ITestNGMethod m : testContext.getPassedConfigurations().getAllMethods()) { if (method == m) { return testContext.getEndDate().getTime(); } } for (ITestNGMethod m : testContext.getFailedConfigurations().getAllMethods()) { if (method == m) { return testContext.getEndDate().getTime(); } } } throw new IllegalStateException("Could not find matching end time."); } public String dateFormate(long endMillis){ SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Date date = new Date(); date.setTime(endMillis); return simpleDateFormat.format(date); } public String formatPercentage(int numerator, int denominator) { return PERCENTAGE_FORMAT.format(numerator / (double) denominator); } public String shotScreen(ITestResult result) { File file1 = null; File file = new File(path); if (!file.exists()) { file.mkdirs(); } File file2[] = file.listFiles(); for (int i = 0; i < file2.length; i++) { if (file2[i].getName().startsWith(result.getMethod().getMethodName())) { file2[i].delete(); } } if(result.getStatus()==2) { SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss", Locale.CHINESE); String name = result.getMethod().getMethodName() + simpleDateFormat.format(new Date()) + ".png"; file1 = new File(path + "\\" + name); Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); //获得屏幕高度和宽度 Rectangle screenRectangle = new Rectangle(screenSize); //指定一个坐标区域 try { Robot robot = new Robot(); BufferedImage image = robot.createScreenCapture(screenRectangle); ImageIO.write(image, "png", file1); image.flush(); } catch (Exception e) { e.getCause(); } } return file1.getPath(); } // public String change(String s){ // String news = s.replace("\\" ,"/"); // return news; // } public String getPathImage( ITestNGMethod testNGMethod){ String temp = null; File file = new File(path); if(file.isDirectory()) { File file1[] = file.listFiles(); for (int i = 0; i < file1.length; i++) { if (file1[i].getName().startsWith(testNGMethod.getMethodName())) { temp = "img/" + file1[i].getName(); break; } } } return temp; } }