com.aol.framework.helper.report.CustomizedReporter.java Source code

Java tutorial

Introduction

Here is the source code for com.aol.framework.helper.report.CustomizedReporter.java

Source

package com.aol.framework.helper.report;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.ConcurrentModificationException;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Random;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.testng.IReporter;
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.TestListenerAdapter;
import org.testng.internal.Utils;
import org.testng.reporters.util.StackTraceTools;
import org.testng.xml.XmlSuite;

import com.aol.framework.helper.TestHelper;

/**
 * Description: Class to generate customized reports.
 * *****************************************************************************
 * TableSorter Algorithm Author: Christian Bach Version: 2.0.5 License: Dual
 * licensed under MIT or GPL licenses.
 * *****************************************************************************
 * 
 */
public class CustomizedReporter extends TestListenerAdapter implements IReporter {
    private PrintWriter out, e_out;
    private boolean doneOutputToConsole = false;
    private boolean disableCss = TestHelper.getTestConfig("DISABLE_CSS_REPORT").equalsIgnoreCase("true");

    private String warnColor = "#FAAC58", passColor = "#00CC00", failColor = "#CC0000", skipColor = "#CCA300",
            passPercentageColor = "#A35200", titleColor = "#A35200";

    //    private String classParam = "class=\"param\"";
    //    private String classDetails = "class=\"details\"";
    private String classParam = "border=\"1\" color=\"#333300\" text-align=\"center\" font-family=\"Georgia,\"Times New Roman\",Times,serif;\"";
    private String classDetails = "border=\"0\" color=\"#333300\" text-align=\"left\" font-family=\"Georgia,\"Times New Roman\",Times,serif;\"";

    synchronized public void generateReport(List<XmlSuite> arg0, List<ISuite> suites, String outdir) {
        TestHelper.threadSleep(10000); // Try to avoid ConcurrentModificationException when deal with ITestResult, it's a known testng report issue

        if (TestHelper.enableEmailableReport) {
            e_out = TestHelper.createFileWriter(TestHelper.emailableReportFile);

            e_startHtmlPage(e_out);

            generateAdditionalInfoReport(true, suites, e_out);
            generateTestExecutionStatus(true, suites, e_out);

            e_endHtmlPage(e_out);
            e_out.flush();
        }
        if (TestHelper.enableCustomeReport) {
            out = TestHelper.createFileWriter(TestHelper.customReportFile);
            startHtmlPage(out, TestHelper.cssFolderName + "/");

            generateAdditionalInfoReport(suites, out);
            generateTestExecutionStatus(suites, out);

            endHtmlPage(out);
            out.flush();
        }

        //System.exit(0);
    }

    synchronized private void generateTestExecutionStatus(List<ISuite> suites, PrintWriter f_out) {
        generateTestExecutionStatus(false, suites, f_out);
    }

    synchronized private void generateTestExecutionStatus(boolean emailable, List<ISuite> suites,
            PrintWriter f_out) {
        String testName = "";

        int totalPassedMethods = 0;
        int totalFailedMethods = 0;
        int totalSkippedMethods = 0;
        int totalSkippedConfigurationMethods = 0;
        int totalFailedConfigurationMethods = 0;
        int totalAutomationErrors = 0;
        int totalMethods = 0;

        int suite_totalPassedMethods = 0;
        int suite_totalFailedMethods = 0;
        int suite_totalSkippedMethods = 0;
        int suite_totalAutomationErrors = 0;

        String suite_passPercentage = "";
        String suiteName = "";

        ITestContext overview = null;
        HashMap<String, String> dashboardReportMap = new HashMap<String, String>();

        String dashboardAppGroup = "";

        for (ISuite suite : suites) {
            suiteName = suite.getName();
            TestHelper.logger.info(">> " + suiteName + " <<");
            Map<String, ISuiteResult> tests = suite.getResults();
            NumberFormat nf = NumberFormat.getInstance();

            for (ISuiteResult r : tests.values()) {
                overview = r.getTestContext();
                testName = overview.getName();

                totalPassedMethods = overview.getPassedTests().getAllMethods().size();
                totalFailedMethods = overview.getFailedTests().getAllMethods().size();
                totalAutomationErrors = overview.getFailedButWithinSuccessPercentageTests().getAllMethods().size();
                totalSkippedMethods = overview.getSkippedTests().getAllMethods().size();
                totalFailedConfigurationMethods = overview.getFailedConfigurations().getAllMethods().size(); // this should be 0 as redirected to automation error
                // totalMethods = overview.getAllTestMethods().length;
                totalMethods = totalPassedMethods + totalFailedMethods;

                nf.setMaximumFractionDigits(2);
                nf.setGroupingUsed(true);

                String includedModule = "";
                String includedGroup = "";

                ITestNGMethod[] allTestMethods = overview.getAllTestMethods();
                for (ITestNGMethod testngMethod : allTestMethods) {
                    String[] modules = testngMethod.getGroups();
                    for (String module : modules) {
                        for (String moduleName : TestHelper.MODULES) {
                            if (module.equalsIgnoreCase(moduleName)) {
                                if (!(includedModule.contains(module))) {
                                    includedModule = includedModule + " " + module;
                                }
                            }
                        }
                        for (String groupName : TestHelper.TEST_GROUPS) {
                            if (module.equalsIgnoreCase(groupName)) {
                                if (!(includedGroup.contains(module))) {
                                    includedGroup = includedGroup + " " + module;
                                }
                            }
                        }
                    }
                }

                String[] nodeInfo = getNodeInfo(overview, testName);

                String browser = nodeInfo[1];
                String browser_version = nodeInfo[2];
                String platform = nodeInfo[0];
                //String nodeIp = nodeInfo[3];

                if (platform == null || platform.trim().length() == 0) {
                    platform = "N/A";
                }

                if (browser_version == null || browser_version.trim().length() == 0) {
                    browser_version = "N/A";
                }

                if (browser == null || browser.trim().length() == 0) {
                    browser = "N/A";
                }

                if (!(dashboardReportMap.containsKey(includedModule))) {
                    if (browser_version.equalsIgnoreCase("N/A")) {
                        browser_version = "";
                    }
                    dashboardReportMap.put(includedModule,
                            "os1~" + platform + "|browser1~" + browser + browser_version + "|testcase_count_1~"
                                    + totalMethods + "|pass_count_1~" + totalPassedMethods + "|fail_count_1~"
                                    + totalFailedMethods + "|skip_count_1~" + totalSkippedMethods
                                    + "|skip_conf_count_1~" + totalSkippedConfigurationMethods
                                    + "|fail_conf_count_1~" + totalFailedConfigurationMethods
                                    + "|fail_automation_count_1~" + totalAutomationErrors);

                } else {
                    for (String key : dashboardReportMap.keySet()) {

                        if (key.equalsIgnoreCase(includedModule)) {
                            if (browser_version.equalsIgnoreCase("N/A")) {
                                browser_version = "";
                            }
                            String value = dashboardReportMap.get(key);
                            int index = StringUtils.countMatches(value, "#") + 1;

                            index += 1;

                            value = value + "#" + "os" + index + "~" + platform + "|browser" + index + "~" + browser
                                    + browser_version + "|testcase_count_" + index + "~" + totalMethods
                                    + "|pass_count_" + index + "~" + totalPassedMethods + "|fail_count_" + index
                                    + "~" + totalFailedMethods + "|skip_count_" + index + "~" + totalSkippedMethods
                                    + "|skip_conf_count_" + index + "~" + totalSkippedConfigurationMethods
                                    + "|fail_conf_count_" + index + "~" + totalFailedConfigurationMethods
                                    + "|fail_automation_count_~" + totalAutomationErrors;
                            dashboardReportMap.put(key, value);
                        }
                    }
                }

                dashboardAppGroup = includedGroup;
                suite_totalPassedMethods += totalPassedMethods;
                suite_totalFailedMethods += totalFailedMethods;
                suite_totalAutomationErrors += totalAutomationErrors;
                suite_totalSkippedMethods += totalSkippedMethods;

                suite_passPercentage = getPercentage(nf, suite_totalPassedMethods,
                        suite_totalPassedMethods + suite_totalFailedMethods);

            }

        }

        if (!doneOutputToConsole) {
            //**************************** report to console as status ******************

            int suite_totalTestedMethods = suite_totalPassedMethods + suite_totalFailedMethods;

            System.out.println("[TOTAL_METHODS]: " + (suite_totalTestedMethods));

            System.out.println("[PASSED_METHODS]: " + suite_totalPassedMethods);
            if (suite_totalFailedMethods > 0 || suite_totalPassedMethods == 0)
                System.out.println("[FAILED_METHODS]: " + suite_totalFailedMethods);
            if (suite_totalAutomationErrors > 0)
                System.out.println("[AUTOMATION_ERRORS]: " + suite_totalAutomationErrors);
            if (suite_totalSkippedMethods > 0)
                System.out.println("[SKIPPED_METHODS]: " + suite_totalSkippedMethods);

            System.out.println("[PASSED%]: " + suite_passPercentage);

            TestHelper.setReportProperties(suite_totalTestedMethods, suite_totalPassedMethods,
                    suite_totalFailedMethods, suite_totalSkippedMethods, suite_passPercentage,
                    suite_totalAutomationErrors);
            //********************************************************************************
        }

        StringBuilder dashboardResults = new StringBuilder();
        if (!emailable) {
            dashboardResults.append(
                    "<table id=\"myTable\" width=\"100%\" cellspacing=0 cellpadding=0 class=\"tablesorter\">");
        } else {
            dashboardResults.append("<table " + classParam + " cellspacing=\"0\" cellpadding=\"0\" width=\"91%\">");
        }
        dashboardResults
                // .append("<thead><tr> <th>Test Name</th><th>"
                .append("<thead><tr> <th>Module Name</th><th>" + " # Unique TestCases</th><th>"
                        + " # Combinations</th><th>" + " # Passed</th><th>" + " # Failed</th><th>"
                        + " # Warning</th><th>" + " # Skipped</th><th>" + "# Total</th><th>"
                        + "Success Rate</th> </tr> </thead> <tbody>");

        int total_browser_combinations = 0;
        int total_unique_testcases = 0;

        for (String key : dashboardReportMap.keySet()) {

            String fileName = key.trim() + "-Overall" + "-customized-report.html";
            if (!emailable) {

                try {
                    generateModuleOverallTestReport(testName, key, suites, fileName);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

            String value = dashboardReportMap.get(key);
            String[] values = value.split("#");

            int testcase_count = 0; //*******************************************
            int pass_count = 0;
            int fail_count = 0;
            int fail_automation_count = 0;
            int skip_count = 0;
            int skip_conf_count = 0;
            int fail_conf_count = 0;
            String appKey = "TEST_APP";
            String appName = TestHelper.getTestConfig(appKey);

            if (dashboardAppGroup.contains("Smoke") && !appName.equalsIgnoreCase("webmail")) {
                appName = appName + "_" + "Smoke";

            } else if (dashboardAppGroup.contains("Regression")) {
                appName = appName + "_" + "Regression";
            }

            String dashboardModule = key;
            //
            //            if (dashboardModule.contains("Compose"))
            //            {
            //                dashboardModule = dashboardModule.replace("Compose", "ComposeMail");
            //            } else if (dashboardModule.contains("Read"))
            //            {
            //                dashboardModule = dashboardModule.replace("Read", "ReadMail");
            //            }

            // int countMatches = StringUtils.countMatches(value, "#") + 1;

            for (String val : values) {

                String[] tokens = val.split("\\|");
                for (String token : tokens) {
                    if (token.contains("testcase_count")) {
                        testcase_count = testcase_count + Integer.parseInt(token.split("~")[1]);
                    }
                    if (token.contains("pass_count")) {
                        pass_count = pass_count + Integer.parseInt(token.split("~")[1]);
                    }
                    if (token.contains("fail_count")) {
                        fail_count = fail_count + Integer.parseInt(token.split("~")[1]);
                    }
                    if (token.contains("fail_automation_count")) {
                        fail_automation_count = fail_automation_count + Integer.parseInt(token.split("~")[1]);
                    }
                    if (token.contains("skip_count")) {
                        skip_count = skip_count + Integer.parseInt(token.split("~")[1]);
                    }
                    if (token.contains("skip_conf_count")) {
                        skip_conf_count = skip_conf_count + Integer.parseInt(token.split("~")[1]);
                    }
                    if (token.contains("fail_conf_count")) {
                        fail_conf_count = fail_conf_count + Integer.parseInt(token.split("~")[1]);
                    }
                }

                testcase_count -= skip_count + skip_conf_count + fail_conf_count;
            }

            NumberFormat nformat = NumberFormat.getInstance();
            nformat.setMaximumFractionDigits(2);
            nformat.setGroupingUsed(true);
            String passPercent = getPercentage(nformat, pass_count, pass_count + fail_count);

            String finalStr = "[";
            String[] val = dashboardReportMap.get(key).split("#");

            int unique_testcase = 0;

            int limit = val.length - 1;
            for (int i = 0; i < val.length; i++) {//TODO - unique_testcase is the max num cases among tests, not the total for the module across tests - Steven
                String testCaseCount = (val[i].split("\\|")[2]).split("~")[1];
                int next = Integer.parseInt(testCaseCount);
                if (next > unique_testcase) {
                    unique_testcase = next;
                }
                finalStr = finalStr + testCaseCount + " T * 1 B]";
                if (i != limit) {
                    finalStr += " + [";
                }
            }
            //unique_testcase = 
            String finalString = "";
            //            if ((unique_testcase * values.length) != (pass_count + fail_count + skip_count))
            //            {
            //                finalString = "<a href=\"#\" title=\"" + finalStr + "\">" + (pass_count + fail_count + skip_count)
            //                        + "</a>";
            //                
            //            } else
            {
                finalString = String.valueOf((pass_count + fail_count + fail_automation_count + skip_count));
            }

            String passCount = "";
            String failCount = "";
            String automationErrorCount = "";
            String skipCount = "";

            if (pass_count > 0) {
                passCount = "<td bgcolor=\"" + passColor + "\"><font color=\"white\"><b>" + pass_count
                        + "</b></font></td>";
            } else {
                passCount = "<td>" + pass_count + "</td>";
            }

            if (fail_count > 0) {
                failCount = "<td bgcolor=\"" + failColor + "\"><font color=\"white\"><b>" + fail_count
                        + "</b></font></td>";
            } else {
                failCount = "<td>" + fail_count + "</td>";
            }
            if (fail_automation_count > 0) {
                automationErrorCount = "<td bgcolor=\"" + warnColor + "\"><font color=\"white\"><b>"
                        + fail_automation_count + "</b></font></td>";
            } else {
                automationErrorCount = "<td>" + fail_automation_count + "</td>";
            }

            if (skip_count > 0) {
                skipCount = "<td bgcolor=\"" + skipColor + "\"><font color=\"white\"><b>" + skip_count
                        + "</b></font></td>";
            } else {
                skipCount = "<td>" + skip_count + "</td>";
            }
            if (!emailable || !disableCss) {
                dashboardResults.append("<tr><td><b><a href='" + TestHelper.jenkinsBuildUrl
                        + TestHelper.jenkinsCustomReportTitle + TestHelper.customReportDirLink + fileName + "'>"
                        + dashboardModule + "</b></td><td>"
                        // + testName + "</b></td><td>"  
                        + unique_testcase + "</td><td>" + values.length + "</td>" + passCount + failCount
                        + automationErrorCount + skipCount + "<td>" + finalString + "</td><td><font color=\""
                        + passPercentageColor + "\"><b>" + passPercent + " %" + "</b></font></td></tr>");
            } else {
                dashboardResults.append("<tr><td><b>" + dashboardModule + "</b></td><td>"
                //+ testName + "</b></td><td>"  
                        + unique_testcase + "</td><td>" + values.length + "</td><td>" + pass_count + "</td><td>"
                        + fail_count + "</td><td>" + fail_automation_count + "</td><td>" + skip_count + "</td><td>"
                        + finalString + "</td><td><b>" + passPercent + " %" + "</td></tr>");
            }
            if (total_browser_combinations < values.length) {
                total_browser_combinations = values.length;
            }

            total_unique_testcases += unique_testcase;
        }

        dashboardResults.append("</tbody></table>");

        if (!emailable || !disableCss) {
            String suite_pass = "";
            String suite_fail = "";
            String suite_automation_error = "";
            String suite_skip = "";

            if (suite_totalPassedMethods > 0) {
                suite_pass = "<td bgcolor=\"" + passColor + "\"><font color=\"white\"><b>"
                        + suite_totalPassedMethods + "</b></font></td>";
            } else {
                suite_pass = "<td>" + suite_totalPassedMethods + "</td>";
            }

            if (suite_totalFailedMethods > 0) {
                suite_fail = "<td bgcolor=\"" + failColor + "\"><font color=\"white\"><b>"
                        + suite_totalFailedMethods + "</b></font></td>";
            } else {
                suite_fail = "<td>" + suite_totalFailedMethods + "</td>";
            }
            if (suite_totalAutomationErrors > 0) {
                suite_automation_error = "<td bgcolor=\"" + warnColor + "\"><font color=\"white\"><b>"
                        + suite_totalAutomationErrors + "</b></font></td>";
            } else {
                suite_automation_error = "<td>" + suite_totalAutomationErrors + "</td>";
            }
            if (suite_totalSkippedMethods > 0) {
                suite_skip = "<td bgcolor=\"" + skipColor + "\"><font color=\"white\"><b>"
                        + suite_totalSkippedMethods + "</b></font></td>";
            } else {
                suite_skip = "<td>" + suite_totalSkippedMethods + "</td>";
            }

            // Summary Table
            f_out.println("<p><b>Overall Execution Summary</b></p>");

            if (!emailable) {
                f_out.println("<table class=\"tablesorter\" width=\"100%\">");
            } else {
                f_out.println("<table " + classParam + "  cellspacing=\"0\" cellpadding=\"0\" width=\"91%\">");
            }
            f_out.println(//"<table class=\"param\" width=\"100%\">"+
                    "<thead><tr><th>Test Suite Name</th><th>" + "# Unique TestCases</th><th>"
                            + "# Combinations</th> <th>" + "# Passed</th> <th>" + "# Failed</th> <th>"
                            + "# Warning</th> <th>" + "# Skipped</th><th>" + "# Total</th> <th>"
                            + "Success Rate</th> </tr> </thead>" + " <tbody> <tr><td><b>" + suiteName
                            + "</b></td><td>" + total_unique_testcases + "</td><td>" + total_browser_combinations
                            + "</td>" + suite_pass + suite_fail + suite_automation_error + suite_skip + "<td>"
                            + (suite_totalPassedMethods + suite_totalFailedMethods + suite_totalSkippedMethods
                                    + suite_totalAutomationErrors)
                            + "</td><td><font color=\"" + passPercentageColor + "\"><b>" + suite_passPercentage
                            + " %" + "</b></font></td></tr></tbody></table>");
        } else {
            f_out.println("<b><font color=\"" + titleColor + "\">Overall Execution Summary</font></b><br/><br/>");
            f_out.println("<table " + classParam + "  cellspacing=\"0\" cellpadding=\"0\" width=\"91%\">"
                    + "<thead><tr><th>Test Suite Name</th><th>" + "# Unique TestCases</th><th>"
                    + "# Combinations</th> <th>" + "# Passed</th> <th>" + "# Failed</th> <th>"
                    + "# Warning</th> <th>" + "# Skipped</th><th>" + "# Total</th> <th>"
                    + "Success Rate</th> </tr> </thead>" + " <tbody> <tr><td><b>" + suiteName + "</b></td><td>"
                    + total_unique_testcases + "</td><td>" + total_browser_combinations + "</td><td>"
                    + suite_totalPassedMethods + "</td><td>" + suite_totalFailedMethods + "</td><td>"
                    + suite_totalAutomationErrors + "</td><td>" + suite_totalSkippedMethods + "</td><td>"
                    + (suite_totalPassedMethods + suite_totalFailedMethods + suite_totalSkippedMethods
                            + suite_totalAutomationErrors)
                    + "</td><td>" + suite_passPercentage + " %" + "</td></tr></tbody></table>");

        }
        f_out.flush();

        f_out.println("<br/>");
        f_out.println("<p><b>Modulewise Execution Summary</b></p>");
        f_out.println(dashboardResults);
        //        if(!emailable){
        //        f_out.println("<br/><h4>Legend:</h4>");
        //        f_out.print("<ul>");
        //        f_out.println("<li>T: Unique Testcase</li>");
        //        f_out.println("<li>B: Unique Browser Combination</li>");
        //        f_out.print("</ul>");
        //        }else{
        f_out.println("<br/><br/><br/><br/>");
        //        }
        f_out.flush();
    }

    synchronized private void generateModuleOverallTestReport(String testName, String moduleVar,
            List<ISuite> suites, String newFileName) throws Exception {
        StringBuilder moduleResults = new StringBuilder();

        final PrintWriter pw = TestHelper.createFileWriter(TestHelper.customReportDir + newFileName);

        startHtmlPage(pw);

        pw.println("<button class=\"sexybutton sexysimple sexylarge sexyblack\" onClick=\"location.href='"
                + TestHelper.customizedReportFileLink//customized-test-run-report.html+
                + "'\"><span class=\"prev\">Back to Overall Execution Summary</span></button>");
        pw.println("<br/><br/><br/><fieldset><legend><b>Testwise Overall Execution Details</b></legend><br/>"
                + "<table class=\"details\" cellspacing=0 cellpadding=0><tr><td><b>Module Name: </b></td><td>"
                + moduleVar + "</td></tr></table></fieldset><br/><br/>");

        moduleResults
                .append("<table id=\"myTable\" width=\"100%\" cellspacing=0 cellpadding=0 class=\"tablesorter\">");
        moduleResults.append("<thead><tr><th>Test Name</th> " +
        //"<th>Module</th> <th>Group</th>"+
                "<th>Browser</th> <th>Version</th> <th>OS</th>"
                + "<th>Node IP</th><th># Passed</th> <th># Failed</th> <th># Warning</th> <th># Skipped</th>"
                + "<th># Total</th> <th>Success Rate</th> </tr> </thead> <tbody>");

        int totalPassedMethods = 0;
        int totalFailedMethods = 0;
        int totalAutomationErrors = 0;
        int totalSkippedMethods = 0;

        String passPercentage = "";

        String suiteName = "";
        ITestContext overview = null;
        try {
            for (ISuite suite : suites) {
                suiteName = suite.getName();
                TestHelper.logger.info(">> " + suiteName + " <<");
                Map<String, ISuiteResult> tests = suite.getResults();

                for (ISuiteResult r : tests.values()) {
                    overview = r.getTestContext();
                    testName = overview.getName();

                    totalPassedMethods = overview.getPassedTests().getAllMethods().size();
                    totalFailedMethods = overview.getFailedTests().getAllMethods().size();
                    totalAutomationErrors = overview.getFailedButWithinSuccessPercentageTests().getAllMethods()
                            .size();
                    totalSkippedMethods = overview.getSkippedTests().getAllMethods().size();

                    NumberFormat nf = NumberFormat.getInstance();
                    nf.setMaximumFractionDigits(2);
                    nf.setGroupingUsed(true);

                    passPercentage = getPercentage(nf, totalPassedMethods, totalPassedMethods + totalFailedMethods);

                    String includedModule = "";
                    String includedGroup = "";

                    ITestNGMethod[] allTestMethods = overview.getAllTestMethods();
                    for (ITestNGMethod testngMethod : allTestMethods) {
                        String[] modules = testngMethod.getGroups();
                        for (String module : modules) {
                            for (String moduleName : TestHelper.MODULES) {
                                if (module.equalsIgnoreCase(moduleName)) {
                                    if (!(includedModule.contains(module))) {
                                        includedModule = includedModule + " " + module;
                                    }
                                }
                            }
                            for (String groupName : TestHelper.TEST_GROUPS) {
                                if (module.equalsIgnoreCase(groupName)) {
                                    if (!(includedGroup.contains(module))) {
                                        includedGroup = includedGroup + " " + module;
                                    }
                                }
                            }
                        }
                    }

                    String[] nodeInfo = getNodeInfo(overview, testName);

                    String browser = nodeInfo[1];
                    String browser_version = nodeInfo[2];
                    String platform = nodeInfo[0];
                    String nodeIp = nodeInfo[3];

                    if (platform == null || platform.trim().length() == 0) {
                        platform = "N/A";
                    }

                    if (browser_version == null || browser_version.trim().length() == 0) {
                        browser_version = "N/A";
                    }

                    if (browser == null || browser.trim().length() == 0) {
                        browser = "N/A";
                    }

                    if (browser.equalsIgnoreCase("firefox")) {
                        browser = "Firefox";
                    } else if (browser.equalsIgnoreCase("chrome")) {
                        browser = "Chrome";
                    } else if (browser.equalsIgnoreCase("internet explorer")) {
                        browser = "IE";
                    }

                    if (platform.equalsIgnoreCase("xp")) {
                        platform = "XP";
                    } else if (platform.equalsIgnoreCase("windows7")) {
                        platform = "Win 7";
                    } else if (platform.equalsIgnoreCase("mac")) {
                        platform = "Mac";
                    } else {

                    }

                    if (includedModule.equalsIgnoreCase(moduleVar)) {
                        String fileName = testName + "-customized-report.html";

                        if (nodeIp == null || nodeIp.trim().length() == 0) {
                            nodeIp = "?";
                        }

                        try {
                            generateModuleWiseTestReport(testName, suites, fileName, moduleVar, nodeIp);
                        } catch (IOException e) {
                            e.printStackTrace();
                        }

                        String passCount = "";
                        String failCount = "";
                        String automationErrorCount = "";
                        String skipCount = "";

                        if (totalPassedMethods > 0) {
                            passCount = "<td bgcolor=\"" + passColor + "\"><font color=\"white\"><b>"
                                    + totalPassedMethods + "</b></font></td>";
                        } else {
                            passCount = "<td>" + totalPassedMethods + "</td>";
                        }

                        if (totalFailedMethods > 0) {
                            failCount = "<td bgcolor=\"" + failColor + "\"><font color=\"white\"><b>"
                                    + totalFailedMethods + "</b></font></td>";
                        } else {
                            failCount = "<td>" + totalFailedMethods + "</td>";
                        }
                        if (totalAutomationErrors > 0) {
                            automationErrorCount = "<td bgcolor=\"" + warnColor + "\"><font color=\"white\"><b>"
                                    + totalAutomationErrors + "</b></font></td>";
                        } else {
                            automationErrorCount = "<td>" + totalAutomationErrors + "</td>";
                        }
                        if (totalSkippedMethods > 0) {
                            skipCount = "<td bgcolor=\"" + skipColor + "\"><font color=\"white\"><b>"
                                    + totalSkippedMethods + "</b></font></td>";
                        } else {
                            skipCount = "<td>" + totalSkippedMethods + "</td>";
                        }

                        moduleResults.append(
                                "<tr><td><b><a href=\"" + fileName + "\">" + testName + "</a></b></td>" + "<td>"
                                //+ includedModule + "</td><td>" + includedGroup + "</td><td>" 
                                        + browser + "</td><td>" + browser_version + "</td><td>" + platform
                                        + "</td><td>" + nodeIp + "</td>" + passCount + failCount
                                        + automationErrorCount + skipCount + "</td><td>"
                                        + (totalPassedMethods + totalFailedMethods + +totalAutomationErrors
                                                + totalSkippedMethods)
                                        + "</td><td><font color=\"" + passPercentageColor + "\"><b>"
                                        + passPercentage + " %" + "</b></font></td></tr>");
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();//"Exception in report!!!: "+e);
        }

        moduleResults.append("</tbody></table>");
        pw.println(moduleResults);
        endHtmlPage(pw);
        pw.flush();
        pw.close();
    }

    synchronized private void generateModuleWiseTestReport(String testName, List<ISuite> suites, String newFileName,
            String passedModule, String nodeIp) throws IOException {
        final PrintWriter pw = TestHelper.createFileWriter(TestHelper.customReportDir + newFileName);

        startHtmlPage(pw);

        pw.println("<button class=\"sexybutton sexysimple sexylarge sexyblack\" onClick=\"location.href='"
                + passedModule + "-Overall-customized-report.html"
                + "'\"><span class=\"prev\">Back to Modulewise Test Execution Summary</span></button>");

        pw.println(
                "<br/><br/><br/><fieldset><legend><b>Modulewise Execution Details</b></legend><br/><table class=\"details\" cellspacing=0 cellpadding=0><tr><td><b>Test Name: </b></td><td>"
                        + testName + "</td></tr>");

        pw.println("<tr><td><b>Node IP: </b></td><td>" + nodeIp + "</td></tr></table></fieldset><br/><br/>");
        pw.println("<table id=\"myTable\" width=\"100%\" cellspacing=0 cellpadding=0 class=\"tablesorter\">");
        pw.println("<thead><tr><th>Module Name</th><th># Passed</th>" + "<th># Failed</th><th># Warning</th>"
                + "<th># Skipped</th><th># Total</th><th>Success Rate</th></tr></thead>");

        HashMap<String, ArrayList<ITestNGMethod>> moduleMap = new HashMap<String, ArrayList<ITestNGMethod>>();

        ITestContext overview = null;

        for (ISuite suite : suites) {
            Map<String, ISuiteResult> tests = suite.getResults();
            for (ISuiteResult r : tests.values()) {
                overview = r.getTestContext();
                if ((overview.getName()).equalsIgnoreCase(testName)) {
                    ITestNGMethod[] testngMethods = overview.getAllTestMethods();

                    ArrayList<HashMap<String, ITestNGMethod>> moduleMethods = new ArrayList<HashMap<String, ITestNGMethod>>();

                    for (ITestNGMethod testngMethod : testngMethods) {
                        String[] groups = testngMethod.getGroups();
                        for (String group : groups) {
                            for (String module : TestHelper.MODULES) {
                                if (group.equalsIgnoreCase(module)) {
                                    HashMap<String, ITestNGMethod> tempMap = new HashMap<String, ITestNGMethod>();
                                    tempMap.put(module, testngMethod);
                                    moduleMethods.add(tempMap);
                                }
                            }
                        }
                    }

                    for (String module : TestHelper.MODULES) {
                        ArrayList<ITestNGMethod> moduleTestMethods = new ArrayList<ITestNGMethod>();

                        Iterator<HashMap<String, ITestNGMethod>> it = moduleMethods.iterator();

                        while (it.hasNext()) {
                            String moduleName = "";
                            ITestNGMethod testMethod = null;

                            HashMap<String, ITestNGMethod> moduleWithTestMethod = it.next();
                            if (moduleWithTestMethod.containsKey(module)) {
                                moduleName = module;
                                testMethod = moduleWithTestMethod.get(module);
                            }

                            if (module.equalsIgnoreCase(moduleName)) {
                                moduleTestMethods.add(testMethod);
                            }
                        }

                        moduleMap.put(module, moduleTestMethods);
                    }
                }
            }
        }

        Set<String> keySet = moduleMap.keySet();
        Iterator<String> it = keySet.iterator();

        for (ISuite suite : suites) {
            Map<String, ISuiteResult> tests = suite.getResults();
            for (ISuiteResult r : tests.values()) {
                overview = r.getTestContext();
                if ((overview.getName()).equalsIgnoreCase(testName)) {
                    while (it.hasNext()) {
                        String moduleName = it.next();

                        int totalPassedMethods = 0;
                        int totalFailedMethods = 0;
                        int totalAutomationErrors = 0;
                        int totalSkippedMethods = 0;
                        int totalSkippedConfigurations = 0;
                        int totalFailedConfigurations = 0;

                        ArrayList<ITestNGMethod> values = moduleMap.get(moduleName);
                        ListIterator<ITestNGMethod> it2 = values.listIterator();

                        while (it2.hasNext()) {
                            ITestNGMethod method = it2.next();

                            int failedMethods = overview.getFailedTests().getResults(method).size();
                            int failedAutomationErrors = overview.getFailedButWithinSuccessPercentageTests()
                                    .getResults(method).size();
                            int passedMethods = overview.getPassedTests().getResults(method).size();
                            int skippedMethods = overview.getSkippedTests().getResults(method).size();
                            int failedConfiguration = overview.getFailedConfigurations().getResults(method).size();
                            int skippedConfiguration = overview.getSkippedConfigurations().getResults(method)
                                    .size();

                            totalPassedMethods += passedMethods;
                            totalFailedMethods += failedMethods;
                            totalAutomationErrors += failedAutomationErrors;
                            totalSkippedMethods += skippedMethods;
                            totalFailedConfigurations += failedConfiguration;
                            totalSkippedConfigurations += skippedConfiguration;

                        }

                        if (values.size() > 0) {
                            String fileName = testName + "-" + moduleName + "-customized-report.html";
                            try {
                                generateModuleTestMethodSummary(testName, moduleName, suites, fileName, values,
                                        nodeIp);
                            } catch (IOException e) {
                                e.printStackTrace();
                            }

                            int totalMethods = totalPassedMethods + totalFailedMethods + totalAutomationErrors
                                    + totalSkippedMethods;

                            NumberFormat nf = NumberFormat.getInstance();
                            nf.setMaximumFractionDigits(2);
                            nf.setGroupingUsed(false);

                            String passPercentage = getPercentage(nf, totalPassedMethods, totalMethods);

                            generateModulesRow(pw, fileName, moduleName, totalPassedMethods, totalFailedMethods,
                                    totalAutomationErrors, totalSkippedMethods, totalSkippedConfigurations,
                                    totalFailedConfigurations, totalMethods, passPercentage);
                        }
                    }
                    break;
                }
            }
        }

        pw.println("</table>");
        endHtmlPage(pw);
        pw.flush();
        pw.close();
    }

    synchronized private void generateModuleTestMethodSummary(String testName, String modulename,
            List<ISuite> suites, String fileName, ArrayList<ITestNGMethod> testngMethods, String nodeIp)
            throws IOException {
        final PrintWriter pw = TestHelper.createFileWriter(TestHelper.customReportDir + fileName);

        startHtmlPage(pw);

        String htmlFile = testName + "-customized-report.html";
        String modulewiseTestFileName = testName + "-" + modulename + "-customized-report.html";

        pw.println("<button class=\"sexybutton sexysimple sexylarge sexyblack\" onClick=\"location.href='"
                + htmlFile + "'\"><span class=\"prev\">Back to Modulewise Execution Summary</span></button>");
        pw.println("<br/><br/><br/><fieldset><legend><b>Details</b></legend><br/>"
                + "<table class=\"details\" cellspacing=0 cellpadding=0><tr><td><b>Test Name: </b></td><td>"
                + testName + "</td></tr>");
        pw.println("<tr><td><b>Module Name: </b></td><td>" + modulename + "</td></tr>");
        pw.println("<tr><td><b>Node IP: </b></td><td>" + nodeIp + "</td></tr></table></fieldset><br/><br/>");

        pw.println("<table id=\"myTable\" width=\"100%\" cellspacing=0 cellpadding=0 class=\"tablesorter\">");
        pw.println("<thead><tr><th  style=\"text-align:left\">Method Name</th>" + "<th>Total Time (ms)</th>"
                + "<th>Status</th>"
                + "<th style=\"text-align:center\">Stack Trace | Test Parameters</th></tr></thead>");

        for (ISuite suite : suites) {
            Map<String, ISuiteResult> tests = suite.getResults();
            for (ISuiteResult re : tests.values()) {
                ITestContext overview = re.getTestContext();
                if ((overview.getName()).equalsIgnoreCase(testName)) {
                    Iterator<ITestNGMethod> it = testngMethods.iterator();
                    while (it.hasNext()) {
                        ITestNGMethod method = it.next();
                        String[] allGroups = method.getGroups();

                        String methodName = "";
                        //String className = "";

                        for (String grp : allGroups) {
                            if (grp.equalsIgnoreCase(modulename)) {
                                methodName = method.getMethodName();
                                //className = method.getTestClass().getName();

                                ArrayList<Set<ITestResult>> statusResult = new ArrayList<Set<ITestResult>>();

                                Set<ITestResult> failedTestAutomationStatus = overview
                                        .getFailedButWithinSuccessPercentageTests().getResults(method);
                                if (!(failedTestAutomationStatus.isEmpty())) {
                                    statusResult.add(setTestStatus(failedTestAutomationStatus,
                                            ITestResult.SUCCESS_PERCENTAGE_FAILURE));
                                }

                                //TODO -- these 2 sets are somehow missing from the report, not sure they are attached
                                // with @test method or @BeforeMethod, so could be commented out if they are always empty
                                Set<ITestResult> confFailedTestStatus = overview.getFailedConfigurations()
                                        .getResults(method);
                                if (!(confFailedTestStatus.isEmpty())) {
                                    statusResult.add(setTestStatus(confFailedTestStatus,
                                            ITestResult.SUCCESS_PERCENTAGE_FAILURE));
                                }
                                Set<ITestResult> confSkippedTestStatus = overview.getSkippedConfigurations()
                                        .getResults(method);
                                if (!(confSkippedTestStatus.isEmpty())) {
                                    statusResult.add(setTestStatus(confSkippedTestStatus, ITestResult.SKIP));
                                }
                                // ***************************************************************************************************

                                Set<ITestResult> skippedTestStatus = overview.getSkippedTests().getResults(method);
                                if (!(skippedTestStatus.isEmpty())) {
                                    statusResult.add(setTestStatus(skippedTestStatus, ITestResult.SKIP));
                                }

                                Set<ITestResult> passedTestStatus = overview.getPassedTests().getResults(method);
                                if (!(passedTestStatus.isEmpty())) {
                                    statusResult.add(setTestStatus(passedTestStatus, ITestResult.SUCCESS));
                                }
                                Set<ITestResult> failedTestStatus = overview.getFailedTests().getResults(method);
                                if (!(failedTestStatus.isEmpty())) {
                                    statusResult.add(setTestStatus(failedTestStatus, ITestResult.FAILURE));
                                }

                                if (methodName == null || methodName.trim() == "") {
                                    methodName = " Empty ?";
                                }

                                // ________________________________________________________
                                String test_tag = "";
                                pw.print("<tr><td  style=\"text-align:left\" colspan=\"3\"><b>"
                                        + methodName.toUpperCase() + "</b>");

                                pw.println("" + "</td>" + "<td bgcolor=\"white\" style=\"border: 0px;\"></td>"
                                        + "</tr>");

                                Iterator<Set<ITestResult>> statusIterator = statusResult.iterator();

                                while (statusIterator.hasNext()) {
                                    Set<ITestResult> status = statusIterator.next();

                                    StringBuilder stackTrace;
                                    StringBuilder failedConf;

                                    Iterator<ITestResult> it2 = status.iterator();

                                    List<String> msgs = new ArrayList<String>();

                                    String executionStatus = "";

                                    long time_start = Long.MAX_VALUE;
                                    long time_end = Long.MIN_VALUE;

                                    Throwable exception = null;
                                    String screenshotFileLink = "";
                                    String currentTestUrl = "";
                                    String jsError = "";

                                    ITestResult result = null;

                                    while (it2.hasNext()) {

                                        //                                        pw.println("<tr><td  style=\"text-align:left\"><b>"
                                        //                                                + methodName.toUpperCase() + "</b></td>");

                                        stackTrace = new StringBuilder();
                                        failedConf = new StringBuilder();

                                        result = it2.next();

                                        time_start = result.getStartMillis();
                                        time_end = result.getEndMillis();
                                        Object[] params = result.getParameters();
                                        //                                        
                                        //                                        if(test_tag.equals("")){
                                        //                                           test_tag = getTestTag(params);
                                        //                                           if(status.size()==1){
                                        //                                           pw.println( " ["+test_tag+"]"
                                        //                                        +"</td>"
                                        //                                        + "<td bgcolor=\"white\" style=\"border: 0px;\"></td>"
                                        //                                                + "</tr>");
                                        //                                           }else {
                                        //                                               pw.println( ""
                                        //                                                       +"</td>"
                                        //                                                       + "<td bgcolor=\"white\" style=\"border: 0px;\"></td>"
                                        //                                                               + "</tr>");
                                        //                                           }
                                        //                                        }

                                        // String test_para = getTestPara(params,status.size()>1?0:1);
                                        String test_para = getTestPara(params, 0);
                                        int execStatus = result.getStatus();
                                        if (execStatus == ITestResult.SUCCESS) {
                                            executionStatus = "PASS";
                                        } else if (execStatus == ITestResult.FAILURE) {
                                            executionStatus = "FAIL";
                                        } else if (execStatus == ITestResult.SKIP) {
                                            executionStatus = "SKIP";
                                        } else if (execStatus == ITestResult.SUCCESS_PERCENTAGE_FAILURE) {
                                            executionStatus = "WARN";
                                        }

                                        //                                        if (execStatus == ITestResult.SKIP)
                                        //                                        {
                                        //                                            status = overview.getFailedConfigurations().getAllResults();
                                        //                                            it2 = status.iterator();
                                        //                                            failedConf.append("<br/>");
                                        //                                            while (it2.hasNext())
                                        //                                            {
                                        //                                                result = it2.next();
                                        //                                                failedConf.append("<b>Failed Configuration - "
                                        //                                                        + result.getMethod().getMethodName() + "</b>");
                                        //                                                failedConf.append("<br/>");
                                        //                                            }
                                        //                                            
                                        //                                            status = overview.getSkippedConfigurations().getAllResults();
                                        //                                            it2 = status.iterator();
                                        //                                            failedConf.append("<br/>");
                                        //                                            while (it2.hasNext())
                                        //                                            {
                                        //                                                result = it2.next();
                                        //                                                failedConf.append("<b>Skipped Configuration - "
                                        //                                                        + result.getMethod().getMethodName() + "</b>");
                                        //                                                failedConf.append("<br/>");
                                        //                                            }
                                        //                                            exception = result.getThrowable();
                                        //                                        } else
                                        {
                                            exception = result.getThrowable();
                                            if (exception == null) {
                                                if (execStatus == ITestResult.SKIP) {
                                                    status = overview.getFailedConfigurations().getAllResults();
                                                    it2 = status.iterator();
                                                    failedConf.append("<br/>");
                                                    while (it2.hasNext()) {
                                                        result = it2.next();
                                                        failedConf.append("<b>Failed Configuration - "
                                                                + result.getMethod().getMethodName() + "</b>");
                                                        failedConf.append("<br/>");
                                                    }

                                                    status = overview.getSkippedConfigurations().getAllResults();
                                                    it2 = status.iterator();
                                                    failedConf.append("<br/>");
                                                    while (it2.hasNext()) {
                                                        result = it2.next();
                                                        failedConf.append("<b>Skipped Configuration - "
                                                                + result.getMethod().getMethodName() + "</b>");
                                                        failedConf.append("<br/>");
                                                    }
                                                    exception = result.getThrowable();
                                                }
                                            }
                                        }

                                        msgs = Reporter.getOutput(result);

                                        /*
                                         * If enable logs is false, then only
                                         * take the screenshot.
                                         */
                                        if (//(TestHelper.getTestConfig("ENABLE_LOGS_IN_CUSTOM_REPORT").equalsIgnoreCase("false")) && 
                                        (msgs != null)) {
                                            for (String line : msgs) {
                                                if (line.contains(TestHelper.jsErrorMarkerInOutputFile)) {
                                                    jsError = line.substring(line
                                                            .indexOf(TestHelper.jsErrorMarkerInOutputFile)
                                                            + (TestHelper.jsErrorMarkerInOutputFile.length()),
                                                            line.length()).trim();
                                                }
                                                if (line.contains(TestHelper.testUrlMarkerInOutputFile)) {
                                                    currentTestUrl = line.substring(line
                                                            .indexOf(TestHelper.testUrlMarkerInOutputFile)
                                                            + (TestHelper.testUrlMarkerInOutputFile.length()),
                                                            line.length());
                                                }

                                                if (line.contains(TestHelper.testScreenshotMarkerInOutputFile)) {
                                                    screenshotFileLink = line.substring(line
                                                            .indexOf(TestHelper.testScreenshotMarkerInOutputFile)
                                                            + (TestHelper.testScreenshotMarkerInOutputFile
                                                                    .length()),
                                                            line.length());
                                                    break;
                                                }

                                            }
                                        }

                                        /*
                                         * If enable logs is true, take the
                                         * whole log along with screenshot.
                                         */
                                        if ((TestHelper.getTestConfig("ENABLE_LOGS_IN_CUSTOM_REPORT")
                                                .equalsIgnoreCase("true")) && (msgs != null)) {
                                            //                                            if(currentTestUrl!=null && currentTestUrl.trim().length()!=0){
                                            //                                            stackTrace
                                            //                                            .append("<br/><a target=\"_blank\" href=\""
                                            //                                                            + currentTestUrl
                                            //                                                            + "\"><u><b>URL</b></u> - "
                                            //                                                    + currentTestUrl
                                            //                                                    + "</a>");
                                            //                                            }    
                                            for (String line : msgs) {
                                                stackTrace.append("<br/>" + line);
                                            }
                                        } else if (screenshotFileLink != null
                                                && screenshotFileLink.trim().length() != 0) {

                                            stackTrace.append(
                                                    "<br/><div id=\"screenshot-div\" style=\"cursor:pointer;color:blue;\"><u><b>Enlarge Screenshot</b></u> - "
                                                            + currentTestUrl + "</div><br/>"
                                                            // +(jsError.equals("")?jsError:"<b>JS Error:</b>"+jsError+"<br/>")
                                                            + "<a target=\"_blank\" href=\"" + screenshotFileLink
                                                            + "\"><b>View Screenshot in New Window/Tab</b></a><br/><br/><img id=\"screenshot\" src='"
                                                            + screenshotFileLink
                                                            + "' height='300' width='300' border=\"1\" style=\"position: relative; left: 0px;\"/>"
                                                            + (jsError.equals("") ? jsError
                                                                    : "<br/><br/><b>JS Error:</b><br/>" + jsError
                                                                            + "<br/>"));
                                        }

                                        if (msgs != null) {
                                            msgs.clear();
                                        }

                                        Random randomGenerator = new Random();
                                        int randomInt = randomGenerator.nextInt(100000);

                                        String stackTraceFile = testName + "-" + modulename + "-" + methodName + "-"
                                                + randomInt + "-" + "custom-report.html";

                                        stackTrace.append("<br/>" + failedConf.toString());

                                        generateStackTraceReport(modulewiseTestFileName, stackTraceFile, stackTrace,
                                                exception, method, nodeIp, result);

                                        String link = "<button class=\"sexybutton sexysimple sexyblack\" onClick=\"location.href='"
                                                + stackTraceFile + "'\"><span class=\"info\">"
                                                + "View StackTrace/Screenshots" + "</span></button>";

                                        if (executionStatus.equalsIgnoreCase("pass")) {
                                            executionStatus = "<td bgcolor=\"" + passColor
                                                    + "\"><font color=\"white\"><b>" + executionStatus
                                                    + "</b></font></td>";
                                        } else if (executionStatus.equalsIgnoreCase("fail")) {
                                            executionStatus = "<td bgcolor=\"" + failColor
                                                    + "\"><font color=\"white\"><b>" + executionStatus
                                                    + "</b></font></td>";
                                        } else if (executionStatus.equalsIgnoreCase("warn")) {
                                            executionStatus = "<td bgcolor=\"" + warnColor
                                                    + "\"><font color=\"white\"><b>" + executionStatus
                                                    + "</b></font></td>";
                                        } else if (executionStatus.equalsIgnoreCase("skip")) {
                                            executionStatus = "<td bgcolor=\"" + skipColor
                                                    + "\"><font color=\"white\"><b>" + executionStatus
                                                    + "</b></font></td>";
                                        } else {
                                            executionStatus = "<td>" + executionStatus + "</td>";
                                        }

                                        pw.println(//"<tr><td style=\"text-align:left\">" + "[Class Name] " + className
                                                "<tr><td style=\"text-align:left\">" + "[Test Params] " + test_para
                                                        + "</td><td>" + (time_end - time_start) + "</td>"
                                                        + executionStatus
                                                        + "<td bgcolor=\"white\" style=\"text-align:center;border: 0px;\">"
                                                        + link + "</td></tr>");

                                        pw.flush();
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        pw.println("</table>");
        endHtmlPage(pw);
        pw.flush();
        pw.close();
    }

    private void generateStackTraceReport(String fileName, String stackTraceFile, StringBuilder stackTrace,
            Throwable exception, ITestNGMethod method, String _nodeIp, ITestResult result) throws IOException {
        final PrintWriter fw = TestHelper.createFileWriter(TestHelper.customReportDir + stackTraceFile);
        startHtmlPage(fw);

        fw.println("<button class=\"sexybutton sexysimple sexylarge sexyblack\" onClick=\"location.href='"
                + fileName + "'\"><span class=\"prev\">Back to Methodwise Execution Summary</span></button>");
        fw.println("<br/><br/><br/>");

        if (result != null) {
            fw.println("<fieldset><legend><font color=\"blue\"><b>Test Parameters</b></font></legend><br/>");
            fw.println("<table cellspacing=0 cellpadding=0 class=\"details\" ");

            Object[] params = result.getParameters();
            if (params != null) {
                for (int i = 0; i < params.length; i++) {
                    /*
                     * if (params[i].toString().length() > 80) { params[i] =
                     * params[i].toString().substring(0, 78) + " ..."; }
                     */
                    if (i == 1 && params.length > 3 && !((String) params[i]).trim().equals("")) {
                        fw.println("<tr><td><b>[Parameter " + i + "]</b></td><td  bgcolor=\"" + warnColor
                                + "\"><font color=\"white\">" + "KnownBug: " + params[i] + "</font></td></tr>");
                    } else {
                        fw.println("<tr><td><b>[Parameter " + i + "]</b></td><td>" + params[i] + "</td></tr>");
                    }
                }
            }

            fw.println("</table>");
            fw.println("</fieldset>");
            fw.println("<br/>");
        }

        fw.println("<fieldset><legend><font color=\"green\"><b>Console Log/Screenshot</b></font></legend><br/>");
        if (TestHelper.getTestConfig("ENABLE_LOGS_IN_CUSTOM_REPORT").equalsIgnoreCase("false")) {
            fw.println(
                    "<p><b>[Debug] - </b>Console logs in custom report is disabled. To view the Console logs please set the ENABLE_LOGS_IN_CUSTOM_REPORT as true in properties file!</p>");
        }

        String[] nodeInfo = getNodeInfo(result.getTestContext(),
                result.getTestContext().getName() + method.getMethodName());

        String browser = nodeInfo[1];
        String browser_version = nodeInfo[2];
        String platform = nodeInfo[0];
        String nodeIp = nodeInfo[3];
        //        Date endDate = new Date();
        //        try{
        //            endDate =     result.getTestContext().getEndDate();           
        //        }catch(Exception e){
        //            
        //        }

        fw.println("<p><b>[Platform] - </b>" + platform + "</p>");
        fw.println("<p><b>[Browser] - </b>" + browser + "</p>");
        fw.println("<p><b>[Browser Version] - </b>" + browser_version + "</p>");
        fw.println("<p><b>[Node IP] - </b>" + nodeIp + "</p>");
        //fw.println("<p><b>[Timestamp] : </b>" + (endDate) + "</p>");
        fw.println(stackTrace + "<br/>");
        fw.println("</fieldset>");
        fw.println("<br/>");

        if (exception != null) {
            fw.println("<fieldset><legend><font color=\"red\"><b>Stack Trace</b></font></legend><br/>");
            generateExceptionReport(exception, method, fw);
            fw.println("</fieldset>");
        }

        endHtmlPage(fw);
        fw.flush();
        fw.close();
    }

    protected void generateExceptionReport(Throwable exception, ITestNGMethod method, PrintWriter pw) {
        pw.flush();
        generateExceptionReport(exception, method, exception.getLocalizedMessage(), pw);
    }

    private void generateExceptionReport(Throwable exception, ITestNGMethod method, String title,
            PrintWriter m_out) {

        m_out.println("<p>" + exception.getClass() + ": " + title + "</p><p>");

        StackTraceElement[] s1 = exception.getStackTrace();
        Throwable t2 = exception.getCause();
        if (t2 == exception) {
            t2 = null;
        }
        int maxlines = Math.min(100, StackTraceTools.getTestRoot(s1, method));
        for (int x = 0; x <= maxlines; x++) {
            m_out.println((x > 0 ? "<br/>at " : "") + Utils.escapeHtml(s1[x].toString()));
        }
        if (maxlines < s1.length) {
            m_out.println("<br/>" + (s1.length - maxlines) + " lines not shown");
        }
        if (t2 != null) {
            generateExceptionReport(t2, method, "Caused by " + t2.getLocalizedMessage(), m_out);
        }
        m_out.println("</p>");
        m_out.flush();
    }

    private void generateModulesRow(PrintWriter pw, String fileName, String moduleName, int passedMethods,
            int failedMethods, int failedAutomationErrors, int skippedMethods, int skippedConfiguration,
            int failedConfiguration, int totalMethods, String passPercentage) {

        String passCount = "";
        String failCount = "";
        String failAutomationCount = "";
        String skipCount = "";

        if (passedMethods > 0) {
            passCount = "<td bgcolor=\"" + passColor + "\"><font color=\"white\"><b>" + passedMethods
                    + "</b></font></td>";
        } else {
            passCount = "<td>" + passedMethods + "</td>";
        }

        if (failedMethods > 0) {
            failCount = "<td bgcolor=\"" + failColor + "\"><font color=\"white\"><b>" + failedMethods
                    + "</b></font></td>";
        } else {
            failCount = "<td>" + failedMethods + "</td>";
        }
        if (failedAutomationErrors > 0) {
            failAutomationCount = "<td bgcolor=\"" + warnColor + "\"><font color=\"white\"><b>"
                    + failedAutomationErrors + "</b></font></td>";
        } else {
            failAutomationCount = "<td>" + failedAutomationErrors + "</td>";
        }

        if (skippedMethods > 0) {
            skipCount = "<td bgcolor=\"" + skipColor + "\"><font color=\"white\"><b>" + skippedMethods
                    + "</b></font></td>";
        } else {
            skipCount = "<td>" + skippedMethods + "</td>";
        }

        pw.println("<tr><td><b><a href=\"" + fileName + "\">" + moduleName + "</a></b></td>" + passCount + failCount
                + failAutomationCount + skipCount + "<td>" + totalMethods + "</td><td><font color=\""
                + passPercentageColor + "\"><b>" + passPercentage + " %" + "</b></font></td></tr>");

        pw.flush();
    }

    private void generateAdditionalInfoReport(List<ISuite> suites, PrintWriter f_out) {
        generateAdditionalInfoReport(false, suites, f_out);
    }

    private void generateAdditionalInfoReport(boolean emailable, List<ISuite> suites, PrintWriter f_out) {
        if (!emailable) {
            f_out.println("<fieldset><legend><b>Configuration Details</b></legend><br/>"); // used for custom report 
            f_out.println("<table class=\"details\" cellspacing=0 cellpadding=0");
        } else {
            f_out.println("<b><font color=\"" + titleColor + "\">Configuration Details</font></b><br/><br/>");
            f_out.println("<table " + classDetails + " cellspacing=0 cellpadding=0");
        }

        f_out.println("<tr><td>Test Application: " + "</td><td>" + TestHelper.testApp + "</td></tr>");
        //f_out.println("<tr><td>Test Environment: " + "</td><td>" + TestHelper.getTestConfig("TEST_ENVIRONMENT") + "</td></tr>");
        f_out.println("<tr><td>Test Application URL: </td><td>" + "<a href=\"" + TestHelper.suiteTestUrl + "\">"
                + TestHelper.suiteTestUrl + "</a></td></tr>");

        for (ISuite suite : suites) {

            Map<String, ISuiteResult> tests = suite.getResults();
            for (ISuiteResult re : tests.values()) {
                ITestContext testContext = re.getTestContext();
                f_out.println("<tr><td>Test Application Build No: </td><td>" + testContext.getAttribute("RevNo")
                        + "</td></tr>");
                break;
            }

            f_out.println("<tr><td>Run Suite Parallel: </td><td>" + suite.getParallel() + "</td></tr>");
            break;
        }

        //        f_out.println("<tr><td>Using GRID: </td><td>" + "" +  TestHelper.useGrid  + "</td></tr>");

        //        String enableLogsInReport = TestHelper.getTestConfig("ENABLE_LOGS_IN_CUSTOM_REPORT");
        //        if (enableLogsInReport.equalsIgnoreCase("true"))
        //        {
        //            enableLogsInReport = "enabled";
        //        } else if (enableLogsInReport.equalsIgnoreCase("false"))
        //        {
        //            enableLogsInReport = "disabled";
        //        }
        //
        //        f_out.println("<tr><td>Console Logs in Report: </td><td>" + "" + enableLogsInReport + "</td></tr>");

        if (emailable) {
            if (TestHelper.isJenkinsTest) {
                f_out.println("<tr><td><i>Jenkins Report: </i></td><td>" + "<a href=\"" + TestHelper.jenkinsBuildUrl//+TestHelper.customReportFileName
                        + TestHelper.jenkinsCustomReportTitle + "\">" + "Customized HTML Report"
                        + "</a></td></tr>");
                f_out.println("<tr><td><i>Test History: </i></td><td>" + "<a href=\"" + TestHelper.jenkinsJOBUrl
                        + "\">" + TestHelper.jenkinsJOBUrl + "</a></td></tr>");

            }

            //                
            //                        + ""
            //                        + "<a href=\"" + "" + TestHelper.jenkinsBuildUrl+TestHelper.customReportFileName + "</td></tr>"); 
            //            }

        }
        f_out.println("</table>");
        f_out.println("<br/>");
        f_out.flush();
    }

    public static String[] getNodeInfo(ITestContext overview, String testName) {
        String[] nodeInfo = new String[4];
        try {
            String[] temp = TestHelper.testNodeProxy.get(testName).split("~");
            return temp;
        } catch (Exception e) {
            nodeInfo[0] = overview.getCurrentXmlTest().getParameter("platform");
            nodeInfo[1] = overview.getCurrentXmlTest().getParameter("browser");
            nodeInfo[2] = overview.getCurrentXmlTest().getParameter("browser_version");
            nodeInfo[3] = "N/A";
        }

        return nodeInfo;
    }

    //*****************************************************
    // **********  Static HTML ****************************
    //*****************************************************
    /** Starts HTML Stream */
    private static void startHtmlPage(PrintWriter out) {
        startHtmlPage(out, TestHelper.cssDir);
    }

    private static void startHtmlPage(PrintWriter out, String cssDir) {
        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>AOL Automation Test Results Summary</title>");

        /* Include Java Script and JQuery */
        out.println("<script type=\"text/javascript\" src=\"" + cssDir + "jquery-latest.js\"></script>");
        out.println("<script type=\"text/javascript\" src=\"" + cssDir + "jquery.tablesorter.js\"></script>");
        out.println(
                "<script type=\"text/javascript\"> $(document).ready(function(){$(\"#myTable\").tablesorter({sortList:[[1,0],[3,0],[4,0]], widgets: ['zebra']}) ;});</script>");
        out.println(
                "<script type=\"text/javascript\">function goConfirm(title, link){if(confirm(title) == true){ window.location.href = link; return true;} else { return false;}}</script>");
        out.println(
                "<script type=\"text/javascript\">$(document).ready(function(){ $('#screenshot-div').click(function() { $('#screenshot').animate({ width: 900,height: 650}, 5000, function() { });});});</script>");

        /* Include Style Sheets */
        out.println("<link rel=\"stylesheet\" href=\"" + cssDir + "sexybuttons.css\" type=\"text/css\" />");
        out.println("<link rel=\"stylesheet\" href=\"" + cssDir
                + "custom-report-stylesheet.css\" type=\"text/css\" />");

        out.println("</head>");
        out.println("<body><br/>");

        out.println(
                "<div class=\"layout\"> <div class=\"box\"><div class=\"silver\"> <div class=\"corner TL\"></div> <div class=\"corner TR\"></div><div class=\"corner BL\"></div><div class=\"corner BR\"></div> <div class=\"inner\">");
        out.println("<div id=\"content\">");

        Calendar cal = Calendar.getInstance();
        out.println("<br/><br/><br/><h1>AOL AUTOMATION TEST REPORT</h1>");
        out.println("<br/><div align=\"right\">Report generated on: " + cal.getTime() + "</div><br/><br/>");

        out.flush();
    }

    /** Finishes HTML Stream */
    private static void endHtmlPage(PrintWriter out) {

        out.println("<font color=\"#B2ADAD\">");
        out.println("<br/><h4>Legend:</h4>");
        out.print("<ul>");
        out.println("<li><b>Fail</b>: possible product issue(s)</li>");
        out.println("<li><b>Warn</b>: possible known bugs or non-product issue(s)</li>");
        out.println("<li><b>Skip</b>: ignorable enviromnet issue(s) </li>");
        out.println("<li><b>Combination</b>: Browser(Test) Combinations</li>");
        out.print("</ul>");
        out.println("</font>");
        out.println("</div></div></div></div>");
        out.println("<div class=\"footer\"> &copy; <a href=\"http://www.aol.com\">2015 AOL Inc.</a></div>");
        out.println("</body></html>");
        out.flush();
    }

    /** Starts emailable HTML Stream */

    private void e_startHtmlPage(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>AOL Automation Test Results Summary</title>");

        out.println("<style type=\"text/css\">");
        out.println(
                "body { margin-left:2cm; margin-right:2cm; background: white; color: #333300 ; font-size: 100%; font-family: Georgia, \"Times New Roman\", Times, serif; }");
        out.println(
                "table.details{ margin-bottom:10px;border:0px solid white;border-collapse:collapse;empty-cells:hide;width=\"40%\"; }");
        out.println(
                "table.details td { border:0px solid white; color: #333300;font-family:Georgia, \"Times New Roman\", Times, serif; font-size: 100%; text-align: left; }");
        out.println(
                "table.param td { border:1px solid #333300; color: #333300 ;font-family:Georgia, \"Times New Roman\", Times, serif; font-size: 100%; text-align: center; }");
        out.println("table.param tr{ height: 35px;}");
        out.println(
                "table.param th { border:0px solid #333300; color: white;font-family:Georgia, \"Times New Roman\", Times, serif; font-size: 100%; text-align: center; background-color: #333300; }");
        out.println("table.param tr:nth-of-type(odd){background: #F0F0F0;}");
        out.println("table.param tr:nth-of-type(even){background: #B4B4B4 ;}");
        out.println("table.param tr:hover{ background-color: #79830D;}");
        out.println("table.details tr:hover{background-color: #9AEBA5;}");
        out.println("#content {margin-left:1.5cm; margin-right:1.5cm;margin-top:1.5; margin-bottom:1.5cm}");
        out.println("</style>");

        out.println("</head>");
        out.println("<body>");
        // out.println("<div id=\"content\">");
        Calendar cal = Calendar.getInstance();
        out.println("<br/><h1>AOL AUTOMATION TEST REPORT</h1>");
        out.println("<br/><div align=\"right\">Report generated on: " + cal.getTime() + "</div><br/><br/>");

        out.flush();
    }

    private String getTestTag(Object[] params) {
        int indexOfTag = 0;
        String testTag = "You should add a description to your test method";
        if (params.length < indexOfTag + 1)
            return testTag;
        testTag = params[indexOfTag].toString().trim();

        if (testTag.length() > 80) {
            testTag = testTag.substring(0, 79) + "...";
        }
        return testTag;
    }

    private String getTestPara(Object[] params) {
        return getTestPara(params, 1);
    }

    private String getTestPara(Object[] params, int indexOfPara) {
        String testPara = "";
        if (params.length < indexOfPara + 1)
            return testPara;
        testPara = params[indexOfPara].toString().trim();
        for (int i = indexOfPara + 1; i < params.length; i++) {
            testPara += ", " + params[i].toString().trim();
        }
        if (testPara.length() > 80) {
            testPara = testPara.substring(0, 79) + "...";
        }
        return testPara;
    }

    public String getPercentage(NumberFormat nf, float num, float total) {

        String percentage = "0";
        if (total < 1)
            return percentage;
        try {
            percentage = nf.format((num / total) * 100);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return percentage;
    }

    // TODO
    // Seems testng listener failed to update actually status for tests, we are trying to provided a workaround    
    synchronized public static Set<ITestResult> setTestStatus(Set<ITestResult> testResultSet, int status) {
        try {//TBD, use array 
            Object[] trs = testResultSet.toArray();
            for (Object tro : trs) {
                ITestResult tr = (ITestResult) tro;
                int cStatus = tr.getStatus();
                if (cStatus != status) {
                    testResultSet.remove(tr);
                    tr.setStatus(status);
                    testResultSet.add(tr);
                }
            }

            //        for(ITestResult tr: testResultSet){
            //            int cStatus = tr.getStatus();
            //            if(cStatus!=status){
            //                boolean done = false;
            //                int num = 0, maxTime = 3;
            //                Exception ex = null;
            //               do{
            //                   try{
            //                    testResultSet.remove(tr);
            //                    tr.setStatus(status);
            //                    testResultSet.add(tr);  
            //                    done = true;
            //                   }catch(ConcurrentModificationException e){
            //                       ex = e;
            //                       TestHelper.threadSleep(1000);
            //                   }catch(Exception e){
            //                      ex = e;
            //                      num = maxTime;
            //                   }
            //               }while(!done&&++num<maxTime);
            //               
            //               if(!done){
            //                   ex.printStackTrace();
            //               }
            //            }
            //                      
            //           // System.out.println(cStatus +" - " +(cStatus = tr.getStatus()));
            //        }
        } catch (Exception e) {
            System.out.println("Failed to resetTestStatus: " + e);
        }

        return testResultSet;
    }

    /** Finishes emailable HTML Stream */
    private void e_endHtmlPage(PrintWriter out) {
        out.println("<font color=\"#B2ADAD\">");
        out.println("<br/><h4>Legend:</h4>");
        out.print("<ul>");
        out.println("<li><b>Fail</b>: possible product issue(s)</li>");
        out.println("<li><b>Warn</b>: possible known bugs or non-product issue(s)</li>");
        out.println("<li><b>Skip</b>: ignorable enviromnet issue(s) </li>");
        out.println("<li><b>Combination</b>: Browser(Test) Combinations</li>");
        out.print("</ul>");
        out.print("</font>");
        out.println("</body></html>");
        out.flush();
    }
}