|
||||||
SUMMARY: CHILDREN | PARAMETER | INSTPROC | INSTFILTER | INSTFORWARD | DETAIL: | INSTPROC |
::xotcl::Object | +--::xounit::TestResultsTextFormatter
Format test results for display on a web page.
Variables | |||
Name | Default Value | Class | Comment |
apiDoc |
http://xotcllib.sourceforge.net/xodoc/ | ::xounit::TestResultsWebFormatter | url to API documentation |
location |
::xounit::TestResultsWebFormatter | location to write html file to |
|
styleSheet |
style.css | ::xounit::TestResultsWebFormatter | CSS stylesheet to use in html file |
textFormatter |
::xounit::TestResultsWebFormatter | text formatter to use |
|
title |
::xounit::TestResultsWebFormatter | title to use in html file |
|
url |
::xounit::TestResultsWebFormatter | url to more project information |
|
webPath |
::xounit::TestResultsWebFormatter | url where html file will be served |
Methods | |
Name | Comment |
barGraph {passed total}
| Creates the html code for a bar graph that measures the number of passes out of a total number of tests |
cleanUpData {data}
| Cleans up data for presentation in html |
cleanUpLink {link}
| Cleans up a string for use as an html link |
formatClassMethodsInError {error}
| Parse the Tcl/XOTcl stack trace and find instances of XOTcl method calls and add a link to the Class/Method in stack trace |
formatObjectClassMethodLine {line}
| In a stack trace line find a class and method and create a link to the API documentation from that class and method |
formatResults {results}
| Format a list of results and return the formatted string |
formatWebResults {results}
| Format a list of results for display on a web page |
init {}
| Initalizes the TestResultsWebFormatter with a new textFormatter |
makeClassLink {result}
| Make an html link from the testedClass in a TestResult |
makeClassMethodLink {result}
| Make an html linke from the testedClass and testedMethod in a TestResult |
organizeResults {resultOne resultTwo}
| Comparison method that will compare two test results to organize them by TestResult name |
passed {results}
| Returns true if all results passed |
printError {result anError}
| Format a TestError |
printFailure {result aFailure}
| Format a TestFailure |
printPass {result aPass}
| Format a TestPass |
printPasses {aResult}
| Formats all passing sub-results in a TestResult |
printResult {aResult}
| Format one TestResult and return the string |
printSubResult {result subResult}
| Format a subtest result |
rssItem {results link}
| Create an RSS item that describes how many tests failed in this test report |
testSummary {results}
| Format a summary of a list of TestResults |
writeWebResults {results}
| Write the formatted TestResults to location and update the RSS feed and the html index |
Methods from ::xotcl::Object |
#, ., ?, ?code, ?methods, ?object, abstract, copy, coverageFilter, defaultmethod, extractConfigureArg, filterappend, garbageCollect, get#, getClean#, hasclass, init, methodTag, mixinappend, move, profileFilter, self, setParameterDefaults, shell, tclcmd, traceFilter,
|
Instproc Detail |
Creates the html code for a bar graph that measures the number of passes out of a total number of tests.
passed
total
::xounit::TestResultsWebFormatter instproc barGraph {passed total} { if { $total == 0 } { set passWidth 0 set failWidth 200 set failed 0 set passed 0 } else { set failed [ expr { $total - $passed } ] set passWidth [ expr { int( 200 * $passed / $total ) } ] set failWidth [ expr { int( 200 * $failed / $total ) } ] } if { $passed == $total && $total > 0 } { append buffer " <TABLE class=barGraph cellspacing=0> <TBODY> <TR> <TD class=covered><img src=\"spacer.gif\" width=\"$passWidth\" height=\"12\"></TD> </TR> </TBODY> </TABLE>" } elseif { $passed == 0 } { append buffer " <TABLE class=barGraph cellspacing=0> <TBODY> <TR> <TD class=uncovered><img src=\"spacer.gif\" width=\"$failWidth\" height=\"12\"></TD> </TR> </TBODY> </TABLE>" } else { append buffer " <TABLE class=barGraph cellspacing=0> <TBODY> <TR> <TD class=covered><img src=\"spacer.gif\" width=\"$passWidth\" height=\"12\"></TD> <TD class=uncovered><img src=\"spacer.gif\" width=\"$failWidth\" height=\"12\"></TD> </TR> </TBODY> </TABLE>" } return $buffer }
Cleans up data for presentation in html
data
::xounit::TestResultsWebFormatter instproc cleanUpData {data} { regsub -all {\&} "$data" {\&} data regsub -all < "$data" {\<} data regsub -all > "$data" {\>} data return $data }
Cleans up a string for use as an html link.
link
::xounit::TestResultsWebFormatter instproc cleanUpLink {link} { regsub -all {::} "$link" {_} link regsub -all {#} "$link" {_} link return $link }
Parse the Tcl/XOTcl stack trace and find instances of XOTcl method calls and add a link to the Class/Method in stack trace.
error
::xounit::TestResultsWebFormatter instproc formatClassMethodsInError {error} { set newError "" foreach line [ split $error "\n" ] { if { [ string first "->" $line ] != -1 } { append newError [ my formatObjectClassMethodLine $line ] } else { append newError [ my cleanUpData $line ] append newError "\n" } } return $newError }
In a stack trace line find a class and method and create a link to the API documentation from that class and method.
line
::xounit::TestResultsWebFormatter instproc formatObjectClassMethodLine {line} { my instvar apiDoc if { ! [ my exists apiDoc ] } { return $line } set newError "" set object [ lindex $line 0 ] set classMethod [ lindex $line 1 ] set class [ lindex [ split $classMethod "->" ] 0 ] set method [ lindex [ split $classMethod "->" ] 2 ] if { ! [ Object isclass $class ] } { return $line } set cleanClass [ my cleanUpLink $class ] set index [ string first $class $line ] incr index -1 append newError [ string range $line 0 $index ] append newError "<a href=\"$apiDoc$cleanClass.html#$method\">[ my cleanUpData $classMethod ] </a>" append newError "\n" return $newError }
Format a list of results and return the formatted string.
results
::xounit::TestResultsWebFormatter instproc formatResults {results} { my instvar styleSheet set text [ my formatWebResults $results ] append buffer "<html><head>" append buffer "<LINK REL=StyleSheet HREF=\"$styleSheet\" TYPE=\"text/css\" />\n" append buffer "</head><body>\n" append buffer "<a href=\"index.html\">\[ Index \]</a><br/>\n" append buffer "$text\n" append buffer "</body></html>\n" return $buffer }
Format a list of results for display on a web page.
results
::xounit::TestResultsWebFormatter instproc formatWebResults {results} { set results [ lsort -command "[ self ] organizeResults" $results ] foreach result $results { puts "[ $result name ]" } set buffer "" append buffer [ my testSummary $results ] foreach result $results { if [ $result passed ] { continue } append buffer [ my printResult $result ] } append buffer "<h1>Passes</h1>" append buffer "<a href=\"#summary\">\[Summary\]</a> <br />" append buffer " <table class=\"FailureTable\"><tbody> <tr> <td class=\"FailureTableHeader\" >Test</td> <td class=\"FailureTableHeader\" >Message</td> </tr>" foreach result $results { append buffer [ my printPasses $result ] } append buffer "</tbody><table>" return $buffer }
Initalizes the TestResultsWebFormatter with a new textFormatter.
::xounit::TestResultsWebFormatter instproc init {} { my textFormatter [ ::xounit::TestResultsTextFormatter new ] }
Make an html link from the testedClass in a TestResult.
result
::xounit::TestResultsWebFormatter instproc makeClassLink {result} { my instvar apiDoc set class [ $result testedClass ] if { ! [ my exists apiDoc ] || ( "$class" == "" ) } { return [ $result name ] } set cleanClass [ my cleanUpLink $class ] return "<a href=\"$apiDoc$cleanClass.html\">[ $result name ]</a>" }
Make an html linke from the testedClass and testedMethod in a TestResult.
result
::xounit::TestResultsWebFormatter instproc makeClassMethodLink {result} { my instvar apiDoc set class [ $result testedClass ] set method [ $result testedMethod ] if { ! [ my exists apiDoc ] || ( "$class" == "" ) || ( "$method" == "" ) } { return [ $result test ] } set cleanClass [ my cleanUpLink $class ] return "<a href=\"$apiDoc$cleanClass.html#$method\">[ $result test ]</a>" }
Comparison method that will compare two test results to organize them by TestResult name.
resultOne
resultTwo
::xounit::TestResultsWebFormatter instproc organizeResults {resultOne resultTwo} { set nameOne [ $resultOne name ] set nameTwo [ $resultTwo name ] return [ string compare $nameOne $nameTwo ] }
Returns true if all results passed.
results
::xounit::TestResultsWebFormatter instproc passed {results} { foreach result $results { if { ! [ $result passed ] } { return 0 } } return 1 }
Format a TestError
result
anError
::xounit::TestResultsWebFormatter instproc printError {result anError} { set return "<tr> <td class=\"ErrorTable\"> <a name=\"[ my cleanUpLink $anError ]\"/> [ my makeClassLink $anError ] [ my makeClassMethodLink $anError ] </td> <td class=\"ErrorTable\">Error stacktrace below</td> <tr><td class=\"ErrorTable\" colspan=\"2\"> <pre>[ my formatClassMethodsInError [ $anError error] ]</pre> </td></tr>" return $return }
Format a TestFailure
result
aFailure
::xounit::TestResultsWebFormatter instproc printFailure {result aFailure} { set return "<tr> <td class=\"FailureTable\">[ my makeClassLink $aFailure ] [ my makeClassMethodLink $aFailure ] </td> <td class=\"FailureTable\"> <a name=\"[ my cleanUpLink $aFailure ]\"/> <pre>[ my cleanUpData [$aFailure error] ]</pre> </td></tr>" return $return }
Format a TestPass
result
aPass
::xounit::TestResultsWebFormatter instproc printPass {result aPass} { set return "<tr> <td class=\"PassTable\">[ my makeClassLink $aPass ] [ my makeClassMethodLink $aPass ] </td> <td class=\"PassTable\"> <pre> [ my cleanUpData [$aPass message] ]</pre> </td></tr>" return $return }
Formats all passing sub-results in a TestResult.
aResult
::xounit::TestResultsWebFormatter instproc printPasses {aResult} { set buffer "" foreach pass [ $aResult passes ] { append buffer [ my printPass $aResult $pass ] } return $buffer }
Format one TestResult and return the string.
aResult
::xounit::TestResultsWebFormatter instproc printResult {aResult} { set buffer "" append buffer "<a href=\"#summary\">\[Summary\]</a> <br />" append buffer " <table class=\"FailureTable\"><tbody> <tr> <td class=\"FailureTableHeader\" >Failure</td> <td class=\"FailureTableHeader\" >Message</td> </tr>" foreach error [ $aResult errors ] { append buffer [ my printError $aResult $error ] } foreach failure [ $aResult failures ] { append buffer [ my printFailure $aResult $failure ] } foreach subResult [ $aResult results ] { if [ $subResult hasclass ::xounit::TestPass ] { continue } if [ $subResult hasclass ::xounit::TestFail ] { continue } if [ $subResult hasclass ::xounit::TestError ] { continue } if [ $subResult passed ] { continue } append buffer [ my printSubResult $aResult $subResult ] } append buffer "</tbody><table>" return $buffer }
Format a subtest result.
result
subResult
::xounit::TestResultsWebFormatter instproc printSubResult {result subResult} { my instvar textFormatter set return "<tr> <td class=\"FailureTable\">[ $result name ] [ $subResult name ] </td> <td class=\"FailureTable\"> <a name=\"[ my cleanUpLink $subResult ]\"/> <pre>[ $textFormatter printSubResult $subResult ]</pre> </td></tr>" return $return }
Create an RSS item that describes how many tests failed in this test report.
results
link
::xounit::TestResultsWebFormatter instproc rssItem {results link} { set failures [ expr { [ my numberOfErrors $results ] + [ my numberOfFailures $results ] } ] set summary "[ clock format [ clock seconds ] -format "%b %d %H:%M:%S" ] Tests fail: $failures" return " <item> <title>$summary</title> <description>$summary</description> <link>$link</link> </item>" }
Format a summary of a list of TestResults.
results
::xounit::TestResultsWebFormatter instproc testSummary {results} { set buffer "" append buffer "<div class=\"summary\">" append buffer "<h1>Test Summary</h1><a name=\"summary\" />" append buffer "<table class=\"SummaryTable\"><tbody>" append buffer "<tr><td class=\"SummaryTableHeader\">Timestamp</td>" append buffer "<td class=\"SummaryTableHeader\">Tests</td>" append buffer "<td class=\"SummaryTableHeader\">Failures</td>" append buffer "<td class=\"SummaryTableHeader\">Passes</td>" append buffer "<td class=\"SummaryTableHeader\">Graph</td>" append buffer "</tr><tr>" append buffer "<td class=\"SummaryTable\"><span class=\"time\">[ clock format [ clock seconds ] -format "%b %d %H:%M:%S" ]</span></td>" append buffer "<td class=\"SummaryTable\">[ my numberOfTests $results ]</td>" set failures [ expr { [ my numberOfErrors $results ] + [ my numberOfFailures $results ] } ] append buffer "<td class=\"SummaryTable\">$failures</td>" append buffer "<td class=\"SummaryTable\">[ my numberOfPasses $results ]</td>" append buffer "<td class=\"SummaryTable\">" append buffer [ my barGraph [ my numberOfPasses $results ] [ my numberOfTests $results ] ] append buffer "</td></tr></tbody></table>" set index 0 append buffer "<h1>Failures</h1><a name=\"failures\" />" append buffer "<tr>" append buffer "<table class=\"SummaryTable\"><tbody>" append buffer "<td class=\"SummaryTableHeader\">Test Name</td>" append buffer "<td class=\"SummaryTableHeader\">Failure</td>" foreach result $results { foreach failure [ concat [ $result errors ] [ $result failures ] ] { append buffer "</tr><tr>" append buffer "<td class=\"SummaryTable\"><a href=\"#[ my cleanUpLink $failure ]\">[ $failure name ]</a></td>" append buffer "<td class=\"SummaryTable\"><a href=\"#[ my cleanUpLink $failure ]\">[ $failure test ]</a></td>" incr index } } append buffer "</td></tr></tbody></table>" append buffer "</div>" return $buffer }
Write the formatted TestResults to location and update the RSS feed and the html index.html. If the number of old test runs is greater than 100 then delete the oldest ones over 100.
results
::xounit::TestResultsWebFormatter instproc writeWebResults {results} { my instvar location webPath title url global env if { ! [ file exists $location ] } { file mkdir $location } set xounit [ ::xounit packagePath ] if { ! [ file exists [ file join $location rss.gif ] ] } { file copy $xounit/test/rss.gif $location } if { ! [ file exists [ file join $location spacer.gif ] ] } { file copy $xounit/test/spacer.gif $location } file copy -force $xounit/test/style.css $location set resultsName "results[ clock seconds ].html" set rssName "rss[ clock seconds ].xml" ::xox::withOpenFile [ file join $location $resultsName ] w file { puts $file [ my formatResults $results ] } ::xox::withOpenFile [ file join $location $rssName ] w file { puts $file [ my rssItem $results "$webPath/$resultsName" ] } ::xox::withOpenFile [ file join $location feed.xml ] w feed { puts $feed "<rss version=\"2.0\"> <channel> <title>$title</title> <description>Tests</description> <link>$url</link> " set rssFiles [ lsort -decreasing [ glob -nocomplain -directory $location rss*.xml ] ] foreach rssFile [ lrange $rssFiles 0 5 ] { puts $feed [ ::xox::readFile [ file join $location $rssFile ] ] } puts $feed " </channel> </rss> " } ::xox::withOpenFile [ file join $location index.html ] w index { puts $index "<html><body><a href=\"$url\"><h1>$title</h1></a>" set resultsFiles [ lsort -decreasing [ glob -nocomplain -directory $location results*.html ] ] puts $index { 100 Most Recent Test Runs:<br /> } foreach resultsFile [ lrange $resultsFiles 100 end ] { set webFile [ file tail $resultsFile ] set path [ file dirname $resultsFile ] regexp {results(\d+)} $webFile dummy time set rssFileName [ file join $path "rss$time.xml" ] puts "deleting old results $resultsFile" file delete $resultsFile puts "deleting old results $rssFileName" file delete $rssFileName } foreach resultsFile [ lrange $resultsFiles 0 100 ] { catch { set webFile [ file tail $resultsFile ] regexp {results(\d+)} $webFile dummy time set rssFileName "rss$time.xml" set rssDom [ [ dom parse [ ::xox::readFile [ file join $location $rssFileName ] ] ] documentElement ] set failures [ [ $rssDom getElementsByTagName description ] text ] puts $index "<a href=\"$webFile\" > $failures </a><br/>" } } puts $index {<link rel="alternate" type="application/rss+xml" title="Test Results Feed" href="feed.xml">} puts $index { <a href="feed.xml" alt="help!" ><img src="rss.gif" /></a> } puts $index "</body></html>" } }