Title: [1450] trunk/core/examples/trader: JBEHAVE-226: Added statistics scenario reporter and displayed collected statistics on the reports index page.

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:

http://xircles.codehaus.org/manage_email

Reply via email to