Showing posts with label Selenium. Show all posts
Showing posts with label Selenium. Show all posts

Thursday, March 3, 2016

Java : Building Better GUI (GUI for framework ),without looping

Building Better GUI (GUI for framework)


Use following steps as guideline :
  1. Use Eclipse .
  2. Add window builder plugin to eclipse 
  3. While Creating Swing file , Select "Dialog" in Swing Designer 
  4. Create a GUI as required
  5. Right click on components to add listeners .
  6. In the Main class (calling function) , use below Code :

CODE :
public class test3 {

public static boolean bGUI_Yes=false;
public static void main(String[] args) {
GUI2 f2=new GUI2();// GUI2 is the GUI created using window builder
f2.setModal(true); //Modal tells thread to wait until user enters data ,should always be visible
f2.setVisible(true);

if(test3.bGUI_Yes==true) // set to true in the action listener inside OK button
System.out.println(f2.bGUI_UseExcel+ " "+f2.sGUI_testcases+" "+f2.sBrowser);
else
System.out.println("closed");
}
}


Note :
Cant stress enough - Select Dialog never select Jframe for this case  .
 

Wednesday, March 2, 2016

Selenium :Run Testng.xml using a Java file

Run Testng.xml using a Java file

http://stackoverflow.com/questions/23272861/how-to-call-testng-xml-from-java-main-method




// Create object of TestNG Class
TestNG runner=new TestNG();

// Create a list of String 
List<String> suitefiles=new ArrayList<String>();

// Add xml file which you have to execute
suitefiles.add("C:\\Automation Test\\Git\\vne_automation\\testng.xml");

// now set xml file for execution
runner.setTestSuites(suitefiles);

// finally execute the runner using run method
runner.run();

Saturday, February 27, 2016

Selenium : All About Reports


All ABout Reports :



http://examples.javacodegeeks.com/enterprise-java/testng/testng-html-xml-reports-example/
https://seleniumexperience.wordpress.com/2013/07/25/generating-custom-reports-with-testng/
http://kaczanowscy.pl/tomek/2009-11/testng-listeners-apache-velocity-and-css
https://solidsoft.wordpress.com/2011/01/23/better-looking-html-test-reports-for-testng-with-reportng-maven-guide/

Java :Classpath and library error even when dependencies are added to Gradle

Classpath and library error even when dependencies are added to Gradle


I have added all dependencies in "build.gradle" required for a selenium project.But still i am getting error when i try to launch a firefox driver using : WebDriver driver = new FirefoxDriver();


Solution : 
 
1. Make sure that you have imported the FirefoxDriver class in your code. Add the following line in your import section.

    import org.openqa.selenium.firefox.FirefoxDriver;

2. Clean the Gradle project (https://www.jetbrains.com/idea/help/gradle-tool-window.html)
3. Refresh the project (File>Synchronize)
4. Use the refresh button in Gradle Tool Window if ".gradle" file is edited
https://www.jetbrains.com/idea/help/gradle-tool-window.html


Note :All Dependencies add should appear in Gradle Tool Window >Dependencies

Java : Ivy (Gradle)

Java : Ivy



Apache Ivy was developed as an extension to the Ant build tool to provide Maven-style binary artifact management. It was never deployed as widely as Maven-style repos

Gradle :Declaring an Ivy repository using the default Maven layout

repositories {
  ivy {
    url 'http://build.megacorp.com/ivy/repo'
  }
}

Java :Maven Repositories(Gradle)

Java :Maven Repositories


https://www.safaribooksonline.com/library/view/gradle-beyond-the/9781449373801/ch04.html

Since a Maven repository is nothing more than a website containing downloadable POM files and modules in a predictable directory structure, declaring a Maven repository in Gradle begins with telling Gradle the URL of the repo. '

The most common Maven repository http://repo1.maven.org/maven2/ ( to avoid scripting that URL directly into your build).

Gradle: Declaring the Central repository
repositories {
  mavenCentral()
}


Other open-source Maven repositories exist on the Internet, Sonatype’s Nexus and JFrog’s Artifactory

Gradle : Declaring Maven repositories in general
repositories {
  maven {
    url = 'http://download.java.net/maven/2'
  }
  maven {
    name = 'JBoss Repo'  //optional name
    url = 'https://repository.jboss.org/nexus/content/repositories/releases'
  }
}


To download build artifacts from a mirrored copy of the repo somewhere else in the network

Gradle: Setting the artifact URL as distinct from the default POM URL

repositories {
  // Overriding artifacts for an internal repo
  maven {
    url = 'http://central.megacorp.com/main/repo'
    artifactUrls = [ 'http://dept.megacorp.com/local/repo' ]
  }
  // Obtain Maven Central artifacts locally
  mavenCentral artifactUrls: ['http://dept.megacorp.com/maven/central']
}

-----------------

Thursday, February 18, 2016

Selenium : Create Custom TestNG Report

Create Custom TestNG Report

http://www.testingdiaries.com/testng-reports-atu-reporter/ 

http://www.seleniumeasy.com/testng-tutorials/testng-customize-emailable-html-report-example


testng.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="Main Test Suite" verbose="5">

<parameter name="appURL" value="https://www.google.co.in/"/>
<parameter name="browserType" value="firefox"/>

   <listeners>
         <listener class-name="com.easy.TestNGCustomReportListener" />
    </listeners>
    <test name="TestNG Test Group">
        <packages>
            <package name="com.tests" />
        </packages>
    </test>
</suite>

Project Tree
Customized TestNG Report



 Code :
package com.custom;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;

import org.testng.IInvokedMethod;
import org.testng.IReporter;
import org.testng.IResultMap;
import org.testng.ISuite;
import org.testng.ISuiteResult;
import org.testng.ITestClass;
import org.testng.ITestContext;
import org.testng.ITestNGMethod;
import org.testng.ITestResult;
import org.testng.Reporter;
import org.testng.collections.Lists;
import org.testng.internal.Utils;
import org.testng.xml.XmlSuite;

public class TestNGCustomReportListener implements IReporter{

    private PrintWriter writer;
    private int m_row;
    private Integer m_testIndex;
    private int m_methodIndex;
    private String reportTitle= "TestNG Customized Report";
    private String reportFileName = "custom-report.html";

    /** Creates summary of the run */
    @Override
    public void generateReport(List<XmlSuite> xmlSuites, List<ISuite> suites,
                               String outdir) {
        try {
            writer = createWriter(outdir);
        } catch (IOException e) {
            System.err.println("Unable to create output file");
            e.printStackTrace();
            return;
        }

        startHtml(writer);
        writeReportTitle(reportTitle);
        generateSuiteSummaryReport(suites);
        generateMethodSummaryReport(suites);
        generateMethodDetailReport(suites);
        endHtml(writer);
        writer.flush();
        writer.close();
    }

    protected PrintWriter createWriter(String outdir) throws IOException {
        new File(outdir).mkdirs();
        return new PrintWriter(new BufferedWriter(new FileWriter(new File(outdir, reportFileName))));
    }

    /**
     * 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++;
            }
        }
        writer.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) {
                    writer.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;
                        writer.print("<tr class=\"\"" + style + (cq % 2 == 0 ? "even" : "odd") + ">" + "<td");
                        if (mq > 1) {
                            writer.print(" rowspan=\"\" + mq + \"\"");
                        }
                        writer.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;
                long startMS=0;
                String firstLine="";

                for (ITestResult testResult : tests.getResults(method)) {
                    if (testResult.getEndMillis() > end) {
                        end = testResult.getEndMillis()/1000;
                    }
                    if (testResult.getStartMillis() < start) {
                        startMS = testResult.getStartMillis();
                        start =startMS/1000;
                    }

                    Throwable exception=testResult.getThrowable();
                    boolean hasThrowable = exception != null;
                    if(hasThrowable){
                        String str = Utils.stackTrace(exception, true)[0];
                        Scanner scanner = new Scanner(str);
                        firstLine = scanner.nextLine();
                    }
                }
                DateFormat formatter = new SimpleDateFormat("hh:mm:ss");
                Calendar calendar = Calendar.getInstance();
                calendar.setTimeInMillis(startMS);

                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\" style=\"text-align:left;padding-right:2em\">" + firstLine+"<br/></td>"
                        + "<td style=\"text-align:right\">" + formatter.format(calendar.getTime()) + "</td>" + "<td class=\"numi\">"
                        + timeConversion(end - start) + "</td>" + "</tr>");

            }
            if (mq > 0) {
                cq += 1;
                writer.print("<tr class=\"" + style + (cq % 2 == 0 ? "even" : "odd") + "\">" + "<td");
                if (mq > 1) {
                    writer.print(" rowspan=\"" + mq + "\"");
                }
                writer.println(">" + lastClassName + "</td>" + buff);
            }
        }
    }


    private String timeConversion(long seconds) {

        final int MINUTES_IN_AN_HOUR = 60;
        final int SECONDS_IN_A_MINUTE = 60;

        int minutes = (int) (seconds / SECONDS_IN_A_MINUTE);
        seconds -= minutes * SECONDS_IN_A_MINUTE;

        int hours = minutes / MINUTES_IN_AN_HOUR;
        minutes -= hours * MINUTES_IN_AN_HOUR;

        return prefixZeroToDigit(hours) + ":" + prefixZeroToDigit(minutes) + ":" + prefixZeroToDigit((int)seconds);
    }

    private String prefixZeroToDigit(int num){
        int number=num;
        if(number<=9){
            String sNumber="0"+number;
            return sNumber;
        }
        else
            return ""+number;

    }

    /** Starts and defines columns result summary table */
    private void startResultSummaryTable(String style) {
        tableStart(style, "summary");
        writer.println("<tr><th>Class</th>"
                + "<th>Method</th><th>Exception Info</th><th>Start Time </th><th>Execution Time<br/>(hh:mm:ss)</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) {
        Set<ITestResult> testResults=tests.getAllResults();
        List<ITestResult> testResultsList = new ArrayList<ITestResult>(testResults);
        System.setProperty("java.util.Arrays.useLegacyMergeSort", "true");
        System.setProperty("java.util.Collections.useLegacyMergeSort", "true");
        Collections.sort(testResultsList, new TestResultsSorter());
        for (ITestResult result : testResultsList) {
            ITestNGMethod method = result.getMethod();
            m_methodIndex++;
            String cname = method.getTestClass().getName();
            writer.println("<h2 id=\"m" + m_methodIndex + "\">" + cname + ":"
                    + method.getMethodName() + "</h2>");
            Set<ITestResult> resultSet = tests.getResults(method);
            generateResult(result, method, resultSet.size());
            writer.println("<p class=\"totop\"><a href=\"#summary\">back to summary</a></p>");

        }
    }

    private void generateResult(ITestResult ans, ITestNGMethod method,
                                int resultSetSize) {
        Object[] parameters = ans.getParameters();
        boolean hasParameters = parameters != null && parameters.length > 0;
        if (hasParameters) {
            tableStart("result", null);
            writer.print("<tr class=\"param\">");
            for (int x = 1; x <= parameters.length; x++) {
                writer.print("<th>Param." + x + "</th>");
            }
            writer.println("</tr>");
            writer.print("<tr class=\"param stripe\">");
            for (Object p : parameters) {
                writer.println("<td>" + Utils.escapeHtml(Utils.toString(p))
                        + "</td>");
            }
            writer.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) {
                writer.print("<tr><td");
                if (parameters.length > 1) {
                    writer.print(" colspan=\"\" + parameters.length + \"\"");
                }
                writer.println(">");
            } else {
                writer.println("<div>");
            }
            if (hasReporterOutput) {
                if (hasThrowable) {
                    writer.println("<h3>Test Messages</h3>");
                }
                for (String line : msgs) {
                    writer.println(line + "<br/>");
                }
            }
            if (hasThrowable) {
                boolean wantsMinimalOutput = ans.getStatus() == ITestResult.SUCCESS;
                if (hasReporterOutput) {
                    writer.println("<h3>"
                            + (wantsMinimalOutput ? "Expected Exception"
                            : "Failure") + "</h3>");
                }
                generateExceptionReport(exception, method);
            }
            if (hasParameters) {
                writer.println("</td></tr>");
            } else {
                writer.println("</div>");
            }
        }
        if (hasParameters) {
            writer.println("</table>");
        }
    }

    protected void generateExceptionReport(Throwable exception, ITestNGMethod method) {
        writer.print("<div class=\"stacktrace\">");
        writer.print(Utils.stackTrace(exception, true)[0]);
        writer.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);
            }
        }

        System.setProperty("java.util.Arrays.useLegacyMergeSort", "true");
        System.setProperty("java.util.Collections.useLegacyMergeSort", "true");
        Collections.sort(r,new TestSorter());
        List<ITestNGMethod> result = Lists.newArrayList();

        // Add all the invoked methods
        for (IInvokedMethod m : r) {
            for (ITestNGMethod temp : result) {
                if (!temp.equals(m.getTestMethod()))
                    result.add(m.getTestMethod());
            }
        }

        // Add all the methods that weren't invoked (e.g. skipped) that we
        // haven't added yet
        Collection<ITestNGMethod> allMethodsCollection=tests.getAllMethods();
        List<ITestNGMethod> allMethods=new ArrayList<ITestNGMethod>(allMethodsCollection);
        Collections.sort(allMethods, new TestMethodSorter());

        for (ITestNGMethod m : allMethods) {
            if (!result.contains(m)) {
                result.add(m);
            }
        }
        return result;
    }

    @SuppressWarnings("unused")
    public void generateSuiteSummaryReport(List<ISuite> suites) {
        tableStart("testOverview", null);
        writer.print("<tr>");
        tableColumnStart("Test");
        tableColumnStart("Methods<br/>Passed");
        tableColumnStart("# skipped");
        tableColumnStart("# failed");
        tableColumnStart("Browser");
        tableColumnStart("Start<br/>Time");
        tableColumnStart("End<br/>Time");
        tableColumnStart("Total<br/>Time(hh:mm:ss)");
        tableColumnStart("Included<br/>Groups");
        tableColumnStart("Excluded<br/>Groups");

        writer.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;
        long time_start = Long.MAX_VALUE;
        int qty_fail = 0;
        long time_end = Long.MIN_VALUE;
        m_testIndex = 1;
        for (ISuite suite : suites) {
            if (suites.size() >= 1) {
                titleRow(suite.getName(), 10);
            }
            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 = getMethodSet(overview.getSkippedTests(), suite).size();
                qty_skip += q;
                summaryCell(q, 0);
                q = getMethodSet(overview.getFailedTests(), suite).size();
                qty_fail += q;
                summaryCell(q, 0);

                // Write OS and Browser
                summaryCell(suite.getParameter("browserType"), true);
                writer.println("</td>");

                SimpleDateFormat summaryFormat = new SimpleDateFormat("hh:mm:ss");
                summaryCell(summaryFormat.format(overview.getStartDate()),true);
                writer.println("</td>");

                summaryCell(summaryFormat.format(overview.getEndDate()),true);
                writer.println("</td>");

                time_start = Math.min(overview.getStartDate().getTime(), time_start);
                time_end = Math.max(overview.getEndDate().getTime(), time_end);
                summaryCell(timeConversion((overview.getEndDate().getTime() - overview.getStartDate().getTime()) / 1000), true);

                summaryCell(overview.getIncludedGroups());
                summaryCell(overview.getExcludedGroups());
                writer.println("</tr>");
                m_testIndex++;
            }
        }
        if (qty_tests > 1) {
            writer.println("<tr class=\"total\"><td>Total</td>");
            summaryCell(qty_pass_m, Integer.MAX_VALUE);
            summaryCell(qty_skip, 0);
            summaryCell(qty_fail, 0);
            summaryCell(" ", true);
            summaryCell(" ", true);
            summaryCell(" ", true);
            summaryCell(timeConversion(((time_end - time_start) / 1000)), true);
            writer.println("<td colspan=\"3\">&nbsp;</td></tr>");
        }
        writer.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) {
        writer.print("<td class=\"numi" + (isgood ? "" : "_attn") + "\">" + v
                + "</td>");
    }

    private void startSummaryRow(String label) {
        m_row += 1;
        writer.print("<tr" + (m_row % 2 == 0 ? " class=\"stripe\"" : "") + "><td style=\"text-align:left;padding-right:2em\"><a href=\"#t"
                + m_testIndex +"\"><b>" + label + "</b></a>" + "</td>");

    }

    private void summaryCell(int v, int maxexpected) {
        summaryCell(String.valueOf(v), v <= maxexpected);
    }

    private void tableStart(String cssclass, String id) {
        writer.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) {
        writer.print("<th>" + label + "</th>");
    }

    private void titleRow(String label, int cq) {
        titleRow(label, cq, null);
    }

    private void titleRow(String label, int cq, String id) {
        writer.print("<tr");
        if (id != null) {
            writer.print(" id=\"" + id + "\"");
        }
        writer.println("><th colspan=\"" + cq + "\">" + label + "</th></tr>");
        m_row = 0;
    }

    protected void writeReportTitle(String title) {
        writer.print("<center><h1>" + title + " - " + getDateAsString() + "</h1></center>");
    }


    /*
     * Method to get Date as String
     */
    private String getDateAsString() {
        DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
        Date date = new Date();
        return dateFormat.format(date);
    }

    /** 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(“<html xmlns=\”http://www.w3.org/1999/xhtml\”>”);
        out.println("<head>");
        out.println("<title>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> TestNG Report </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 obj1, IInvokedMethod obj2) {
            int r = obj1.getTestMethod().getTestClass().getName().compareTo(obj2.getTestMethod().getTestClass().getName());
            return r;
        }
    }

    private class TestMethodSorter implements Comparator<ITestNGMethod> {
        @Override
        public int compare(ITestNGMethod obj1, ITestNGMethod obj2) {
            int r = obj1.getTestClass().getName().compareTo(obj2.getTestClass().getName());
            if (r == 0) {
                r = obj1.getMethodName().compareTo(obj2.getMethodName());
            }
            return r;
        }
    }

    private class TestResultsSorter implements Comparator<ITestResult> {
        @Override
        public int compare(ITestResult obj1, ITestResult obj2) {
            int result = obj1.getTestClass().getName().compareTo(obj2.getTestClass().getName());
            if (result == 0) {
                result = obj1.getMethod().getMethodName().compareTo(obj2.getMethod().getMethodName());
            }
            return result;
        }
    }

}