package org.jbehave.core.reporters;
import static java.util.Arrays.asList;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.is;
import static org.jbehave.core.reporters.Format.HTML;
import static org.jbehave.core.reporters.Format.TXT;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.Date;
import java.util.Locale;
import java.util.Properties;
import org.custommonkey.xmlunit.XMLUnit;
import org.jbehave.core.failures.KnownFailure;
import org.jbehave.core.failures.UUIDExceptionWrapper;
import org.jbehave.core.i18n.LocalizedKeywords;
import org.jbehave.core.io.CodeLocations;
import org.jbehave.core.io.IOUtils;
import org.jbehave.core.io.StoryLocation;
import org.jbehave.core.io.StoryPathResolver;
import org.jbehave.core.io.UnderscoredCamelCaseResolver;
import org.jbehave.core.junit.JUnitStory;
import org.jbehave.core.model.OutcomesTable;
import org.jbehave.core.model.OutcomesTable.OutcomesFailed;
import org.jbehave.core.reporters.StoryNarrator.IsDateEqual;
import org.jbehave.core.reporters.TemplateableViewGenerator.ViewGenerationFailedForTemplate;
import org.junit.Test;
import org.xml.sax.SAXException;
public class PrintStreamOutputBehaviour {
@Test
public void shouldReportEventsToTxtOutput() {
// Given
OutputStream out = new ByteArrayOutputStream();
StoryReporter reporter = new TxtOutput(new PrintStream(out));
// When
StoryNarrator.narrateAnInterestingStory(reporter, false);
// Then
String expected = "An interesting story & special chars\n"
+ "(/path/to/story)\n"
+ "Meta:\n"
+ "@author Mauro\n"
+ "@theme testing\n"
+ "\n"
+ "DRY RUN\n"
+ "Narrative:\n"
+ "In order to renovate my house\n"
+ "As a customer\n"
+ "I want to get a loan\n"
+ "Scenario: I ask for a loan\n"
+ "GivenStories:\n"
+ "/given/story1 \n"
+ "/given/story2 \n"
+ "\n"
+ "Given I have a balance of $50\n"
+ "!-- Then ignore me\n"
+ "!-- A comment\n"
+ "When I request $20\n"
+ "When I ask Liz for a loan of $100\n"
+ "When I ask Liz for a loan of $99\n"
+ "When I write special chars <>&\"\n"
+ "When I write special chars in parameter <>&\"\n"
+ "When I write two parameters ,,, and &&&\n"
+ "Then I should... - try again (hi)\n"
+ "/path/to/story (Restarted Story)\n"
+ "STORY CANCELLED (DURATION 2 s)\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"
+ "(org.jbehave.core.model.OutcomesTable$OutcomesFailed)\n"
+ "|Description|Value|Matcher|Verified|\n"
+ "|I don't return all|100|<50.0>|No|\n"
+ "|A wrong date|01/01/2011|\"02/01/2011\"|No|\n"
+ "\n"
+ "Scenario: Parametrised Scenario\n"
+ "Examples:\n"
+ "Given money <money>\n"
+ "Then I give it to <to>\n"
+ "\n"
+ "|money|to|\n" + "|$30|Mauro|\n"
+ "|$50|Paul|\n" // Examples table
+ "\nExample: {money=$30, to=Mauro}\n"
+ "Given money $30\n"
+ "Then I give it to Mauro\n"
+ "\nExample: {money=$50, to=Paul}\n"
+ "Given money $50\n"
+ "Then I give it to Paul\n"
+ "Then I should have a balance of $30 (PENDING)\n"
+ "\n" // end of examples
+ "\n" // end of scenario
// pending methods
+ "@When(\"something \\\"$param\\\"\")\n"
+ "@Pending\n"
+ "public void whenSomething() {\n"
+ " // PENDING\n"
+ "}\n"
+ "\n"
+ "@Then(\"something is <param1>\")\n"
+ "@Pending\n"
+ "public void thenSomethingIsParam1() {\n"
+ " // PENDING\n"
+ "}\n\n"
+ "\n"; // end of story
assertThatOutputIs(out, expected);
}
@Test
public void shouldReportEventsToTxtOutputWhenNotAllowedByFilter() {
// Given
OutputStream out = new ByteArrayOutputStream();
StoryReporter reporter = new TxtOutput(new PrintStream(out));
// When
StoryNarrator
.narrateAnInterestingStoryNotAllowedByFilter(reporter, false);
// Then
String expected = "An interesting story\n"
+"(/path/to/story)\n"
+"Meta:\n"
+"@author Mauro\n"
+"@theme testing\n\n"
+"Scenario: A scenario\n"
+"-theme testing\n\n\n";
assertThatOutputIs(out, expected);
}
@Test
public void shouldReportEventsToHtmlOutput() {
// Given
final OutputStream out = new ByteArrayOutputStream();
PrintStreamFactory factory = new PrintStreamFactory() {
public PrintStream createPrintStream() {
return new PrintStream(out);
}
};
StoryReporter reporter = new HtmlOutput(factory.createPrintStream());
// When
StoryNarrator.narrateAnInterestingStory(reporter, false);
// Then
String expected = "<div class=\"story\">\n"
+ "<h1>An interesting story & special chars</h1>\n"
+ "<div class=\"path\">/path/to/story</div>\n"
+ "<div class=\"meta\">\n"
+ "<div class=\"keyword\">Meta:</div>\n"
+ "<div class=\"property\">@author Mauro</div>\n"
+ "<div class=\"property\">@theme testing</div>\n"
+ "</div>\n"
+ "<div class=\"dryRun\">DRY RUN</div>\n"
+ "<div class=\"narrative\"><h2>Narrative:</h2>\n"
+ "<div class=\"element inOrderTo\"><span class=\"keyword inOrderTo\">In order to</span> renovate my house</div>\n"
+ "<div class=\"element asA\"><span class=\"keyword asA\">As a</span> customer</div>\n"
+ "<div class=\"element iWantTo\"><span class=\"keyword iWantTo\">I want to</span> get a loan</div>\n"
+ "</div>\n"
+ "<div class=\"scenario\">\n"
+ "<h2>Scenario: I ask for a loan</h2>\n"
+ "<div class=\"givenStories\">GivenStories:\n"
+ "<div class=\"givenStory\">/given/story1 </div>\n"
+ "<div class=\"givenStory\">/given/story2 </div>\n"
+ "</div>\n"
+ "<div class=\"step successful\">Given I have a balance of $50</div>\n"
+ "<div class=\"step ignorable\">!-- Then ignore me</div>\n"
+ "<div class=\"comment\">!-- A comment</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 successful\">When I ask Liz for a loan of $<span class=\"step parameter\">99</span></div>\n"
+ "<div class=\"step successful\">When I write special chars <>&"</div>\n"
+ "<div class=\"step successful\">When I write special chars in parameter <span class=\"step parameter\"><>&"</span></div>\n"
+ "<div class=\"step successful\">When I write two parameters <span class=\"step parameter\">,,,</span> and <span class=\"step parameter\">&&&</span></div>\n"
+ "<div class=\"step restarted\">Then I should... - try again <span class=\"message restarted\">hi</span></div>\n"
+ "<div class=\"story restarted\">/path/to/story <span class=\"message restarted\">Restarted Story</span></div>\n"
+ "<div class=\"cancelled\">STORY CANCELLED (DURATION 2 s)</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><br/><span class=\"message failed\">org.jbehave.core.model.OutcomesTable$OutcomesFailed</span></div>\n"
+ "<div class=\"outcomes\"><table>\n"
+ "<thead>\n"
+ "<tr>\n"
+ "<th>Description</th><th>Value</th><th>Matcher</th><th>Verified</th></tr>\n"
+ "</thead>\n"
+ "<tbody>\n"
+ "<tr class=\"notVerified\">\n"
+ "<td>I don't return all</td><td>100.0</td><td><50.0></td><td>No</td></tr>\n"
+ "<tr class=\"notVerified\">\n"
+ "<td>A wrong date</td><td>01/01/2011</td><td>"02/01/2011"</td><td>No</td></tr>\n"
+ "</tbody>\n"
+ "</table></div>\n"
+ "</div>\n"
+ "<div class=\"scenario\">\n"
+ "<h2>Scenario: Parametrised Scenario</h2>\n"
+ "<div class=\"examples\">\n"
+ "<h3>Examples:</h3>\n"
+ "<div class=\"step\">Given money <money></div>\n"
+ "<div class=\"step\">Then I give it to <to></div>\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: {money=$30, to=Mauro}</h3>\n"
+ "<div class=\"step successful\">Given money $30</div>\n"
+ "<div class=\"step successful\">Then I give it to Mauro</div>\n"
+ "\n"
+ "<h3 class=\"example\">Example: {money=$50, to=Paul}</h3>\n"
+ "<div class=\"step successful\">Given money $50</div>\n"
+ "<div class=\"step successful\">Then I give it to Paul</div>\n"
+ "<div class=\"step pending\">Then I should have a balance of $30 <span class=\"keyword pending\">(PENDING)</span></div>\n"
+ "</div>\n"
+ "</div>\n"
+ "<div><pre class=\"pending\">@When("something \\"$param\\"")\n"
+ "@Pending\n"
+ "public void whenSomething() {\n"
+ " // PENDING\n"
+ "}\n"
+ "</pre></div>\n"
+ "<div><pre class=\"pending\">@Then("something is <param1>")\n"
+ "@Pending\n"
+ "public void thenSomethingIsParam1() {\n"
+ " // PENDING\n"
+ "}\n"
+ "</pre></div>\n"
+ "</div>\n"; // end of story
assertThatOutputIs(out, expected);
}
@Test
public void shouldReportEventsToHtmlOutputWhenNotAllowedByFilter() {
// Given
OutputStream out = new ByteArrayOutputStream();
StoryReporter reporter = new HtmlOutput(new PrintStream(out));
// When
StoryNarrator
.narrateAnInterestingStoryNotAllowedByFilter(reporter, false);
// Then
String expected ="<div class=\"story\">\n"
+ "<h1>An interesting story</h1>\n"
+ "<div class=\"path\">/path/to/story</div>\n"
+ "<div class=\"meta\">\n"
+ "<div class=\"keyword\">Meta:</div>\n"
+ "<div class=\"property\">@author Mauro</div>\n"
+ "<div class=\"property\">@theme testing</div>\n"
+ "</div>\n"
+ "<div class=\"scenario\">\n"
+ "<h2>Scenario: A scenario</h2>\n"
+ "<div class=\"filter\">-theme testing</div>\n"
+ "</div>\n"
+ "</div>\n";
assertThatOutputIs(out, expected);
}
@Test
public void shouldReportEventsToHtmlOutputUsingCustomPatterns() {
// Given
final OutputStream out = new ByteArrayOutputStream();
PrintStreamFactory factory = new PrintStreamFactory() {
public PrintStream createPrintStream() {
return new PrintStream(out);
}
};
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");
StoryReporter reporter = new HtmlOutput(factory.createPrintStream(), patterns);
// When
StoryNarrator.narrateAnInterestingStory(reporter, false);
// Then
String expected = "<div class=\"story\">\n"
+ "<h1>An interesting story & special chars</h1>\n"
+ "<div class=\"path\">/path/to/story</div>\n"
+ "<div class=\"meta\">\n"
+ "<div class=\"keyword\">Meta:</div>\n"
+ "<div class=\"property\">@author Mauro</div>\n"
+ "<div class=\"property\">@theme testing</div>\n"
+ "</div>\n"
+ "<div class=\"dryRun\">DRY RUN</div>\n"
+ "<div class=\"narrative\"><h2>Narrative:</h2>\n"
+ "<div class=\"element inOrderTo\"><span class=\"keyword inOrderTo\">In order to</span> renovate my house</div>\n"
+ "<div class=\"element asA\"><span class=\"keyword asA\">As a</span> customer</div>\n"
+ "<div class=\"element iWantTo\"><span class=\"keyword iWantTo\">I want to</span> get a loan</div>\n"
+ "</div>\n"
+ "<div class=\"scenario\">\n"
+ "<h2>Scenario: I ask for a loan</h2>\n"
+ "<div class=\"givenStories\">GivenStories:\n"
+ "<div class=\"givenStory\">/given/story1 </div>\n"
+ "<div class=\"givenStory\">/given/story2 </div>\n"
+ "</div>\n"
+ "<div class=\"step successful\">Given I have a balance of $50</div>\n"
+ "<div class=\"step ignorable\">!-- Then ignore me</div>\n"
+ "<div class=\"comment\">!-- A comment</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 successful\">When I ask Liz for a loan of $<span class=\"step parameter\">99</span></div>\n"
+ "<div class=\"step successful\">When I write special chars <>&"</div>\n"
+ "<div class=\"step successful\">When I write special chars in parameter <span class=\"step parameter\"><>&"</span></div>\n"
+ "<div class=\"step successful\">When I write two parameters <span class=\"step parameter\">,,,</span> and <span class=\"step parameter\">&&&</span></div>\n"
+ "<div class=\"step restarted\">Then I should... - try again <span class=\"message restarted\">hi</span></div>\n"
+ "<div class=\"story restarted\">/path/to/story <span class=\"message restarted\">Restarted Story</span></div>\n"
+ "<div class=\"cancelled\">STORY CANCELLED (DURATION 2 s)</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><br/><span class=\"message failed\">org.jbehave.core.model.OutcomesTable$OutcomesFailed</span></div>\n"
+ "<div class=\"outcomes\"><table>\n"
+ "<thead>\n"
+ "<tr>\n"
+ "<th>Description</th><th>Value</th><th>Matcher</th><th>Verified</th></tr>\n"
+ "</thead>\n"
+ "<tbody>\n"
+ "<tr class=\"notVerified\">\n"
+ "<td>I don't return all</td><td>100.0</td><td><50.0></td><td>No</td></tr>\n"
+ "<tr class=\"notVerified\">\n"
+ "<td>A wrong date</td><td>01/01/2011</td><td>"02/01/2011"</td><td>No</td></tr>\n"
+ "</tbody>\n"
+ "</table></div>\n"
+ "</div><!-- after scenario -->\n"
+ "<div class=\"scenario\">\n"
+ "<h2>Scenario: Parametrised Scenario</h2>\n"
+ "<div class=\"examples\">\n"
+ "<h3>Examples:</h3>\n"
+ "<div class=\"step\">Given money <money></div>\n"
+ "<div class=\"step\">Then I give it to <to></div>\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: {money=$30, to=Mauro}</h3>\n"
+ "<div class=\"step successful\">Given money $30</div>\n"
+ "<div class=\"step successful\">Then I give it to Mauro</div>\n"
+ "\n"
+ "<h3 class=\"example\">Example: {money=$50, to=Paul}</h3>\n"
+ "<div class=\"step successful\">Given money $50</div>\n"
+ "<div class=\"step successful\">Then I give it to Paul</div>\n"
+ "<div class=\"step pending\">Then I should have a balance of $30 <span class=\"keyword pending\">(PENDING)</span></div>\n"
+ "</div><!-- after examples -->\n"
+ "</div><!-- after scenario -->\n"
// pending methods
+ "<div><pre class=\"pending\">@When("something \\"$param\\"")\n"
+ "@Pending\n"
+ "public void whenSomething() {\n"
+ " // PENDING\n"
+ "}\n"
+ "</pre></div>\n"
+ "<div><pre class=\"pending\">@Then("something is <param1>")\n"
+ "@Pending\n"
+ "public void thenSomethingIsParam1() {\n"
+ " // PENDING\n"
+ "}\n"
+ "</pre></div>\n"
+ "</div><!-- after story -->\n";
assertThatOutputIs(out, expected);
}
@Test
public void shouldReportEventsToXmlOutput() throws SAXException, IOException {
// Given
final OutputStream out = new ByteArrayOutputStream();
PrintStreamFactory factory = new PrintStreamFactory() {
public PrintStream createPrintStream() {
return new PrintStream(out);
}
};
StoryReporter reporter = new XmlOutput(factory.createPrintStream());
// When
StoryNarrator.narrateAnInterestingStory(reporter, false);
// Then
String expected = "<story path=\"/path/to/story\" title=\"An interesting story & special chars\">\n"
+ "<meta>\n"
+ "<property keyword=\"@\" name=\"author\" value=\"Mauro\"/>\n"
+ "<property keyword=\"@\" name=\"theme\" value=\"testing\"/>\n"
+ "</meta>\n"
+ "<dryRun>DRY RUN</dryRun>\n"
+ "<narrative keyword=\"Narrative:\">\n"
+ " <inOrderTo keyword=\"In order to\">renovate my house</inOrderTo>\n"
+ " <asA keyword=\"As a\">customer</asA>\n"
+ " <iWantTo keyword=\"I want to\">get a loan</iWantTo>\n"
+ "</narrative>\n"
+ "<scenario keyword=\"Scenario:\" title=\"I ask for a loan\">\n"
+ "<givenStories keyword=\"GivenStories:\">\n"
+ "<givenStory parameters=\"\">/given/story1</givenStory>\n"
+ "<givenStory parameters=\"\">/given/story2</givenStory>\n"
+ "</givenStories>\n"
+ "<step outcome=\"successful\">Given I have a balance of $50</step>\n"
+ "<step outcome=\"ignorable\">!-- Then ignore me</step>\n"
+ "<step outcome=\"comment\">!-- A comment</step>\n"
+ "<step outcome=\"successful\">When I request $20</step>\n"
+ "<step outcome=\"successful\">When I ask Liz for a loan of $100</step>\n"
+ "<step outcome=\"successful\">When I ask Liz for a loan of $<parameter>99</parameter></step>\n"
+ "<step outcome=\"successful\">When I write special chars <>&"</step>\n"
+ "<step outcome=\"successful\">When I write special chars in parameter <parameter><>&"</parameter></step>\n"
+ "<step outcome=\"successful\">When I write two parameters <parameter>,,,</parameter> and <parameter>&&&</parameter></step>\n"
+ "<step outcome=\"restarted\">Then I should... - try again<reason>hi</reason></step>\n"
+ "<story outcome=\"restartedStory\">/path/to/story<reason>Restarted Story</reason></story>\n"
+ "<cancelled keyword=\"STORY CANCELLED\" durationKeyword=\"DURATION\" durationInSecs=\"2\"/>\n"
+ "<step outcome=\"pending\" keyword=\"PENDING\">Then I should have a balance of $30</step>\n"
+ "<step outcome=\"notPerformed\" keyword=\"NOT PERFORMED\">Then I should have $20</step>\n"
+ "<step outcome=\"failed\" keyword=\"FAILED\">Then I don't return loan<failure>org.jbehave.core.model.OutcomesTable$OutcomesFailed</failure></step>\n"
+ "<outcomes>\n"
+ "<fields><field>Description</field><field>Value</field><field>Matcher</field><field>Verified</field></fields>\n"
+ "<outcome><value>I don't return all</value><value>100.0</value><value><50.0></value><value>No</value></outcome>\n"
+ "<outcome><value>A wrong date</value><value>01/01/2011</value><value>"02/01/2011"</value><value>No</value></outcome>\n"
+ "</outcomes>\n"
+ "</scenario>\n"
+ "<scenario keyword=\"Scenario:\" title=\"Parametrised Scenario\">\n"
+ "<examples keyword=\"Examples:\">\n"
+ "<step>Given money <money></step>\n"
+ "<step>Then I give it to <to></step>\n"
+ "<parameters>\n"
+ "<names><name>money</name><name>to</name></names>\n"
+ "<values><value>$30</value><value>Mauro</value></values>\n"
+ "<values><value>$50</value><value>Paul</value></values>\n"
+ "</parameters>\n"
+ "\n"
+ "<example keyword=\"Example:\">{money=$30, to=Mauro}</example>\n"
+ "<step outcome=\"successful\">Given money $30</step>\n"
+ "<step outcome=\"successful\">Then I give it to Mauro</step>\n"
+ "\n"
+ "<example keyword=\"Example:\">{money=$50, to=Paul}</example>\n"
+ "<step outcome=\"successful\">Given money $50</step>\n"
+ "<step outcome=\"successful\">Then I give it to Paul</step>\n"
+ "<step outcome=\"pending\" keyword=\"PENDING\">Then I should have a balance of $30</step>\n"
+ "</examples>\n"
+ "</scenario>\n"
// pending methods
+ "<pendingMethod>@When("something \\"$param\\"")\n"
+ "@Pending\n"
+ "public void whenSomething() {\n"
+ " // PENDING\n"
+ "}\n"
+ "</pendingMethod>\n"
+ "<pendingMethod>@Then("something is <param1>")\n"
+ "@Pending\n"
+ "public void thenSomethingIsParam1() {\n"
+ " // PENDING\n"
+ "}\n"
+ "</pendingMethod>\n"
+ "</story>\n";
String xmlDocument=out.toString();
XMLUnit.buildTestDocument(xmlDocument);
assertEquals(expected, xmlDocument);
}
@Test
public void shouldNotSuppressStackTraceForNotKnownFailure() {
// Given
final OutputStream out = new ByteArrayOutputStream();
PrintStreamFactory factory = new PrintStreamFactory() {
public PrintStream createPrintStream() {
return new PrintStream(out);
}
};
TxtOutput reporter = new TxtOutput(factory.createPrintStream(), new Properties(), new LocalizedKeywords(), true);
reporter.failed("Then I should have a balance of $30", new UUIDExceptionWrapper(new NullPointerException()));
reporter.afterScenario();
assertThatOutputStartsWith(out, "Then I should have a balance of $30 (FAILED)\n" +
"(java.lang.NullPointerException)\n" +
"\n" +
"java.lang.NullPointerException\n" +
"\tat "); // there is a whole stack trace but we're skipping that for the sake of an assertion
}
@Test
public void shouldSuppressStackTraceForKnownFailure() {
// Given
final OutputStream out = new ByteArrayOutputStream();
PrintStreamFactory factory = new PrintStreamFactory() {
public PrintStream createPrintStream() {
return new PrintStream(out);
}
};
TxtOutput reporter = new TxtOutput(factory.createPrintStream(), new Properties(), new LocalizedKeywords(), true);
reporter.failed("Then I should have a balance of $30", new UUIDExceptionWrapper(new MyKnownFailure()));
reporter.afterScenario();
assertThatOutputIs(out, "Then I should have a balance of $30 (FAILED)\n" +
"(org.jbehave.core.reporters.PrintStreamOutputBehaviour$MyKnownFailure)\n\n" +
"");
}
@Test
public void shouldReportEventsToXmlOutputWhenNotAllowedByFilter() {
// Given
OutputStream out = new ByteArrayOutputStream();
StoryReporter reporter = new XmlOutput(new PrintStream(out));
// When
StoryNarrator
.narrateAnInterestingStoryNotAllowedByFilter(reporter, false);
// Then
String expected = "<story path=\"/path/to/story\" title=\"An interesting story\">\n"
+ "<meta>\n"
+ "<property keyword=\"@\" name=\"author\" value=\"Mauro\"/>\n"
+ "<property keyword=\"@\" name=\"theme\" value=\"testing\"/>\n"
+ "</meta>\n"
+ "<scenario keyword=\"Scenario:\" title=\"A scenario\">\n"
+ "<filter>-theme testing</filter>\n"
+ "</scenario>\n"
+ "</story>\n";
assertThatOutputIs(out, expected);
}
private void assertThatOutputIs(OutputStream out, String expected) {
assertEquals(expected, dos2unix(out.toString()));
}
private void assertThatOutputStartsWith(OutputStream out, String expected) {
assertTrue(dos2unix(out.toString()).startsWith(expected));
}
private String dos2unix(String string) {
return string.replace("\r\n", "\n");
}
@Test
public void shouldReportFailureTraceWhenToldToDoSo() {
// Given
UUIDExceptionWrapper exception = new UUIDExceptionWrapper(new RuntimeException("Leave my money alone!"));
OutputStream stackTrace = new ByteArrayOutputStream();
exception.getCause().printStackTrace(new PrintStream(stackTrace));
OutputStream out = new ByteArrayOutputStream();
TxtOutput reporter = new TxtOutput(new PrintStream(out), new Properties(),
new LocalizedKeywords(), true);
// When
reporter.beforeScenario("A title");
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");
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"
+ "(java.lang.RuntimeException: Leave my money alone!)\n"
+ "Then I should have a balance of $30 (PENDING)\n"
+ "Then I should have $20 (NOT PERFORMED)\n"
+ "\n";
String actual = dos2unix(out.toString());
assertThat(actual, containsString(expected));
assertThat(actual, containsString("at org.jbehave.core.reporters.PrintStreamOutputBehaviour.shouldReportFailureTraceWhenToldToDoSo("));
// Given
out = new ByteArrayOutputStream();
reporter = new TxtOutput(new PrintStream(out));
// When
reporter.beforeScenario("A title");
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");
reporter.afterScenario();
// Then
assertThat(out.toString().contains(stackTrace.toString()), is(false));
}
@Test
public void shouldReportEventsToTxtOutputWithCustomPatterns() {
// Given
UUIDExceptionWrapper exception = new UUIDExceptionWrapper(new RuntimeException("Leave my money alone!"));
OutputStream out = new ByteArrayOutputStream();
Properties patterns = new Properties();
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");
StoryReporter reporter = new TxtOutput(new PrintStream(out), patterns, new LocalizedKeywords(),
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";
assertThatOutputIs(out, expected);
}
@Test
public void shouldReportEventsToIdeOnlyConsoleOutput() {
// When
StoryNarrator.narrateAnInterestingStory(new IdeOnlyConsoleOutput(), false);
StoryNarrator.narrateAnInterestingStory(new IdeOnlyConsoleOutput(new LocalizedKeywords()), false);
StoryNarrator.narrateAnInterestingStory(new IdeOnlyConsoleOutput(new Properties(), new LocalizedKeywords(), true), false);
}
@Test
public void shouldReportEventsToPrintStreamInItalian() {
// Given
UUIDExceptionWrapper exception = new UUIDExceptionWrapper(new RuntimeException("Lasciate in pace i miei soldi!"));
OutputStream out = new ByteArrayOutputStream();
LocalizedKeywords keywords = new LocalizedKeywords(Locale.ITALIAN);
StoryReporter reporter = new TxtOutput(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"
+ "(java.lang.RuntimeException: Lasciate in pace i miei soldi!)\n"
+ "Allora dovrei avere un saldo di $30 (IN SOSPESO)\n"
+ "Allora dovrei avere $20 (NON ESEGUITO)\n";
assertThatOutputIs(out, expected);
}
@Test
public void shouldCreateAndWriteToFilePrintStreamForStoryLocation() throws IOException {
// Given
String storyPath = storyPath(MyStory.class);
FilePrintStreamFactory factory = new FilePrintStreamFactory(new StoryLocation(CodeLocations.codeLocationFromClass(this.getClass()), storyPath));
File file = factory.outputFile();
file.delete();
assertThat(file.exists(), is(false));
// When
PrintStream printStream = factory.createPrintStream();
file = factory.getOutputFile();
printStream.print("Hello World");
// Then
assertThat(file.exists(), is(true));
assertThat(IOUtils.toString(new FileReader(file), true), equalTo("Hello World"));
}
@Test
public void shouldReportEventsToFilePrintStreamsAndGenerateView() throws IOException {
final String storyPath = storyPath(MyStory.class);
File outputDirectory = new File("target/output");
StoryReporter reporter = new StoryReporterBuilder().withRelativeDirectory(outputDirectory.getName())
.withFormats(HTML, TXT)
.build(storyPath);
// When
StoryNarrator.narrateAnInterestingStory(reporter, false);
ViewGenerator viewGenerator = new FreemarkerViewGenerator();
Properties viewProperties = new Properties();
viewGenerator.generateReportsView(outputDirectory, asList("html", "txt"), viewProperties);
// Then
ensureFileExists(new File(outputDirectory, "view/index.html"));
ensureFileExists(new File(outputDirectory, "view/org.jbehave.core.reporters.my_story.txt.html"));
}
@Test
public void shouldReportEventsToFilePrintStreamsAndGenerateViewWithoutDecoratingNonHtml() throws IOException {
final String storyPath = storyPath(MyStory.class);
File outputDirectory = new File("target/output");
StoryReporter reporter = new StoryReporterBuilder().withRelativeDirectory(outputDirectory.getName())
.withFormats(HTML, TXT)
.build(storyPath);
// When
StoryNarrator.narrateAnInterestingStory(reporter, false);
((ConcurrentStoryReporter) reporter).invokeDelayed();
ViewGenerator viewGenerator = new FreemarkerViewGenerator();
Properties viewProperties = new Properties();
viewProperties.setProperty("decorateNonHtml", "false");
viewGenerator.generateReportsView(outputDirectory, asList("html", "txt"), viewProperties);
// Then
ensureFileExists(new File(outputDirectory, "view/index.html"));
ensureFileExists(new File(outputDirectory, "view/org.jbehave.core.reporters.my_story.txt"));
}
@Test
public void shouldBuildPrintStreamReportersAndOverrideDefaultForAGivenFormat() throws IOException {
final String storyPath = storyPath(MyStory.class);
final FilePrintStreamFactory factory = new FilePrintStreamFactory(new StoryLocation(CodeLocations.codeLocationFromClass(this.getClass()), storyPath));
StoryReporter reporter = new StoryReporterBuilder() {
@Override
public StoryReporter reporterFor(String storyPath, org.jbehave.core.reporters.Format format) {
if (format == org.jbehave.core.reporters.Format.TXT) {
factory.useConfiguration(new FilePrintStreamFactory.FileConfiguration("text"));
return new TxtOutput(factory.createPrintStream(), new Properties(), new LocalizedKeywords(), true);
} else {
return super.reporterFor(storyPath, format);
}
}
}.withFormats(TXT).build(storyPath);
// When
StoryNarrator.narrateAnInterestingStory(reporter, false);
((ConcurrentStoryReporter) reporter).invokeDelayed();
// Then
File outputFile = factory.getOutputFile();
ensureFileExists(outputFile);
}
private void ensureFileExists(File file) throws IOException, FileNotFoundException {
assertThat(file.exists(), is(true));
assertThat(IOUtils.toString(new FileReader(file), true).length(), greaterThan(0));
}
@Test(expected = ViewGenerationFailedForTemplate.class)
public void shouldFailGeneratingViewWithInexistentTemplates() throws IOException {
// Given
Properties templates = new Properties();
templates.setProperty("reports", "target/inexistent");
ViewGenerator viewGenerator = new FreemarkerViewGenerator();
// When
File outputDirectory = new File("target");
viewGenerator.generateReportsView(outputDirectory, asList("html"), templates);
// Then ... fail as expected
}
private String storyPath(Class<MyStory> storyClass) {
StoryPathResolver resolver = new UnderscoredCamelCaseResolver(".story");
return resolver.resolve(storyClass);
}
@Test
public void shouldUseDateConversionPattern() {
// Given
OutputStream out = new ByteArrayOutputStream();
StoryReporter reporter = new TxtOutput(new PrintStream(out));
// When
OutcomesTable outcomesTable = new OutcomesTable(new LocalizedKeywords(), "dd/MM/yyyy");
Date actualDate = StoryNarrator.dateFor("01/01/2011");
Date expectedDate = StoryNarrator.dateFor("02/01/2011");
outcomesTable.addOutcome("A wrong date", actualDate, new IsDateEqual(expectedDate, outcomesTable.getDateFormat()));
try {
outcomesTable.verify();
} catch (UUIDExceptionWrapper e) {
reporter.failedOutcomes("some step", ((OutcomesFailed) e.getCause()).outcomesTable());
}
// Then
String expected = "some step (FAILED)\n"
+ "(org.jbehave.core.model.OutcomesTable$OutcomesFailed)\n"
+ "|Description|Value|Matcher|Verified|\n"
+ "|A wrong date|01/01/2011|\"02/01/2011\"|No|\n";
assertThatOutputIs(out, expected);
}
@SuppressWarnings("serial")
private static class MyKnownFailure extends KnownFailure {
}
private abstract class MyStory extends JUnitStory {
}
}