Story Reporters

Reporting is an essential element of BDD as it allows to monitor the outcome of the stories that have been run. At the heart of JBehave's reporting is the StoryReporter, to which events are reported as they occur.

Currently, the story reporters supported are:

  • ConsoleOutput: a text-based console output
  • IdeOnlyConsoleOutput: a text-based console output, which only reports events when running in IDEs (Eclipse and IDEA supported).
  • TxtOutput: a text-based file output
  • HtmlOutput: an HTML file output
  • HtmlTemplateOutput: an HTML template-based file output. By default, a Freemarker-based template processor is used but a different implementation based on a different templating system can be provided.
  • XmlOutput: an XML file output
  • PostStoryStatisticsCollector: collects statistics and stores them as properties after story is run
  • DelegatingStoryReporter: used by the StoryReporterBuilder to delegate to any number of reporters as a proxy.

The StoryReporterBuilder allows to configure multiple story reporters with pre-configured formats: CONSOLE, TXT, HTML, HTML_TEMPLATE and XML.

Note that we use the StoryReporterBuilder to implement a builder pattern for file-based reporters via the FilePrintStreamFactory. The file path resolution strategy from a story path to a report file path is definable via the FilePathResolver. By default, it uses the ResolveToPackagedName whereby the story path is resolved to a Java package. So, e.g., if the story path is com/example/my_cool.story, we'll end up with file report outputs of the form: com.example.my_cool.[format] (where format is any of txt,html,xml in the example above). An alternative strategy, is the ResolveToSimpleName, whereby only the simple name portion, without the package structure, is considered, i.e. we'd end up with file report outputs of the form: my_cool.[format]

The builder provides defaults for all the formats supported, but if the user needs to create a bespoke instance of a reporter for a given format, it can be easily done by overriding the default. E.g. to override the reporter for TXT format to use a ".text" extension:

        StoryReporterBuilder builder = new StoryReporterBuilder() {
            public StoryReporter reporterFor(String storyPath, Format format) {
                switch (format) {
                case TXT:
                    factory.useConfiguration(new FileConfiguration("text"));
                    return new TxtOutput(factory.createPrintStream(), new Properties(), 
                                                        new LocalizedKeywords(), true);                    
                default:
                    return super.reporterFor(storyPath, format);
                }
            }
        };

Code Locations

The file-based print stream factory for the story reporting requires a StoryLocation to be provided in order to derive from it the output file paths (with the appropriate format extension). The story location, in turn, requires a code location URL and a story path.

The code location URLs can be created from different sources, via static methods in the CodeLocations utility class:

View Generation

The generation of the reports is only the first part of a complete HTML-based reporting solution. Next we generate the stories view, aggregating all the reports that have been configured and written to a given output directory, and presenting a collective index view for all formats configured. Moreover, we can style the reports, both for HTML and non-HTML report formats, by decorating their content with CSS and syntax highlighting. The decorating of non-HTML reports can be switched off if one prefers the raw content accessible via a URL:

    Properties viewResources = new Properties();
    viewResources("decorateNonHtml","false");
    new StoryReporterBuilder().useViewResources(viewResources);        

The view generation is the responsibility of the ViewGenerator. JBehave provides an implementation (FreemarkerViewGenerator.) based on Freemarker to allow a templateable and easily styleable way to generate the view. JBehave also provides a more generic TemplateableViewGenerator which supports any TemplateProcessorr to generate the view.

The default resources required for the view generation are bundled in the jbehave-core-resources.zip but can be overridden. The Freemarker templates (the ftl/** files) need to be the classpath for the FreemarkerViewGenerator to find them, while the look and feel resources (the js/* and style/* files) need to be copied to the target/jbehave/view directory (or wherever the story reporter builder relative directory is configured to be). Also note that the default style makes use of images found in the jbehave-site-resources.zip.

Maven users can use the unpack-view-resources goal which will derive the view directory from the configured Embedder and unpack to it the resources specified as normal project dependencies (provided they match the type and artifactId filters, see maven goals for more details).

Reporting Statistics

The PostStoryStatisticsCollector is treated in the view generation slightly differently from other reports, in that the statistics are displayed on the index view page, if available. To ensure they are always available the story reporter builder is configured to have stats as a default format (although the default formats need to be added to the builder).

Default Formats

Default formats allow users to define a builder that can be used in multiple configurations without having to repeat tediously all the formats required, if these are used consistently. By default, "stats" is the only default format (used for collecting reporting statistics). To modify simply override the method withDefaultFormats(). E.g. to add "txt" as a default format:

    new StoryReporterBuilder(){
        public StoryReporterBuilder withDefaultFormats() {
            return withFormats(STATS, TXT);
        }
    }

By default, JBehave writes file-based reports to the relative directory jbehave (relative to the story class code source location, e.g. the target directory in Maven), but this can be changed via the builder:

    new StoryReporterBuilder().withRelativeDirectory("my-output")

Story naming

All reported stories have the name equivalent to the name of the original story without ".story" extension. The exception is stories using ExamplesTable at the lifecycle level. Such stories have the postfix indicating the index of the current row of the example table. The index format can be configured via Configuration in StoryControls:

storyControls.useStoryIndexFormat(new DecimalFormat(<index format>)); //default value - " [0]" (minimum one integer digit in square brackets)

For example, if the format is " [000]" (minimum three integer digits in square brackets), stories will have names like "Story [000]", "Story [001]", "Story [010]", "Story [100]", etc. This can be useful when a reporting framework uses the lexicographic order for sorting and cannot correctly display the order of current ExamplesTable row.

Next?

The trader examples are configured to have a fully-working end-to-end use of JBehave reporting (be sure to read the instructions on running examples). After running the build simply open the page target/jbehave/view/reports.html of the appropriate trader example modules.