001package org.w3.ldp.testsuite.reporter; 002 003import static org.rendersnake.HtmlAttributesFactory.NO_ESCAPE; 004import static org.rendersnake.HtmlAttributesFactory.class_; 005import static org.rendersnake.HtmlAttributesFactory.href; 006import static org.rendersnake.HtmlAttributesFactory.id; 007import static org.rendersnake.HtmlAttributesFactory.style; 008 009import java.io.BufferedWriter; 010import java.io.File; 011import java.io.FileWriter; 012import java.io.IOException; 013import java.io.StringWriter; 014import java.lang.reflect.Method; 015import java.util.ArrayList; 016import java.util.Arrays; 017import java.util.Date; 018import java.util.HashMap; 019import java.util.Iterator; 020import java.util.List; 021import java.util.Map; 022import java.util.Set; 023 024import org.rendersnake.HtmlCanvas; 025import org.rendersnake.StringResource; 026import org.testng.IReporter; 027import org.testng.IResultMap; 028import org.testng.ISuite; 029import org.testng.ISuiteResult; 030import org.testng.ITestContext; 031import org.testng.ITestNGMethod; 032import org.testng.ITestResult; 033import org.testng.annotations.Test; 034import org.testng.internal.Utils; 035import org.testng.xml.XmlSuite; 036import org.w3.ldp.testsuite.BuildProperties; 037import org.w3.ldp.testsuite.LdpTestSuite; 038import org.w3.ldp.testsuite.annotations.SpecTest; 039import org.w3.ldp.testsuite.annotations.SpecTest.METHOD; 040import org.w3.ldp.testsuite.annotations.SpecTest.STATUS; 041 042/** 043 * HTML reporter for the LDP test suite. Takes the results of the test methods 044 * and displays the information to the user. 045 */ 046public class LdpHtmlReporter implements IReporter { 047 048 private int passed = 0; 049 private int failed = 0; 050 private int skipped = 0; 051 private int mustPass = 0; 052 private int mayPass = 0; 053 private int shouldPass = 0; 054 055 private int total; 056 057 private int mustSkip = 0; 058 private int shouldSkip = 0; 059 private int maySkip = 0; 060 061 private int mustFailed = 0; 062 private int shouldFailed; 063 private int mayFailed; 064 065 private IResultMap passedTests; 066 private IResultMap failedTests; 067 private IResultMap skippedTests; 068 069 HashMap<String, Integer> passClasses; 070 HashMap<String, Integer> failClasses; 071 HashMap<String, Integer> skipClasses; 072 073 private HtmlCanvas html; 074 075 private String outputName = "ldp-testsuite"; 076 077 private static final String PASS = "Passed"; 078 private static final String FAIL = "Failed"; 079 private static final String SKIP = "Skipped"; 080 081 private List<ITestNGMethod> indirect = new ArrayList<ITestNGMethod>(); 082 083 private static StringWriter graphs = new StringWriter(); 084 085 private static ArrayList<String> colors = new ArrayList<String>(Arrays.asList("#42d992", "#1cbfbb", "#1d0b4e", "#bf1c56")); 086 087 private String outputDirectory = LdpTestSuite.OUTPUT_DIR; 088 089 public void setOutputDirectory(String outputDirectory) { 090 this.outputDirectory = outputDirectory; 091 } 092 093 public void generateReport(List<XmlSuite> xmlSuites, List<ISuite> suites, String outputDirectory) { 094 try { 095 for (ISuite suite : suites) { 096 html = new HtmlCanvas(); 097 html.html().head(); 098 099 writeCss(); 100 html.title().content(LdpTestSuite.NAME + " Report")._head() 101 .body(); 102 html.h1().content(LdpTestSuite.NAME + " Summary"); 103 104 // Getting the results for the said suite 105 Map<String, ISuiteResult> suiteResults = suite.getResults(); 106 107 for (ISuiteResult sr : suiteResults.values()) { 108 109 ITestContext tc = sr.getTestContext(); 110 passedTests = tc.getPassedTests(); 111 failedTests = tc.getFailedTests(); 112 skippedTests = tc.getSkippedTests(); 113 } 114 115 // Initialize variables for charts 116 passClasses = getClasses(passedTests); 117 failClasses = getClasses(failedTests); 118 skipClasses = getClasses(skippedTests); 119 120 html.h2().content("Overall Coverage Bar Charts"); 121 122 html.span(class_("chartStart")); 123 html.label(class_("label")).b().write("Test Results by Specification Requirement")._b()._label(); 124 html.div(class_("barChart").id("overallChart1"))._div(); // svg chart 125 writePassFailLegend(); 126 127 html._span(); 128 129 html.span(class_("chartStart")); 130 html.label(class_("label")).b().write("Test Results by Test Class")._b()._label(); 131 html.div(class_("barChart").id("resourcesChart"))._div(); 132 writeTestClassLegend(); 133 html._span(); 134 135 html.br(); 136 generateOverallSummaryReport(suites, "summary"); 137 displayGroupsInfo(suites); 138 displayMethodsSummary(suites); 139 toTop(); 140 generateMethodDetails(suites); 141 142 html.script().content( 143 StringResource.get("/raphael/raphael-min.js"), NO_ESCAPE); 144 html.script().content( 145 StringResource.get("/prototype/prototype.js"), NO_ESCAPE); 146 html.script().content( 147 StringResource.get("/grafico/grafico-min.js"), NO_ESCAPE); 148 149 writeOverallBarChart(); 150 writeResourcesBarChart(); 151 152 html.write(graphs.toString(), NO_ESCAPE); 153 html._body()._html(); 154 155 // send html to a file 156 createWriter(this.outputDirectory, html.toHtml(), outputName); 157 } 158 } catch (IOException e) { 159 e.printStackTrace(); 160 } 161 } 162 163 public void setTitle(String title) { 164 this.outputName = title; 165 } 166 167 private void writeCss() throws IOException { 168 169 html.style().write(StringResource.get("reportStyle.css"), NO_ESCAPE) 170 ._style(); 171 } 172 173 private void createWriter(String directory, String output, String title) { 174 BufferedWriter writer = null; 175 new File(directory).mkdirs(); 176 try { 177 writer = new BufferedWriter(new FileWriter(directory 178 + "/" + title + "-execution-report.html")); 179 writer.write(output); 180 181 } catch (IOException e) { 182 } finally { 183 try { 184 if (writer != null) 185 writer.close(); 186 } catch (IOException e) { 187 } 188 } 189 } 190 191 private void generateOverallSummaryReport(List<ISuite> suites, String id) 192 throws IOException { 193 html.table(class_("summary")); 194 Date date = new Date(); 195 for (ISuite suite : suites) { 196 // Getting the results for the said suite 197 Map<String, ISuiteResult> suiteResults = suite.getResults(); 198 199 for (ISuiteResult sr : suiteResults.values()) { 200 201 ITestContext tc = sr.getTestContext(); 202 203 Iterator<ITestResult> passedResults = tc.getPassedTests() 204 .getAllResults().iterator(); 205 while (passedResults.hasNext()) { 206 ITestResult result = passedResults.next(); 207 208 try { 209 Method m = result.getMethod().getConstructorOrMethod() 210 .getMethod(); 211 String[] groups = m.getAnnotation(Test.class).groups(); 212 for (int i = 0; i < groups.length; i++) { 213 if (groups[i].equals("MUST")) 214 mustPass++; 215 if (groups[i].equals("MAY")) 216 mayPass++; 217 if (groups[i].equals("SHOULD")) 218 shouldPass++; 219 220 } 221 } catch (SecurityException e) { 222 e.printStackTrace(); 223 } 224 225 } 226 Iterator<ITestResult> failedResults = tc.getFailedTests() 227 .getAllResults().iterator(); 228 while (failedResults.hasNext()) { 229 ITestResult result = failedResults.next(); 230 231 try { 232 Method m = result.getMethod().getConstructorOrMethod() 233 .getMethod(); 234 String[] groups = m.getAnnotation(Test.class).groups(); 235 for (int i = 0; i < groups.length; i++) { 236 if (groups[i].equals("MUST")) 237 mustFailed++; 238 if (groups[i].equals("SHOULD")) 239 shouldFailed++; 240 if (groups[i].equals("MAY")) 241 mayFailed++; 242 } 243 } catch (SecurityException e) { 244 e.printStackTrace(); 245 } 246 247 } 248 Iterator<ITestResult> skippedResults = tc.getSkippedTests() 249 .getAllResults().iterator(); 250 while (skippedResults.hasNext()) { 251 ITestResult result = skippedResults.next(); 252 253 try { 254 Method m = result.getMethod().getConstructorOrMethod() 255 .getMethod(); 256 String[] groups = m.getAnnotation(Test.class).groups(); 257 for (int i = 0; i < groups.length; i++) { 258 if (groups[i].equals("MUST")) 259 mustSkip++; 260 if (groups[i].equals("MAY")) 261 maySkip++; 262 if (groups[i].equals("SHOULD")) 263 shouldSkip++; 264 265 } 266 } catch (SecurityException e) { 267 e.printStackTrace(); 268 } 269 270 } 271 passed = tc.getPassedTests().getAllResults().size(); 272 failed = tc.getFailedTests().getAllResults().size(); 273 skipped = tc.getSkippedTests().getAllResults().size(); 274 } 275 total = passed + failed + skipped; 276 generateSummaryTableStart(date, suite.getName()); 277 generateSummaryTable(); 278 html._table(); 279 } 280 281 } 282 283 private void generateSummaryTableStart(Date date, String suiteName) 284 throws IOException { 285 html.tr().th().content("Test Suite Name"); 286 html.th().content("Revision"); 287 html.th().content("Report Date"); 288 html.th().content("Skipped Tests"); 289 html.th().content("MUST Requirements"); 290 html.th().content("SHOULD Requirements"); 291 html.th().content("MAY Requirements"); 292 html._tr(); 293 294 html.tr(class_("alt")).td().content(suiteName); 295 final String commit = BuildProperties.getRevision(); 296 if (commit == null) { 297 html.td().content("<UNKNOWN>"); 298 } else { 299 html.td().a(href("https://github.com/w3c/ldp-testsuite/commit/" + commit)).content(commit)._td(); 300 } 301 html.td().content(date.toString()); 302 } 303 304 private void generateSummaryTable() 305 throws IOException { 306 printSkipCellResult(); 307 printReqCellResult(mustPass, mustFailed, mustSkip); 308 printReqCellResult(shouldPass, shouldFailed, shouldSkip); 309 printReqCellResult(mayPass, mayFailed, maySkip); 310 html._tr(); 311 } 312 313 private void printSkipCellResult() throws IOException { 314 if (skipped == 0) 315 html.td().i().write("No tests of this type called")._i()._td(); 316 else { 317 html.td(); 318 html.write("("); 319 html.b().write(skipped + "/" + total)._b(); 320 html.write(") "); 321 html.write("of the total tests.")._td(); 322 } 323 324 } 325 326 private void printReqCellResult(int passed, int failed, int skipped) throws IOException { 327 int total = passed + failed + skipped; 328 329 html.td().b().write(passed + "/" + total)._b(); 330 html.write(" Passed"); 331 332 html.br().b().write(failed + "/" + total)._b(); 333 html.write(" Failed"); 334 335 html.br().b().write(skipped + "/" + total)._b(); 336 html.write(" Skipped"); 337 html._td(); 338 339 } 340 341 private void displayGroupsInfo(List<ISuite> suite) throws IOException { 342 for (ISuite testSuite : suite) { 343 Map<String, ISuiteResult> tests = testSuite.getResults(); 344 for (ISuiteResult results : tests.values()) { 345 ITestContext overview = results.getTestContext(); 346 String[] excluded = overview.getExcludedGroups(); 347 String[] included = overview.getIncludedGroups(); 348 generateList(included, 349 "Included Groups for " + testSuite.getName()); 350 generateList(excluded, 351 "Excluded Groups for " + testSuite.getName()); 352 } 353 } 354 } 355 356 private void generateList(String[] list, String title) throws IOException { 357 html.h2().write(title)._h2(); 358 if (list.length == 0) { 359 html.div(style("padding-left:2em")).i() 360 .content("No groups of this type found in the test suite") 361 ._div(); 362 } else { 363 html.ul(); 364 for (String group : list) { 365 html.li().content(group); 366 } 367 html._ul(); 368 } 369 } 370 371 private void displayMethodsSummary(List<ISuite> suites) throws IOException { 372 for (ISuite suite : suites) { 373 Map<String, ISuiteResult> r = suite.getResults(); 374 for (ISuiteResult r2 : r.values()) { 375 ITestContext testContext = r2.getTestContext(); 376 makeMethodsList(testContext); 377 } 378 } 379 } 380 381 private void makeMethodsList(ITestContext testContext) throws IOException { 382 IResultMap failed = testContext.getFailedTests(); 383 IResultMap passed = testContext.getPassedTests(); 384 IResultMap skipped = testContext.getSkippedTests(); 385 386 html.h1(class_("center")).content("Methods called"); 387 html.a(href("#Skipped")).write("Go To Skipped Tests").br()._a(); 388 html.a(href("#Passed")).write("Go To Passed Tests").br()._a(); 389 html.a(href("#Indirect")).write("Go To Indirect Tests").br()._a(); 390 html.br(); 391 392 makeMethodSummaryTable(failed, "Failed"); 393 html.br(); 394 toTop(); 395 html.br(); 396 makeMethodSummaryTable(skipped, "Skipped"); 397 html.br(); 398 toTop(); 399 html.br(); 400 makeMethodSummaryTable(passed, "Passed"); 401 html.br(); 402 toTop(); 403 makeIndirectSummaryTable(); 404 html.br(); 405 406 } 407 408 private void makeMethodSummaryTable(IResultMap tests, String title) 409 throws IOException { 410 html.table(class_("indented")); 411 html.tr().th(class_(title)).a(id((title))).write(title + " Test Cases")._a()._th(); 412 html.th(class_(title)).content("Groups"); 413 html.th(class_(title)).content("Description of Test Method")._tr(); 414 for (ITestResult result : tests.getAllResults()) { 415 ITestNGMethod method = result.getMethod(); 416 if(method.getConstructorOrMethod().getMethod().getAnnotation(SpecTest.class).testMethod().equals(METHOD.INDIRECT)){ 417 // do nothing, will add this in a separate table that specifically defines indirect tests 418 indirect.add(method); 419 420 } else { 421 List<String> groups = Arrays.asList(method.getGroups()); 422 if (groups.contains("MUST") && result.getStatus() == ITestResult.FAILURE) { 423 html.tr(class_("critical")); 424 } else { 425 html.tr(); 426 } 427 428 String normalizedName = AbstractEarlReporter.createTestCaseName( 429 method.getTestClass().getName(), method.getMethodName()); 430 html.td() 431 .a(href("#" + method.getTestClass().getName() + "_" 432 + method.getMethodName())) 433 .write(normalizedName)._a(); 434 if (method.getConstructorOrMethod().getMethod().getAnnotation(SpecTest.class).approval() == STATUS.WG_PENDING) { 435 html.br().b().em().write("WG Approval Pending")._em()._b(); 436 } 437 html._td(); 438 html.td().content(Arrays.toString(method.getGroups())); 439 html.td().content( 440 (method.getDescription() != null ? method.getDescription() 441 : "No Description found")); 442 html._tr(); 443 } 444 } 445 html._table(); 446 } 447 448 private void makeIndirectSummaryTable() throws IOException { 449 html.table(class_("indented")); 450 html.tr().th().a(id(("Indirect"))).write("Indirectly Tested Test Cases")._a()._th(); 451 html.th().content("Overall Test Result"); 452 html.th().content("Description of Test Method")._tr(); 453 454 for(ITestNGMethod method : indirect){ 455 html.tr(); 456 String normalizedName = AbstractEarlReporter.createTestCaseName( 457 method.getTestClass().getName(), method.getMethodName()); 458 html.td() 459 .a(href("#" + method.getTestClass().getName() + "_" 460 + method.getMethodName())).write(normalizedName)._a()._td(); 461 ArrayList<String> result = new ArrayList<String>(); 462 Method m = method.getConstructorOrMethod().getMethod(); 463 SpecTest spec = m.getAnnotation(SpecTest.class); 464 for(Class<?> className : spec.coveredByTests()){ 465 Method[] classMethod = className.getDeclaredMethods(); 466 for(Method methodName : classMethod) { 467 if(methodName.getAnnotation(Test.class) != null) { 468 String group = Arrays.toString(methodName.getAnnotation(Test.class).groups()); 469 for(String groupCover : spec.coveredByGroups()) { 470 if(group.contains(groupCover) && !methodName.getName().contains("Conforms")) { 471 result.add(findTestResult(methodName.getName())); 472 } 473 } 474 } 475 } 476 } 477 // evaluate the testResults for the Indirect Test 478 // if one of the tests fails, then the entire indirect test fails 479 // if there are only pass and skipped tests (none failed), then it passes 480 // if there are only skipped (none passed or failed), then it is skipped 481 if(result.size() > 0){ 482 if(result.contains(FAIL)) 483 html.td(class_("Failed")).content(FAIL); 484 else if(result.contains(PASS) && !result.contains(FAIL)) 485 html.td(class_("Passed")).content(PASS); 486 else if(result.contains(SKIP) && !result.contains(FAIL) && !result.contains(PASS)) 487 html.td(class_("Skipped")).content(SKIP); 488 } 489 html.td().content( 490 (method.getDescription() != null ? method.getDescription() 491 : "No Description found")); 492 html._tr(); 493 } 494 495 html._table(); 496 } 497 498 private void generateMethodDetails(List<ISuite> suites) throws IOException { 499 html.h1().content("Test Method Details"); 500 for (ISuite suite : suites) { 501 Map<String, ISuiteResult> r = suite.getResults(); 502 for (ISuiteResult r2 : r.values()) { 503 ITestContext testContext = r2.getTestContext(); 504 505 generateDetail(testContext.getFailedTests()); 506 generateDetail(testContext.getSkippedTests()); 507 generateDetail(testContext.getPassedTests()); 508 } 509 } 510 } 511 512 private void generateDetail(IResultMap tests) throws IOException { 513 for (ITestResult m : tests.getAllResults()) { 514 ITestNGMethod method = m.getMethod(); 515 String normalizedName = AbstractEarlReporter.createTestCaseName( 516 m.getTestClass().getName(), method.getMethodName()); 517 html.h2() 518 .a(id(m.getTestClass().getName() + "_" 519 + method.getMethodName())) 520 .write(normalizedName)._a()._h2(); 521 getAdditionalInfo(m, method); 522 html.p(class_("indented")) 523 .b() 524 .write("Description: ") 525 ._b() 526 .write((method.getDescription() != null ? method 527 .getDescription() 528 : "No description for this test method found")) 529 ._p(); 530 String groups = ""; 531 for (String group : method.getGroups()) { 532 groups += group + " "; 533 } 534 html.p(class_("indented")).b().write("Requirement Level: ")._b() 535 .write(groups)._p(); 536 537 toTop(); 538 539 } 540 541 } 542 543 private void getAdditionalInfo(ITestResult m, ITestNGMethod method) 544 throws IOException { 545 if (m.getThrowable() != null) { 546 Throwable thrown = m.getThrowable(); 547 String exception = thrown.getClass().getName(); 548 if (exception.contains("Skip")) { 549 createSkipExceptionTable(thrown); 550 } else { 551 createThrownTable(thrown); 552 } 553 } 554 555 if (m.getParameters() != null && m.getParameters().length != 0) { 556 Object[] params = m.getParameters(); 557 String parameters = ""; 558 for (Object p : params) { 559 if (p != null) 560 parameters += p.toString() + " "; 561 } 562 html.p(class_("indented")).b().write("Parameters: ")._b() 563 .write(parameters)._p(); 564 } 565 566 if (m.getMethod().getConstructorOrMethod().getMethod() 567 .getAnnotation(SpecTest.class) != null) { 568 SpecTest testLdp = m.getMethod().getConstructorOrMethod().getMethod() 569 .getAnnotation(SpecTest.class); 570 if(!testLdp.comment().equals("")) 571 html.p(class_("note")).b().write("NOTE: ")._b() 572 .write(testLdp.comment())._p(); 573 if(testLdp.steps().length != 0) 574 writeSteps(testLdp.steps(), m.getName()); 575 if(testLdp.coveredByTests().length > 0 && testLdp.coveredByGroups().length > 0){ 576 html.p().b().content("Test Case is covered Indirectly by the following:")._p(); 577 html.ul(); 578 for(Class<?> className : testLdp.coveredByTests()){ 579 Method[] classMethod = className.getDeclaredMethods(); 580 for(Method methodName : classMethod) { 581 if(methodName.getAnnotation(Test.class) != null) { 582 String group = Arrays.toString(methodName.getAnnotation(Test.class).groups()); 583 for(String groupCover : testLdp.coveredByGroups()) { 584 if(group.contains(groupCover) && !methodName.getName().contains("Conforms")) { 585 String testCaseName = methodName.getDeclaringClass().getSimpleName(); 586 String normalizedName = AbstractEarlReporter.createTestCaseName(testCaseName, methodName.getName()); 587 html.li().b().write(normalizedName)._b(); 588 html.write(" - [Test " + findTestResult(methodName.getName()) + "]"); 589 html._li(); 590 } 591 } 592 } 593 } 594 } 595 html._ul(); 596 } 597 html.p(class_("indented")).b().write("Reference URI: ")._b() 598 .a(href(testLdp.specRefUri())).write(testLdp.specRefUri())._a()._p(); 599 } 600 601 } 602 603 private String findTestResult(String methodName) { 604 Iterator<ITestNGMethod> passed = passedTests.getAllMethods().iterator(); 605 while(passed.hasNext()){ 606 ITestNGMethod method = passed.next(); 607 if(method.getMethodName().equals(methodName)){ 608 return PASS; 609 } 610 } 611 612 Iterator<ITestNGMethod> skipped = skippedTests.getAllMethods().iterator(); 613 while(skipped.hasNext()){ 614 ITestNGMethod method = skipped.next(); 615 if(method.getMethodName().equals(methodName)){ 616 return SKIP; 617 } 618 } 619 620 Iterator<ITestNGMethod> failed = failedTests.getAllMethods().iterator(); 621 while(failed.hasNext()){ 622 ITestNGMethod method = failed.next(); 623 if(method.getMethodName().equals(methodName)){ 624 return FAIL; 625 } 626 } 627 628 return null; 629 630 } 631 632 private void writeSteps(String[] steps, String title) throws IOException { 633 html.p().content("How to Run " + title); 634 html.ul(); 635 for(String step : steps) 636 html.li().content(step); 637 html._ul(); 638 } 639 640 private void createSkipExceptionTable(Throwable thrown) throws IOException { 641 html.table(class_("indented")); 642 html.tr(class_("center")).th(class_("Skipped")) 643 .content("[SKIPPED TEST]")._tr(); 644 html.tr().td().content(thrown.getMessage())._tr(); 645 html._table(); 646 647 } 648 649 private void createThrownTable(Throwable thrown) throws IOException { 650 html.table(class_("indented")); 651 html.tr(class_("center")).th(class_("Failed")).content("[FAILED TEST]") 652 ._tr(); 653 html.tr().td(class_("throw")).content(Utils.stackTrace(thrown, false)[0])._tr(); 654 655 html._table(); 656 657 } 658 659 private void toTop() throws IOException { 660 html.p(class_("totop")).a(href("#top")).content("Back to Top")._p(); 661 } 662 private void writeOverallBarChart() throws IOException { 663 graphs.write("<script>"); 664 graphs.write("Event.observe(window, 'load', function() {"); 665 graphs.write("var summary_bar = new Grafico.StackedBarGraph($('overallChart1'),"); 666 graphs.write("{ passed: [ " + mustPass + ", " + shouldPass + ", " 667 + mayPass + " ],"); 668 graphs.write("failed: [" + mustFailed + ", " + shouldFailed + ", " 669 + mayFailed + " ], "); 670 graphs.write("skipped: [" + mustSkip + ", " + shouldSkip + ", " + maySkip + " ]"); 671 graphs.write("},"); 672 graphs.write("{ labels: [ \"MUST\", \"SHOULD\", \"MAY\" ],"); 673 graphs.write("colors: { passed: '#a2bf2f', failed: '#a80000', skipped: '#606060' },"); 674 graphs.write("hover_color: \"#ccccff\","); 675 676 graphs.write("datalabels: { passed: [ \"" + mustPass + " Passed\", \"" 677 + shouldPass + " Passed\", \"" + mayPass + " Passed\"],"); 678 graphs.write("failed: [ \"" + mustFailed + " Failed\" , \"" 679 + shouldFailed + " Failed\" , \"" + mayFailed 680 + " Failed\" ],"); 681 graphs.write("skipped: [ \"" + mustSkip + " Skipped\", \"" + shouldSkip 682 + " Skipped\", \"" + maySkip + " Skipped\" ]"); 683 graphs.write("},"); 684 685 graphs.write("}); });"); 686 graphs.write("</script>"); 687 } 688 689 private void writeResourcesBarChart() throws IOException { 690 691 graphs.write("<script>"); 692 graphs.write("Event.observe(window, 'load', function() {"); 693 graphs.write("var resource_bar = new Grafico.StackedBarGraph($('resourcesChart'),"); 694 writeChartValues(passClasses, failClasses, skipClasses); 695 graphs.write("{ labels: [ \"Passed\", \"Failed\", \"Skipped\" ],"); 696 graphs.write("hover_color: \"#ccccff\","); 697 writeChartColors(passClasses); 698 writeChartLabels(passClasses, failClasses, skipClasses); 699 graphs.write("}); });"); 700 graphs.write("</script>"); 701 } 702 703 private void writePassFailLegend() throws IOException { 704 html.write("<svg id=\"passFailLegend\" width=\"150\" height=\"250\">", NO_ESCAPE); 705 html.write("<rect width=\"15\" height=\"15\" x=\"0\" y=\"0\" style=\"fill:#a2bf2f\"/>", NO_ESCAPE); 706 html.write("<text x=\"20\" y=\"13\" fill=\"black\">Passed Tests</text>", NO_ESCAPE); 707 html.write("<rect width=\"15\" height=\"15\" x=\"0\" y=\"20\" style=\"fill:#a80000\"/>", NO_ESCAPE); 708 html.write("<text x=\"20\" y=\"33\" fill=\"black\">Failed Tests</text>", NO_ESCAPE); 709 html.write("<rect width=\"15\" height=\"15\" x=\"0\" y=\"40\" style=\"fill:#606060\"/>", NO_ESCAPE); 710 html.write("<text x=\"20\" y=\"53\" fill=\"black\">Skipped Tests</text>", NO_ESCAPE); 711 html.write("</svg>"); 712 } 713 714 private void writeTestClassLegend() throws IOException { 715 html.write("<svg id=\"testClassLegend\" width=\"175\" height=\"250\">", NO_ESCAPE); 716 717 Set<String> names = passClasses.keySet(); 718 Iterator<String> label = names.iterator(); 719 int textY = 13; 720 int rectY = 0; 721 int getColor = 0; 722 723 while (label.hasNext() && getColor != colors.size()) { 724 String className = label.next(); 725 html.write("<rect width=\"15\" height=\"15\" x=\"0\" y=\"" + rectY 726 + "\" style=\"fill:" + colors.get(getColor) + "\"/>", 727 NO_ESCAPE); 728 html.write("<text x=\"20\" y=\"" + textY + "\" fill=\"black\">" 729 + className + "</text>", NO_ESCAPE); 730 731 textY += 20; 732 rectY += 20; 733 getColor++; 734 735 } 736 html.write("</svg>"); 737 } 738 739 private void writeChartLabels(HashMap<String, Integer> passClasses, 740 HashMap<String, Integer> failClasses, 741 HashMap<String, Integer> skipClasses) { 742 graphs.write("datalabels: {"); 743 Set<String> names = passClasses.keySet(); 744 Iterator<String> label = names.iterator(); 745 while (label.hasNext()) { 746 String className = label.next(); 747 graphs.write(className + ": [ \"" + passClasses.get(className) 748 + " " + className + "\", \"" + failClasses.get(className) 749 + " " + className + "\", \"" + skipClasses.get(className) 750 + " " + className + "\" ]"); 751 if (label.hasNext()) 752 graphs.write(","); 753 } 754 graphs.write("},"); 755 } 756 757 private void writeChartColors(HashMap<String, Integer> passClasses) { 758 graphs.write("colors: {"); 759 Set<String> names = passClasses.keySet(); 760 Iterator<String> label = names.iterator(); 761 int getColor = 0; 762 while (label.hasNext() && getColor != colors.size()) { 763 String className = label.next(); 764 765 if (label.hasNext()) 766 graphs.write(className + ": '" + colors.get(getColor) + "', "); 767 else 768 graphs.write(className+ ": '" + colors.get(getColor) + "' },"); 769 getColor++; 770 } 771 } 772 773 private void writeChartValues(HashMap<String, Integer> passClasses, 774 HashMap<String, Integer> failClasses, 775 HashMap<String, Integer> skipClasses) { 776 graphs.write("{"); 777 Set<String> names = passClasses.keySet(); 778 Iterator<String> label = names.iterator(); 779 while (label.hasNext()) { 780 String className = label.next(); 781 782 graphs.write(className + ": [" + passClasses.get(className) + ", " 783 + failClasses.get(className) + ", " 784 + skipClasses.get(className) + " ]"); 785 if (label.hasNext()) 786 graphs.write(","); 787 } 788 graphs.write(" },"); 789 } 790 791 private HashMap<String, Integer> getClasses(IResultMap tests) { 792 HashMap<String, Integer> classes = new HashMap<String, Integer>(); 793 Iterator<ITestResult> results = tests.getAllResults().iterator(); 794 while (results.hasNext()) { 795 String name = results.next().getTestClass().getName().toString(); 796 name = name.substring(name.lastIndexOf(".") + 1); 797 798 if (!classes.containsKey(name)) 799 classes.put(name, 1); 800 else 801 classes.put(name, classes.get(name) + 1); 802 } 803 return classes; 804 } 805 806}