- Revision
- 1450
- Author
- mauro
- Date
- 2009-12-22 09:14:36 -0600 (Tue, 22 Dec 2009)
Log Message
JBEHAVE-226: Added statistics scenario reporter and displayed collected statistics on the reports index page.
Modified Paths
- trunk/core/distribution/src/site/content/reports.html
- trunk/core/distribution/src/site/content/running-scenarios.html
- trunk/core/examples/trader/pom.xml
- trunk/core/examples/trader/src/main/java/org/jbehave/examples/trader/TraderScenario.java
- trunk/core/jbehave-core/src/behaviour/java/org/jbehave/scenario/reporters/PrintStreamScenarioReporterBehaviour.java
- trunk/core/jbehave-core/src/main/java/org/jbehave/scenario/reporters/FreemarkerReportRenderer.java
- trunk/core/jbehave-core/src/main/resources/ftl/jbehave-reports-index.ftl
- trunk/core/jbehave-core/src/main/resources/ftl/jbehave-reports-single.ftl
- trunk/core/jbehave-core/src/main/resources/style/jbehave-reports.css
Added Paths
Diff
Modified: trunk/core/distribution/src/site/content/reports.html (1449 => 1450)
--- trunk/core/distribution/src/site/content/reports.html 2009-12-22 11:20:04 UTC (rev 1449) +++ trunk/core/distribution/src/site/content/reports.html 2009-12-22 15:14:36 UTC (rev 1450) @@ -25,6 +25,9 @@ specialises the <b>PrintStreamScenarioReporter</b> to use HTML formats</li> <li><a + href="" + collects statistics and stores them as properties</li> + <li><a href="" delegates to any number of reporters as a proxy.</li> </ul> @@ -47,14 +50,18 @@ @Override public ScenarioReporter forReportingScenarios() { return new DelegatingScenarioReporter ( - // report to System.out in PLAIN format + return new DelegatingScenarioReporter( + // report to System.out new PrintStreamScenarioReporter(), // report to .txt file in PLAIN format - new PrintStreamScenarioReporter(new FilePrintStreamFactory(scenarioClass, converter, new FileConfiguration("txt")) - .getPrintStream()), - // report to .html file in HTML format - new HtmlPrintStreamScenarioReporter(new FilePrintStreamFactory(scenarioClass, converter, new FileConfiguration("html")) - .getPrintStream())); + new PrintStreamScenarioReporter(new FilePrintStreamFactory(scenarioClass, converter, + new FileConfiguration("txt")).getPrintStream()), + // report to .html file in HTML format + new HtmlPrintStreamScenarioReporter(new FilePrintStreamFactory(scenarioClass, converter, + new FileConfiguration("html")).getPrintStream()), + // report to .stats file in Properties format + new StatisticsScenarioReporter(new FilePrintStreamFactory(scenarioClass, converter, + new FileConfiguration("stats")).getPrintStream())); } }, new TraderSteps()); @@ -69,8 +76,8 @@ name resolution mechanism used for mapping Java classes and textual scenarios. So, e.g., if the scenario class is <b>com.example.MyScenario</b>, we'll end up with file report outputs of the form: <b>com.example.my_scenario.[format]</b> -(where <b>format</b> is <b>txt</b> and <b>html</b> in the example -above).</p> +(where <b>format</b> is <b>txt</b>, <b>html</b> and <b>stats</b>in the +example above).</p> <h2>Report Rendering</h2> @@ -96,6 +103,16 @@ and <b>jbehave-reports/style</b> directories. Also note that the default style makes use of images found in the <b>jbehave-site-resources.jar</b>.</p> +<span class="followup">Note that the <b>stats</b> report defined +above is treated in the rendering slightly differently from other +reports, in that the statistics are displayed in the index page, if +available. Conventionally, it looks for a report format named <b>stats</b>, +so if you configure it with a different name or not configure it at all, +the statistics will be displayed as not available (<b>N/A</b>). Also, +note that the report formats configured should match ones found in the +Ant or Maven execution for the report rendering task or goal (c.f. <a + href="" scenarios</a> for examples).</span> + <h2>Next?</h2> <span class="followup">The <a
Modified: trunk/core/distribution/src/site/content/running-scenarios.html (1449 => 1450)
--- trunk/core/distribution/src/site/content/running-scenarios.html 2009-12-22 11:20:04 UTC (rev 1449) +++ trunk/core/distribution/src/site/content/running-scenarios.html 2009-12-22 15:14:36 UTC (rev 1450) @@ -34,6 +34,12 @@ sourceDirectory="[sourceDirectory|src/main/java]" testSourceDirectory="[testSourceDirectory|src/test/java]" /> + <taskdef name="renderReports" + classname="org.jbehave.ant.ReportRendererTask" + classpathref="your.runtime.classpath" /> + + <renderReports formats="html,txt,stats" /> + </pre> <p>Remember to include <b>jbehave-ant</b> to your runtime classpath.</p> @@ -72,6 +78,20 @@ <goal>run-scenarios</goal> </goals> </execution> + <execution> + <id>render-reports</id> + <phase>integration-test</phase> + <configuration> + <formats> + <format>txt</format> + <format>html</format> + <format>stats</format> + </formats> + </configuration> + <goals> + <goal>render-reports</goal> + </goals> + </execution> </executions> </plugin> </pre>
Modified: trunk/core/examples/trader/pom.xml (1449 => 1450)
--- trunk/core/examples/trader/pom.xml 2009-12-22 11:20:04 UTC (rev 1449) +++ trunk/core/examples/trader/pom.xml 2009-12-22 15:14:36 UTC (rev 1450) @@ -122,6 +122,11 @@ <id>render-reports-generated</id> <phase>post-integration-test</phase> <configuration> + <formats> + <format>html</format> + <format>stats</format> + <format>txt</format> + </formats> </configuration> <goals> <goal>render-reports</goal>
Modified: trunk/core/examples/trader/src/main/java/org/jbehave/examples/trader/TraderScenario.java (1449 => 1450)
--- trunk/core/examples/trader/src/main/java/org/jbehave/examples/trader/TraderScenario.java 2009-12-22 11:20:04 UTC (rev 1449) +++ trunk/core/examples/trader/src/main/java/org/jbehave/examples/trader/TraderScenario.java 2009-12-22 15:14:36 UTC (rev 1450) @@ -8,6 +8,7 @@ import org.jbehave.scenario.parser.ScenarioDefiner; import org.jbehave.scenario.parser.ScenarioNameResolver; import org.jbehave.scenario.parser.UnderscoredCamelCaseResolver; +import org.jbehave.scenario.reporters.StatisticsScenarioReporter; import org.jbehave.scenario.reporters.DelegatingScenarioReporter; import org.jbehave.scenario.reporters.FilePrintStreamFactory; import org.jbehave.scenario.reporters.HtmlPrintStreamScenarioReporter; @@ -28,15 +29,19 @@ @Override public ScenarioReporter forReportingScenarios() { - return new DelegatingScenarioReporter ( + return new DelegatingScenarioReporter( // report to System.out new PrintStreamScenarioReporter(), // report to .txt file in PLAIN format - new PrintStreamScenarioReporter(new FilePrintStreamFactory(scenarioClass, converter, new FileConfiguration("txt")) - .getPrintStream()), - // report to .html file in HTML format - new HtmlPrintStreamScenarioReporter(new FilePrintStreamFactory(scenarioClass, converter, new FileConfiguration("html")) - .getPrintStream())); + new PrintStreamScenarioReporter(new FilePrintStreamFactory(scenarioClass, converter, + new FileConfiguration("txt")).getPrintStream()), + // report to .html file in HTML format + new HtmlPrintStreamScenarioReporter(new FilePrintStreamFactory(scenarioClass, converter, + new FileConfiguration("html")).getPrintStream()), + // report to .stats file in Properties format + new StatisticsScenarioReporter(new FilePrintStreamFactory(scenarioClass, converter, + new FileConfiguration("stats")).getPrintStream())); + } }, new TraderSteps());
Modified: trunk/core/jbehave-core/src/behaviour/java/org/jbehave/scenario/reporters/PrintStreamScenarioReporterBehaviour.java (1449 => 1450)
--- trunk/core/jbehave-core/src/behaviour/java/org/jbehave/scenario/reporters/PrintStreamScenarioReporterBehaviour.java 2009-12-22 11:20:04 UTC (rev 1449) +++ trunk/core/jbehave-core/src/behaviour/java/org/jbehave/scenario/reporters/PrintStreamScenarioReporterBehaviour.java 2009-12-22 15:14:36 UTC (rev 1450) @@ -23,47 +23,37 @@ import org.jbehave.scenario.definition.ScenarioDefinition; import org.jbehave.scenario.definition.StoryDefinition; import org.jbehave.scenario.i18n.I18nKeyWords; +import org.jbehave.scenario.parser.ScenarioNameResolver; import org.jbehave.scenario.parser.UnderscoredCamelCaseResolver; import org.jbehave.scenario.reporters.FilePrintStreamFactory.FileConfiguration; import org.jbehave.scenario.reporters.FreemarkerReportRenderer.RenderingFailedException; import org.junit.Test; - public class PrintStreamScenarioReporterBehaviour { - + @Test public void shouldReportEventsToPrintStream() { // Given OutputStream out = new ByteArrayOutputStream(); - ScenarioReporter reporter = new PrintStreamScenarioReporter(new PrintStream(out)); - - // When + ScenarioReporter reporter = new PrintStreamScenarioReporter(new PrintStream(out)); + + // When narrateAnInterestingStory(reporter); // Then - String expected = - "An interesting story\n" + - "(/path/to/story)\n"+ - "Scenario: I ask for a loan\n" + - "GivenScenarios: [/given/scenario1,/given/scenario2]\n" + - "Given I have a balance of $50\n" + - "When I request $20\n" + - "When I ask Liz for a loan of $100\n" + - "Then I should have a balance of $30 (PENDING)\n" + - "Then I should have $20 (NOT PERFORMED)\n" + - "Then I don't return loan (FAILED)\n" + - "Examples:\n\n" + - "|money|to|\n" + - "|$30|Mauro|\n" + - "|$50|Paul|\n" + - "\n\n" + // Examples table - "\nExample: {to=Mauro, money=$30}\n" + - "\nExample: {to=Paul, money=$50}\n" + - "\n" + // end of examples - "\n\n"; // end of scenario and story + String expected = "An interesting story\n" + "(/path/to/story)\n" + "Scenario: I ask for a loan\n" + + "GivenScenarios: [/given/scenario1,/given/scenario2]\n" + "Given I have a balance of $50\n" + + "When I request $20\n" + "When I ask Liz for a loan of $100\n" + + "Then I should have a balance of $30 (PENDING)\n" + "Then I should have $20 (NOT PERFORMED)\n" + + "Then I don't return loan (FAILED)\n" + "Examples:\n\n" + "|money|to|\n" + "|$30|Mauro|\n" + + "|$50|Paul|\n" + "\n\n" + // Examples table + "\nExample: {to=Mauro, money=$30}\n" + "\nExample: {to=Paul, money=$50}\n" + "\n" + // end + // of + // examples + "\n\n"; // end of scenario and story ensureThatOutputIs(out, expected); } - + @Test public void shouldReportEventsToHtmlPrintStream() { // Given @@ -75,41 +65,32 @@ } }; ScenarioReporter reporter = new HtmlPrintStreamScenarioReporter(factory.getPrintStream()); - - // When + + // When narrateAnInterestingStory(reporter); // Then - String expected = - "<div class=\"story\">\n<h1>An interesting story</h1>\n" + - "<div class=\"path\">/path/to/story</div>\n" + - "<div class=\"scenario\">\n<h2>Scenario: I ask for a loan</h2>\n" + - "<div class=\"givenScenarios\">GivenScenarios: [/given/scenario1,/given/scenario2]</div>\n" + - "<div class=\"step successful\">Given I have a balance of $50</div>\n" + - "<div class=\"step successful\">When I request $20</div>\n" + - "<div class=\"step successful\">When I ask Liz for a loan of $100</div>\n" + - "<div class=\"step pending\">Then I should have a balance of $30<span class=\"keyword pending\">(PENDING)</span></div>\n" + - "<div class=\"step notPerformed\">Then I should have $20<span class=\"keyword notPerformed\">(NOT PERFORMED)</span></div>\n" + - "<div class=\"step failed\">Then I don't return loan<span class=\"keyword failed\">(FAILED)</span></div>\n" + - "<div class=\"examples\">\n" + - "<h3>Examples:</h3>\n" + - "<table>\n" + - "<thead>\n" + - "<tr>\n<th>money</th><th>to</th></tr>\n" + - "</thead>\n" + - "<tbody>\n" + - "<tr>\n<td>$30</td><td>Mauro</td></tr>\n" + - "<tr>\n<td>$50</td><td>Paul</td></tr>\n" + - "</tbody>\n" + - "</table>\n" + - "\n<h3 class=\"example\">Example: {to=Mauro, money=$30}</h3>\n" + - "\n<h3 class=\"example\">Example: {to=Paul, money=$50}</h3>\n"+ - "</div>\n" + // end of examples - "</div>\n</div>\n"; // end of scenario and story - ensureThatOutputIs(out, expected); - } + String expected = "<div class=\"story\">\n<h1>An interesting story</h1>\n" + + "<div class=\"path\">/path/to/story</div>\n" + + "<div class=\"scenario\">\n<h2>Scenario: I ask for a loan</h2>\n" + + "<div class=\"givenScenarios\">GivenScenarios: [/given/scenario1,/given/scenario2]</div>\n" + + "<div class=\"step successful\">Given I have a balance of $50</div>\n" + + "<div class=\"step successful\">When I request $20</div>\n" + + "<div class=\"step successful\">When I ask Liz for a loan of $100</div>\n" + + "<div class=\"step pending\">Then I should have a balance of $30<span class=\"keyword pending\">(PENDING)</span></div>\n" + + "<div class=\"step notPerformed\">Then I should have $20<span class=\"keyword notPerformed\">(NOT PERFORMED)</span></div>\n" + + "<div class=\"step failed\">Then I don't return loan<span class=\"keyword failed\">(FAILED)</span></div>\n" + + "<div class=\"examples\">\n" + "<h3>Examples:</h3>\n" + "<table>\n" + "<thead>\n" + + "<tr>\n<th>money</th><th>to</th></tr>\n" + "</thead>\n" + "<tbody>\n" + + "<tr>\n<td>$30</td><td>Mauro</td></tr>\n" + "<tr>\n<td>$50</td><td>Paul</td></tr>\n" + "</tbody>\n" + + "</table>\n" + "\n<h3 class=\"example\">Example: {to=Mauro, money=$30}</h3>\n" + + "\n<h3 class=\"example\">Example: {to=Paul, money=$50}</h3>\n" + "</div>\n" + // end + // of + // examples + "</div>\n</div>\n"; // end of scenario and story + ensureThatOutputIs(out, expected); + } - @Test public void shouldReportEventsToHtmlPrintStreamUsingCustomOutputPatterns() { // Given @@ -120,49 +101,38 @@ return new PrintStream(out); } }; - Properties patterns = new Properties(); + Properties patterns = new Properties(); patterns.setProperty("afterStory", "</div><!-- after story -->\n"); patterns.setProperty("afterScenario", "</div><!-- after scenario -->\n"); patterns.setProperty("afterExamples", "</div><!-- after examples -->\n"); ScenarioReporter reporter = new HtmlPrintStreamScenarioReporter(factory.getPrintStream(), patterns); - - // When + + // When narrateAnInterestingStory(reporter); // Then - String expected = - "<div class=\"story\">\n<h1>An interesting story</h1>\n" + - "<div class=\"path\">/path/to/story</div>\n" + - "<div class=\"scenario\">\n<h2>Scenario: I ask for a loan</h2>\n" + - "<div class=\"givenScenarios\">GivenScenarios: [/given/scenario1,/given/scenario2]</div>\n" + - "<div class=\"step successful\">Given I have a balance of $50</div>\n" + - "<div class=\"step successful\">When I request $20</div>\n" + - "<div class=\"step successful\">When I ask Liz for a loan of $100</div>\n" + - "<div class=\"step pending\">Then I should have a balance of $30<span class=\"keyword pending\">(PENDING)</span></div>\n" + - "<div class=\"step notPerformed\">Then I should have $20<span class=\"keyword notPerformed\">(NOT PERFORMED)</span></div>\n" + - "<div class=\"step failed\">Then I don't return loan<span class=\"keyword failed\">(FAILED)</span></div>\n" + - "<div class=\"examples\">\n" + - "<h3>Examples:</h3>\n" + - "<table>\n" + - "<thead>\n" + - "<tr>\n<th>money</th><th>to</th></tr>\n" + - "</thead>\n" + - "<tbody>\n" + - "<tr>\n<td>$30</td><td>Mauro</td></tr>\n" + - "<tr>\n<td>$50</td><td>Paul</td></tr>\n" + - "</tbody>\n" + - "</table>\n" + - "\n<h3 class=\"example\">Example: {to=Mauro, money=$30}</h3>\n" + - "\n<h3 class=\"example\">Example: {to=Paul, money=$50}</h3>\n"+ - "</div><!-- after examples -->\n" + - "</div><!-- after scenario -->\n" + - "</div><!-- after story -->\n"; - ensureThatOutputIs(out, expected); - } - + String expected = "<div class=\"story\">\n<h1>An interesting story</h1>\n" + + "<div class=\"path\">/path/to/story</div>\n" + + "<div class=\"scenario\">\n<h2>Scenario: I ask for a loan</h2>\n" + + "<div class=\"givenScenarios\">GivenScenarios: [/given/scenario1,/given/scenario2]</div>\n" + + "<div class=\"step successful\">Given I have a balance of $50</div>\n" + + "<div class=\"step successful\">When I request $20</div>\n" + + "<div class=\"step successful\">When I ask Liz for a loan of $100</div>\n" + + "<div class=\"step pending\">Then I should have a balance of $30<span class=\"keyword pending\">(PENDING)</span></div>\n" + + "<div class=\"step notPerformed\">Then I should have $20<span class=\"keyword notPerformed\">(NOT PERFORMED)</span></div>\n" + + "<div class=\"step failed\">Then I don't return loan<span class=\"keyword failed\">(FAILED)</span></div>\n" + + "<div class=\"examples\">\n" + "<h3>Examples:</h3>\n" + "<table>\n" + "<thead>\n" + + "<tr>\n<th>money</th><th>to</th></tr>\n" + "</thead>\n" + "<tbody>\n" + + "<tr>\n<td>$30</td><td>Mauro</td></tr>\n" + "<tr>\n<td>$50</td><td>Paul</td></tr>\n" + "</tbody>\n" + + "</table>\n" + "\n<h3 class=\"example\">Example: {to=Mauro, money=$30}</h3>\n" + + "\n<h3 class=\"example\">Example: {to=Paul, money=$50}</h3>\n" + "</div><!-- after examples -->\n" + + "</div><!-- after scenario -->\n" + "</div><!-- after story -->\n"; + ensureThatOutputIs(out, expected); + } + private void narrateAnInterestingStory(ScenarioReporter reporter) { - StoryDefinition story = new StoryDefinition(new Blurb("An interesting story"), new ArrayList<ScenarioDefinition>(), - "/path/to/story"); + StoryDefinition story = new StoryDefinition(new Blurb("An interesting story"), + new ArrayList<ScenarioDefinition>(), "/path/to/story"); boolean embeddedStory = true; reporter.beforeStory(story, embeddedStory); String title = "I ask for a loan"; @@ -186,22 +156,23 @@ private void ensureThatOutputIs(OutputStream out, String expected) { // JUnit assertion allows easier comparison of strings in IDE assertEquals(expected, dos2unix(out.toString())); - //ensureThat(out.toString(), equalTo(expected)); + // ensureThat(out.toString(), equalTo(expected)); } - + private String dos2unix(String string) { - return string.replace("\r\n", "\n"); - } + return string.replace("\r\n", "\n"); + } @Test public void shouldReportThrowablesWhenToldToDoSo() { // Given IllegalAccessException exception = new IllegalAccessException("Leave my money alone!"); OutputStream stackTrace = new ByteArrayOutputStream(); - exception.printStackTrace(new PrintStream(stackTrace)); + exception.printStackTrace(new PrintStream(stackTrace)); OutputStream out = new ByteArrayOutputStream(); - ScenarioReporter reporter = new PrintStreamScenarioReporter(new PrintStream(out), new Properties(), new I18nKeyWords(), true); - + ScenarioReporter reporter = new PrintStreamScenarioReporter(new PrintStream(out), new Properties(), + new I18nKeyWords(), true); + // When reporter.beforeScenario("A title"); reporter.successful("Given I have a balance of $50"); @@ -212,20 +183,15 @@ reporter.afterScenario(); // Then - String expected = - "Scenario: A title\n" + - "Given I have a balance of $50\n" + - "When I request $20\n" + - "When I ask Liz for a loan of $100 (FAILED)\n" + - "Then I should have a balance of $30 (PENDING)\n" + - "Then I should have $20 (NOT PERFORMED)\n" + - "\n" + dos2unix(stackTrace.toString()) + "\n"; + String expected = "Scenario: A title\n" + "Given I have a balance of $50\n" + "When I request $20\n" + + "When I ask Liz for a loan of $100 (FAILED)\n" + "Then I should have a balance of $30 (PENDING)\n" + + "Then I should have $20 (NOT PERFORMED)\n" + "\n" + dos2unix(stackTrace.toString()) + "\n"; ensureThatOutputIs(out, expected); - + // Given out = new ByteArrayOutputStream(); reporter = new PrintStreamScenarioReporter(new PrintStream(out)); - + // When reporter.beforeScenario("A title"); reporter.successful("Given I have a balance of $50"); @@ -234,12 +200,12 @@ reporter.pending("Then I should have a balance of $30"); reporter.notPerformed("Then I should have $20"); reporter.afterScenario(); - + // Then ensureThat(!out.toString().contains(stackTrace.toString())); } - @Test + @Test public void shouldReportEventsToPrintStreamWithCustomPatterns() { // Given IllegalAccessException exception = new IllegalAccessException("Leave my money alone!"); @@ -248,24 +214,24 @@ patterns.setProperty("pending", "{0} - {1} - need to implement me\n"); patterns.setProperty("failed", "{0} <<< {1}\n"); patterns.setProperty("notPerformed", "{0} : {1} (because of previous pending)\n"); - ScenarioReporter reporter = new PrintStreamScenarioReporter(new PrintStream(out), patterns, new I18nKeyWords(), true); - - // When + ScenarioReporter reporter = new PrintStreamScenarioReporter(new PrintStream(out), patterns, new I18nKeyWords(), + true); + + // When reporter.successful("Given I have a balance of $50"); reporter.successful("When I request $20"); reporter.failed("When I ask Liz for a loan of $100", exception); reporter.pending("Then I should have a balance of $30"); reporter.notPerformed("Then I should have $20"); - + // Then - String expected = "Given I have a balance of $50\n" + - "When I request $20\n" + - "When I ask Liz for a loan of $100 <<< FAILED\n" + - "Then I should have a balance of $30 - PENDING - need to implement me\n" + - "Then I should have $20 : NOT PERFORMED (because of previous pending)\n"; + String expected = "Given I have a balance of $50\n" + "When I request $20\n" + + "When I ask Liz for a loan of $100 <<< FAILED\n" + + "Then I should have a balance of $30 - PENDING - need to implement me\n" + + "Then I should have $20 : NOT PERFORMED (because of previous pending)\n"; ensureThatOutputIs(out, expected); - + } @Test @@ -274,88 +240,93 @@ IllegalAccessException exception = new IllegalAccessException("Lasciate in pace i miei soldi!"); OutputStream out = new ByteArrayOutputStream(); I18nKeyWords keywords = new I18nKeyWords(Locale.ITALIAN); - ScenarioReporter reporter = new PrintStreamScenarioReporter(new PrintStream(out), new Properties(), keywords, true); - - // When + ScenarioReporter reporter = new PrintStreamScenarioReporter(new PrintStream(out), new Properties(), keywords, + true); + + // When reporter.successful("Dato che ho un saldo di $50"); reporter.successful("Quando richiedo $20"); reporter.failed("Quando chiedo a Liz un prestito di $100", exception); reporter.pending("Allora dovrei avere un saldo di $30"); reporter.notPerformed("Allora dovrei avere $20"); - + // Then - String expected = - "Dato che ho un saldo di $50\n" + - "Quando richiedo $20\n" + - "Quando chiedo a Liz un prestito di $100 (FALLITO)\n" + - "Allora dovrei avere un saldo di $30 (PENDENTE)\n" + - "Allora dovrei avere $20 (NON ESEGUITO)\n"; - + String expected = "Dato che ho un saldo di $50\n" + "Quando richiedo $20\n" + + "Quando chiedo a Liz un prestito di $100 (FALLITO)\n" + + "Allora dovrei avere un saldo di $30 (PENDENTE)\n" + "Allora dovrei avere $20 (NON ESEGUITO)\n"; + ensureThatOutputIs(out, expected); - + } @Test - public void shouldCreateAndWriteToFilePrintStreamForScenarioClass() throws IOException{ + public void shouldCreateAndWriteToFilePrintStreamForScenarioClass() throws IOException { UnderscoredCamelCaseResolver converter = new UnderscoredCamelCaseResolver(".scenario"); // Given Class<MyScenario> scenarioClass = MyScenario.class; File file = fileFor(scenarioClass, converter); - file.delete(); - ensureThat(!file.exists()); - + file.delete(); + ensureThat(!file.exists()); + // When FilePrintStreamFactory factory = new FilePrintStreamFactory(scenarioClass, converter); PrintStream printStream = factory.getPrintStream(); printStream.print("Hello World"); // Then - ensureThat(file.exists()); + ensureThat(file.exists()); ensureThat(IOUtils.toString(new FileReader(file)), equalTo("Hello World")); } - private File fileFor(Class<MyScenario> scenarioClass, UnderscoredCamelCaseResolver converter) { + private File fileFor(Class<MyScenario> scenarioClass, UnderscoredCamelCaseResolver converter) { FileConfiguration configuration = new FileConfiguration(); File outputDirectory = FilePrintStreamFactory.outputDirectory(scenarioClass, configuration); String fileName = FilePrintStreamFactory.fileName(scenarioClass, converter, configuration); return new File(outputDirectory, fileName); } - + @Test public void shouldReportEventsToFilePrintStreamsAndRenderAggregatedIndex() throws IOException { - // Given - FilePrintStreamFactory printStreamFactory = new FilePrintStreamFactory(MyScenario.class, new UnderscoredCamelCaseResolver()); - ScenarioReporter reporter = new HtmlPrintStreamScenarioReporter(printStreamFactory.getPrintStream()); - - // When + ScenarioNameResolver nameResolver = new UnderscoredCamelCaseResolver(); + Class<MyScenario> scenarioClass = MyScenario.class; + ScenarioReporter htmlReporter = new HtmlPrintStreamScenarioReporter(new FilePrintStreamFactory( + scenarioClass, nameResolver, new FileConfiguration("html")).getPrintStream()); + ScenarioReporter statsReporter = new StatisticsScenarioReporter(new FilePrintStreamFactory( + scenarioClass, nameResolver, new FileConfiguration("stats")).getPrintStream()); + ScenarioReporter txtReporter = new PrintStreamScenarioReporter(new FilePrintStreamFactory( + scenarioClass, nameResolver, new FileConfiguration("txt")).getPrintStream()); + ScenarioReporter reporter = new DelegatingScenarioReporter(htmlReporter, statsReporter, txtReporter); + + // When narrateAnInterestingStory(reporter); - File outputDirectory = printStreamFactory.getOutputDirectory(); + File outputDirectory = new FilePrintStreamFactory(scenarioClass, new UnderscoredCamelCaseResolver()) + .getOutputDirectory(); ReportRenderer renderer = new FreemarkerReportRenderer(); - renderer.render(outputDirectory, asList("html")); + renderer.render(outputDirectory, asList("html", "stats", "txt")); - // Then + // Then ensureFileExists(new File(outputDirectory, "rendered/index.html")); } private void ensureFileExists(File renderedOutput) throws IOException, FileNotFoundException { ensureThat(renderedOutput.exists()); ensureThat(IOUtils.toString(new FileReader(renderedOutput)).length() > 0); - } - - @Test(expected=RenderingFailedException.class) + } + + @Test(expected = RenderingFailedException.class) public void shouldFailRenderingOutputWithInexistentTemplates() throws IOException { // Given Properties templates = new Properties(); templates.setProperty("index", "target/inexistent"); ReportRenderer renderer = new FreemarkerReportRenderer(templates); - // When + // When File outputDirectory = new File("target"); renderer.render(outputDirectory, asList("html")); - // Then ... fail as expected - } + // Then ... fail as expected + } private static class MyScenario extends Scenario { - + } }
Modified: trunk/core/jbehave-core/src/main/java/org/jbehave/scenario/reporters/FreemarkerReportRenderer.java (1449 => 1450)
--- trunk/core/jbehave-core/src/main/java/org/jbehave/scenario/reporters/FreemarkerReportRenderer.java 2009-12-22 11:20:04 UTC (rev 1449) +++ trunk/core/jbehave-core/src/main/java/org/jbehave/scenario/reporters/FreemarkerReportRenderer.java 2009-12-22 15:14:36 UTC (rev 1450) @@ -1,6 +1,7 @@ package org.jbehave.scenario.reporters; import java.io.File; +import java.io.FileInputStream; import java.io.FileReader; import java.io.FileWriter; import java.io.FilenameFilter; @@ -205,6 +206,20 @@ public Map<String, File> getFilesByFormat() { return filesByFormat; } + + public Properties asProperties(String format){ + Properties p = new Properties(); + File stats = filesByFormat.get(format); + if ( stats == null ){ + return p; + } + try { + p.load(new FileInputStream(stats)); + } catch (IOException e) { + // return empty map + } + return p; + } } }
Added: trunk/core/jbehave-core/src/main/java/org/jbehave/scenario/reporters/StatisticsScenarioReporter.java (0 => 1450)
--- trunk/core/jbehave-core/src/main/java/org/jbehave/scenario/reporters/StatisticsScenarioReporter.java (rev 0) +++ trunk/core/jbehave-core/src/main/java/org/jbehave/scenario/reporters/StatisticsScenarioReporter.java 2009-12-22 15:14:36 UTC (rev 1450) @@ -0,0 +1,137 @@ +package org.jbehave.scenario.reporters; + +import static java.util.Arrays.asList; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.Writer; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +import org.jbehave.scenario.definition.Blurb; +import org.jbehave.scenario.definition.ExamplesTable; +import org.jbehave.scenario.definition.StoryDefinition; + +/** + * <p> + * Scenario reporter that collects statistics and stores them as properties to output + * stream + * </p> + */ +public class StatisticsScenarioReporter implements ScenarioReporter { + + private final OutputStream output; + private final Map<String, Integer> data = "" HashMap<String, Integer>(); + private final List<String> events = asList("steps", "stepsSuccessful", "stepsPending", "stepsNotPerformed", + "stepsFailed", "scenarios", "scenariosFailed", "givenScenarios", "examples"); + + private Throwable cause; + + public StatisticsScenarioReporter(OutputStream output) { + this.output = output; + } + + public void successful(String step) { + count("steps"); + count("stepsSuccessful"); + } + + public void pending(String step) { + count("steps"); + count("stepsPending"); + } + + public void notPerformed(String step) { + count("steps"); + count("stepsNotPerformed"); + } + + public void failed(String step, Throwable cause) { + this.cause = cause; + count("steps"); + count("stepsFailed"); + } + + public void beforeStory(StoryDefinition story, boolean embeddedStory) { + resetData(); + } + + public void beforeStory(Blurb blurb) { + beforeStory(new StoryDefinition(blurb), false); + } + + public void afterStory(boolean embeddedStory) { + writeData(); + } + + public void afterStory() { + afterStory(false); + } + + public void givenScenarios(List<String> givenScenarios) { + count("givenScenarios"); + } + + public void beforeScenario(String title) { + cause = null; + } + + public void afterScenario() { + count("scenarios"); + if (cause != null) { + count("scenariosFailed"); + } + } + + public void beforeExamples(ExamplesTable table) { + } + + public void example(Map<String, String> tableRow) { + count("examples"); + } + + public void afterExamples() { + } + + public void examplesTable(ExamplesTable table) { + beforeExamples(table); + } + + public void examplesTableRow(Map<String, String> tableRow) { + example(tableRow); + } + + private void count(String event) { + Integer count = data.get(event); + if (count == null) { + count = 0; + } + count++; + data.put(event, count); + } + + private void writeData() { + Properties p = new Properties(); + for (String event : data.keySet()) { + p.setProperty(event, data.get(event).toString()); + } + try { + Writer writer = new OutputStreamWriter(output); + p.store(writer, this.getClass().getName()); + writer.close(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private void resetData() { + data.clear(); + for (String event : events) { + data.put(event, 0); + } + } + +}
Modified: trunk/core/jbehave-core/src/main/resources/ftl/jbehave-reports-index.ftl (1449 => 1450)
--- trunk/core/jbehave-core/src/main/resources/ftl/jbehave-reports-index.ftl 2009-12-22 11:20:04 UTC (rev 1449) +++ trunk/core/jbehave-core/src/main/resources/ftl/jbehave-reports-index.ftl 2009-12-22 15:14:36 UTC (rev 1450) @@ -1,3 +1,6 @@ +<#ftl strip_whitespace=true> +<#macro stat name stats><#assign value = stats.get(name)!"N/A">${value}</#macro> + <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html> @@ -19,11 +22,20 @@ <h2>Story Reports</h2> <table> -<tr><th>Name</th><th>View</th></tr> +<tr><th>Name</th><th>Statistics</th><th>View</th></tr> <#list reports as report> -<#assign filesByFormat = report.filesByFormat > +<#assign filesByFormat = report.filesByFormat> <tr> <td>${report.name}</td> +<td> +<#assign stats = report.asProperties("stats")> +<#if (stats.size() > 0)> +Scenarios: <@stat "scenarios" stats/> (Failed: <@stat "scenariosFailed" stats/>)<br/> +Steps: <@stat "steps" stats/> (Success: <@stat "stepsSuccessful" stats/>; Pending: <@stat "stepsPending" stats/>; Not Performed: <@stat "stepsNotPerformed" stats/>; Failed: <@stat "stepsFailed" stats/>)<br/> +<#else> +N/A +</#if> +</td> <td><#list filesByFormat.keySet() as format><#assign file = filesByFormat.get(format)><a href="" format_has_next>|</#if></#list></td> </tr> </#list>
Modified: trunk/core/jbehave-core/src/main/resources/ftl/jbehave-reports-single.ftl (1449 => 1450)
--- trunk/core/jbehave-core/src/main/resources/ftl/jbehave-reports-single.ftl 2009-12-22 11:20:04 UTC (rev 1449) +++ trunk/core/jbehave-core/src/main/resources/ftl/jbehave-reports-single.ftl 2009-12-22 15:14:36 UTC (rev 1450) @@ -1,3 +1,4 @@ +<#ftl strip_whitespace=true> <html> <head> <title>${name}</title> @@ -9,7 +10,8 @@ <#if format == "html"> ${body} <#else> -<pre class="brush: ${format}"> +<#assign brushFormat = format> <#if format == "stats"><#assign brushFormat = "plain"> </#if> +<pre class="brush: ${brushFormat}"> ${body} </pre> </#if>
Modified: trunk/core/jbehave-core/src/main/resources/style/jbehave-reports.css (1449 => 1450)
--- trunk/core/jbehave-core/src/main/resources/style/jbehave-reports.css 2009-12-22 11:20:04 UTC (rev 1449) +++ trunk/core/jbehave-core/src/main/resources/style/jbehave-reports.css 2009-12-22 15:14:36 UTC (rev 1450) @@ -95,6 +95,21 @@ text-align: left; } +div.reports table { + border: solid; +} + +div.reports table th { + text-align: center; + font-weight: bold; + padding: 10px; +} + +div.reports table td { + text-align: left; + padding: 5px; +} + .story { text-align: left; margin-left: 10px; @@ -159,7 +174,7 @@ font-weight: bold; } -div.examples table th, div.examples table td { +div.examples table td { text-align: center; }
To unsubscribe from this list please visit:
