public static void main(String args[]) {
   try {
     SeleniumHtmlClient client = new SeleniumHtmlClient();
     String testFile = null;
     String testSuite = null;
     String resultsFilename = null;
     for (int i = 0; i < args.length; i++) {
       if (args[i].equals("--host")) {
         i++;
         if (i < args.length) {
           client.setHost(args[i]);
         } else {
           throw new BadUsageException("--host must be followed by a hostname");
         }
       } else if (args[i].equals("--port")) {
         i++;
         if (i < args.length) {
           client.setPort(Integer.parseInt(args[i]));
         } else {
           throw new BadUsageException("--port must be followed by a port number");
         }
       } else if (args[i].equals("--browser")) {
         i++;
         if (i < args.length) {
           client.setBrowser(args[i]);
         } else {
           throw new BadUsageException("--browser must be followed by a browser spec");
         }
       } else if (args[i].equals("--out")) {
         i++;
         if (i < args.length) {
           resultsFilename = args[i];
         } else {
           throw new BadUsageException("--out must be followed by a filename");
         }
         /*
         } else if (args[i].equals("--outdir")) {
         	i++;
         	if (i < args.length) {
         		client.setResultsDir(new File(args[i]));
         	} else {
         		throw new BadUsageException("--outdir must be followed by a path");
         	}
         	*/
       } else if (args[i].equals("--baseurl")) {
         i++;
         if (i < args.length) {
           client.setBaseUrl(args[i]);
         } else {
           throw new BadUsageException("--baseurl must be followed by a URL");
         }
       } else if (args[i].equals("--test")) {
         i++;
         if (i < args.length) {
           if (testFile == null) {
             testFile = args[i];
           } else {
             throw new BadUsageException("only one test file permitted");
           }
         } else {
           throw new BadUsageException("--test must be followed by a test filepath");
         }
       } else if (args[i].equals("--testsuite")) {
         i++;
         if (i < args.length) {
           testSuite = args[i];
         } else {
           throw new BadUsageException("--testsuite must be followed by a testsuite filepath");
         }
       } else if (args[i].equals("--verbose") || args[i].equals("-v")) {
         client.setVerbose(true);
       } else if (args[i].equals("--help") || args[i].equals("-h")) {
         printUsage();
         System.exit(0);
       } else {
         throw new BadUsageException("Unknown parameter " + args[i]);
       }
     }
     if (testFile == null && testSuite == null) {
       throw new BadUsageException("No test or testsuite file specified");
     } else if (testFile != null && testSuite != null) {
       throw new BadUsageException("A test and testsuite file cannot both be specified");
     }
     Writer resultsWriter = null;
     if (resultsFilename != null) {
       resultsWriter = new FileWriter(resultsFilename);
     } else /* if (client.resultsDir == null) */ {
       resultsWriter = new OutputStreamWriter(System.out);
     }
     client.setResultsWriter(resultsWriter);
     if (testFile != null) {
       client.runTest(testFile);
     } else {
       client.runSuite(testSuite);
     }
     if (resultsWriter != null) resultsWriter.close();
   } catch (BadUsageException e) {
     System.err.println("Error: " + e.getMessage());
     System.err.println();
     printUsage();
     System.exit(1);
   } catch (Exception e) {
     e.printStackTrace();
     System.exit(1);
   }
 }
  public boolean runSuite(String filename) throws Exception {
    if (this.verbose) {
      System.out.println(
          "Running test suite "
              + filename
              + " against "
              + this.host
              + ":"
              + this.port
              + " with "
              + this.browser);
    }
    TestSuite suite = new TestSuite();
    long start = System.currentTimeMillis();
    suite.numTestPasses = 0;
    suite.file = new File(filename);
    File suiteDirectory = suite.file.getParentFile();
    this.document = parseDocument(filename);
    Element table = (Element) this.document.getElementsByTagName("table").item(0);
    NodeList tableRows = table.getElementsByTagName("tr");
    Element tableNameRow = (Element) tableRows.item(0);
    suite.name = tableNameRow.getTextContent();
    suite.result = true;
    suite.tests = new Test[tableRows.getLength() - 1];
    for (int i = 1; i < tableRows.getLength(); i++) {
      Element tableRow = (Element) tableRows.item(i);
      Element cell = (Element) tableRow.getElementsByTagName("td").item(0);
      Element link = (Element) cell.getElementsByTagName("a").item(0);
      Test test = new Test();
      test.label = link.getTextContent();
      test.file = new File(suiteDirectory, link.getAttribute("href"));

      SeleniumHtmlClient subclient = new SeleniumHtmlClient();
      subclient.setHost(this.host);
      subclient.setPort(this.port);
      subclient.setBrowser(this.browser);
      // subclient.setResultsWriter(this.resultsWriter);
      subclient.setBaseUrl(this.baseUrl);
      subclient.setVerbose(this.verbose);
      subclient.runTest(test);
      if (test.result) {
        suite.numTestPasses++;
      }
      suite.result &= test.result;
      suite.tests[i - 1] = test;
    }
    long end = System.currentTimeMillis();

    suite.totalTime = (end - start) / 1000;

    if (this.resultsWriter != null) {
      this.resultsWriter.write("<html><head>\n");
      this.resultsWriter.write("<style type='text/css'>\n");
      this.resultsWriter.write(
          "body, table {font-family: Verdana, Arial, sans-serif;font-size: 12;}\n");
      this.resultsWriter.write("table {border-collapse: collapse;border: 1px solid #ccc;}\n");
      this.resultsWriter.write("th, td {padding-left: 0.3em;padding-right: 0.3em;}\n");
      this.resultsWriter.write("a {text-decoration: none;}\n");
      this.resultsWriter.write(".title {font-style: italic;}");
      this.resultsWriter.write(".selected {background-color: #ffffcc;}\n");
      this.resultsWriter.write(".status_done {background-color: #eeffee;}\n");
      this.resultsWriter.write(".status_passed {background-color: #ccffcc;}\n");
      this.resultsWriter.write(".status_failed {background-color: #ffcccc;}\n");
      this.resultsWriter.write(
          ".breakpoint {background-color: #cccccc;border: 1px solid black;}\n");
      this.resultsWriter.write("</style>\n");
      this.resultsWriter.write("<title>" + suite.name + "</title>\n");
      this.resultsWriter.write("</head><body>\n");
      this.resultsWriter.write("<h1>Test suite results </h1>\n\n");
      this.resultsWriter.write("<table>\n");
      this.resultsWriter.write(
          "<tr>\n<td>result:</td>\n<td>" + (suite.result ? "passed" : "failed") + "</td>\n</tr>\n");
      this.resultsWriter.write(
          "<tr>\n<td>totalTime:</td>\n<td>" + suite.totalTime + "</td>\n</tr>\n");
      this.resultsWriter.write(
          "<tr>\n<td>numTestTotal:</td>\n<td>" + suite.tests.length + "</td>\n</tr>\n");
      this.resultsWriter.write(
          "<tr>\n<td>numTestPasses:</td>\n<td>" + suite.numTestPasses + "</td>\n</tr>\n");
      int numTestFailures = suite.tests.length - suite.numTestPasses;
      this.resultsWriter.write(
          "<tr>\n<td>numTestFailures:</td>\n<td>" + numTestFailures + "</td>\n</tr>\n");
      this.resultsWriter.write("<tr>\n<td>numCommandPasses:</td>\n<td>0</td>\n</tr>\n");
      this.resultsWriter.write("<tr>\n<td>numCommandFailures:</td>\n<td>0</td>\n</tr>\n");
      this.resultsWriter.write("<tr>\n<td>numCommandErrors:</td>\n<td>0</td>\n</tr>\n");
      this.resultsWriter.write("<tr>\n<td>Selenium Version:</td>\n<td>2.24</td>\n</tr>\n");
      this.resultsWriter.write("<tr>\n<td>Selenium Revision:</td>\n<td>.1</td>\n</tr>\n");

      // test suite
      this.resultsWriter.write("<tr>\n<td>\n");
      this.resultsWriter.write(
          "<table id=\"suiteTable\" class=\"selenium\" border=\"1\" cellpadding=\"1\" cellspacing=\"1\"><tbody>\n");
      this.resultsWriter.write(
          "<tr class=\"title "
              + (suite.result ? "status_passed" : "status_failed")
              + "\"><td><b>Test Suite</b></td></tr>\n");

      int i = 0;
      for (Test test : suite.tests) {
        this.resultsWriter.write(
            "<tr class=\""
                + (test.result ? "status_passed" : "status_failed")
                + "\"><td><a href=\"#testresult"
                + i
                + "\">"
                + test.name
                + "</a></td></tr>");
        i++;
      }
      this.resultsWriter.write(
          "</tbody></table>\n</td>\n<td>&nbsp;</td>\n</tr>\n</table>\n<table>");
      int j = 0;
      for (Test test : suite.tests) {
        this.resultsWriter.write(
            "<tr><td><a name=\"testresult" + j + "\">" + test.file + "</a><br/><div>\n");
        this.resultsWriter.write("<table border=\"1\" cellpadding=\"1\" cellspacing=\"1\">\n");
        this.resultsWriter.write(
            "<thead>\n<tr class=\"title "
                + (test.result ? "status_passed" : "status_failed")
                + "\"><td rowspan=\"1\" colspan=\"3\">"
                + test.name
                + "</td></tr>");
        this.resultsWriter.write("</thead><tbody>\n");
        for (Command command : test.commands) {
          boolean result = command.result.startsWith("OK");
          boolean isAssert = command.cmd.startsWith("assert") || command.cmd.startsWith("verify");
          ;
          if (!isAssert) {
            this.resultsWriter.write(
                "<tr class=\"" + (result ? "status_done" : "") + "\">\n<td>\n");
          } else {
            this.resultsWriter.write(
                "<tr class=\"" + (result ? "status_passed" : "status_failed") + "\">\n<td>\n");
          }
          this.resultsWriter.write(command.cmd);
          this.resultsWriter.write("</td>\n");
          if (command.args != null) {
            for (String arg : Arrays.asList(command.args)) {
              this.resultsWriter.write("<td>" + arg + "</td>\n");
            }
          }
        }
        this.resultsWriter.write("</tr>\n");
        this.resultsWriter.write("</tbody></table>\n");
        this.resultsWriter.write("</div></td>\n<td>&nbsp;</td>\n</tr>");

        j++;
      }

      int k = 0;
      for (Test test : suite.tests) {

        k++;
      }

      this.resultsWriter.write("</tbody></table>\n</td><td>&nbsp;</td>\n</tr>\n</table>\n");
      this.resultsWriter.write("</body></html>");
    }
    return suite.result;
  }