@Test
  public void should_load_test_step_details_with_no_screenshot_source_from_xml_file()
      throws Exception {
    String storedReportXML =
        "<acceptance-test-run title='Should do this' name='should_do_this' steps='1' successful='1' failures='0' skipped='0' ignored='0' pending='0' result='SUCCESS'>\n"
            + "  <user-story id='net.thucydides.core.reports.integration.WhenGeneratingAnXMLReport.AUserStory' name='A user story' />\n"
            + "  <test-step result='SUCCESS'>\n"
            + "    <screenshots>"
            + "      <screenshot image='step_1.png'/>"
            + "    </screenshots>"
            + "    <description>step 1</description>\n"
            + "  </test-step>\n"
            + "</acceptance-test-run>";

    File report = temporaryDirectory.newFile("saved-report.xml");
    FileUtils.writeStringToFile(report, storedReportXML);

    Optional<TestOutcome> testOutcome = outcomeReporter.loadReportFrom(report);

    TestStep testStep = (TestStep) testOutcome.get().getTestSteps().get(0);
    assertThat(testOutcome.get().getTestSteps().size(), is(1));
    assertThat(testStep.getResult(), is(TestResult.SUCCESS));
    assertThat(testStep.getDescription(), is("step 1"));
    assertThat(testStep.getScreenshots().get(0).getScreenshotFile().getName(), is("step_1.png"));
    assertThat(testStep.getScreenshots().get(0).getSourcecode().isPresent(), is(false));
  }
  @Test
  public void should_include_the_name_of_any_screenshots_where_present() throws Exception {
    TestOutcome testOutcome = TestOutcome.forTest("a_simple_test_case", SomeTestScenario.class);
    String expectedReport =
        "<acceptance-test-run title='A simple test case' name='a_simple_test_case' steps='2' successful='1' failures='1' skipped='0' ignored='0' pending='0' result='FAILURE'>\n"
            + "  <user-story id='net.thucydides.core.reports.integration.WhenGeneratingAnXMLReport.AUserStory' name='A user story' />\n"
            + "  <test-step result='SUCCESS'>\n"
            + "    <screenshots>\n"
            + "      <screenshot image='step_1.png' source='step_1.html'/>\n"
            + "    </screenshots>\n"
            + "    <description>step 1</description>\n"
            + "  </test-step>\n"
            + "  <test-step result='FAILURE'>\n"
            + "    <description>step 2</description>\n"
            + "  </test-step>\n"
            + "</acceptance-test-run>";

    File screenshot = temporaryDirectory.newFile("step_1.png");
    File source = temporaryDirectory.newFile("step_1.html");

    TestStep step1 = TestStepFactory.successfulTestStepCalled("step 1");
    step1.addScreenshot(new ScreenshotAndHtmlSource(screenshot, source));
    testOutcome.recordStep(step1);
    testOutcome.recordStep(TestStepFactory.failingTestStepCalled("step 2"));

    File xmlReport = reporter.generateReportFor(testOutcome);
    String generatedReportText = getStringFrom(xmlReport);

    assertThat(generatedReportText, isSimilarTo(expectedReport));
  }
  @Test
  public void should_have_a_meaningful_filename() throws Exception {
    TestOutcome testOutcome = TestOutcome.forTest("a_simple_test_case", SomeTestScenario.class);

    TestStep step1 = TestStepFactory.successfulTestStepCalled("step 1");
    File screenshot = temporaryDirectory.newFile("step_1.png");
    File source = temporaryDirectory.newFile("step_1.html");
    step1.addScreenshot(new ScreenshotAndHtmlSource(screenshot, source));
    testOutcome.recordStep(step1);

    File xmlReport = reporter.generateReportFor(testOutcome);
    assertThat(xmlReport.getName(), is("a_user_story_a_simple_test_case.xml"));
  }
  @Test
  public void should_include_error_message_for_failing_test() throws Exception {
    TestOutcome testOutcome = TestOutcome.forTest("a_simple_test_case", SomeTestScenario.class);

    TestStep step = TestStepFactory.failingTestStepCalled("step 1");
    step.failedWith(new IllegalArgumentException("Oh nose!"));

    testOutcome.recordStep(step);

    File xmlReport = reporter.generateReportFor(testOutcome);
    String generatedReportText = getStringFrom(xmlReport);

    assertThat(generatedReportText, containsString("<error>Oh nose!</error>"));
  }
  @Test
  public void should_have_a_meaningful_filename() throws Exception {
    TestOutcome testOutcome = TestOutcome.forTest("should_do_this", SomeTestScenario.class);

    TestStep step1 = TestStepFactory.successfulTestStepCalled("step 1");
    File screenshot = temporaryDirectory.newFile("google_page_1.png");
    File screenshotSource = temporaryDirectory.newFile("google_page_1.html");
    step1.addScreenshot(new ScreenshotAndHtmlSource(screenshot, screenshotSource));
    testOutcome.recordStep(step1);

    File xmlReport = reporter.generateReportFor(testOutcome, allTestOutcomes);
    assertThat(
        xmlReport.getName(), is(Digest.ofTextValue("a_user_story_should_do_this") + ".html"));
  }
  @Test
  public void spaces_in_the_qualifier_are_converted_to_underscores_for_the_report_name()
      throws Exception {
    TestOutcome testOutcome = TestOutcome.forTest("should_do_this", SomeTestScenario.class);

    TestStep step1 = TestStepFactory.successfulTestStepCalled("step 1");
    File screenshot = temporaryDirectory.newFile("google_page_1.png");
    File screenshotSource = temporaryDirectory.newFile("google_page_1.html");
    step1.addScreenshot(new ScreenshotAndHtmlSource(screenshot, screenshotSource));
    testOutcome.recordStep(step1);

    reporter.setQualifier("a b c");

    File xmlReport = reporter.generateReportFor(testOutcome, allTestOutcomes);
    assertThat(
        xmlReport.getName(), is(Digest.ofTextValue("a_user_story_should_do_this_a_b_c") + ".html"));
  }
  @Test
  public void screenshots_should_have_a_separate_html_report() throws Exception {
    TestOutcome testOutcome = TestOutcome.forTest("should_do_this", SomeTestScenario.class);

    TestStep step1 = TestStepFactory.successfulTestStepCalled("step 1");
    File screenshot = temporaryDirectory.newFile("google_page_1.png");
    File screenshotSource = temporaryDirectory.newFile("google_page_1.html");
    step1.addScreenshot(new ScreenshotAndHtmlSource(screenshot, screenshotSource));
    testOutcome.recordStep(step1);

    reporter.generateReportFor(testOutcome, allTestOutcomes);

    File screenshotReport =
        new File(
            outputDirectory,
            Digest.ofTextValue("a_user_story_should_do_this") + "_screenshots.html");
    assertThat(screenshotReport.exists(), is(true));
  }
  @Test
  public void spaces_in_the_qualifer_should_be_converted_to_underscores_in_the_test_run_name()
      throws Exception {
    TestOutcome testOutcome = TestOutcome.forTest("a_simple_test_case", SomeTestScenario.class);

    TestStep step1 = TestStepFactory.successfulTestStepCalled("step 1");
    File screenshot = temporaryDirectory.newFile("step_1.png");
    File source = temporaryDirectory.newFile("step_1.html");
    step1.addScreenshot(new ScreenshotAndHtmlSource(screenshot, source));
    testOutcome.recordStep(step1);

    reporter.setQualifier("a b c");

    File xmlReport = reporter.generateReportFor(testOutcome);

    String generatedReportText = getStringFrom(xmlReport);

    assertThat(generatedReportText, containsString("name=\"a_simple_test_case_a_b_c\""));
  }
  @Test
  public void screenshot_html_should_mention_the_step_name() throws Exception {
    TestOutcome testOutcome = TestOutcome.forTest("should_do_this", SomeTestScenario.class);

    TestStep step1 = TestStepFactory.successfulTestStepCalled("step 1");
    File screenshot = temporaryDirectory.newFile("google_page_1.png");
    File screenshotSource = temporaryDirectory.newFile("google_page_1.html");
    step1.addScreenshot(new ScreenshotAndHtmlSource(screenshot, screenshotSource));
    testOutcome.recordStep(step1);

    reporter.generateReportFor(testOutcome, allTestOutcomes);

    File screenshotReport =
        new File(
            outputDirectory,
            Digest.ofTextValue("a_user_story_should_do_this") + "_screenshots.html");
    String reportContents = FileUtils.readFileToString(screenshotReport);
    assertThat(reportContents, containsString("step 1"));
  }
  private void recordTestOutcomeAsSteps(TestOutcome testOutcome, TestOutcome scenarioOutcome) {
    TestStep nestedStep =
        TestStep.forStepCalled(testOutcome.getTitle()).withResult(testOutcome.getResult());
    List<TestStep> testSteps = testOutcome.getTestSteps();

    if (testOutcome.getTestFailureCause() != null) {
      nestedStep.failedWith(testOutcome.getTestFailureCause().toException());
    }

    if (!testSteps.isEmpty()) {
      for (TestStep nextStep : testSteps) {
        nextStep.setDescription(
            normalizeTestStepDescription(
                nextStep.getDescription(), scenarioOutcome.getTestSteps().size() + 1));
        nestedStep.addChildStep(nextStep);
      }
    }
    scenarioOutcome.recordStep(nestedStep);
  }
  private void recordTestOutcomeAsSteps(TestOutcome testOutcome, TestOutcome scenarioOutcome) {
    final String name = alternativeMethodName(testOutcome);
    TestStep nestedStep = TestStep.forStepCalled(name).withResult(testOutcome.getResult());
    List<TestStep> testSteps = testOutcome.getTestSteps();

    if (testOutcome.getTestFailureCause() != null) {
      nestedStep.failedWith(testOutcome.getTestFailureCause().toException());
    }

    if (!testSteps.isEmpty()) {
      for (TestStep nextStep : testSteps) {
        nextStep.setDescription(
            normalizeTestStepDescription(
                nextStep.getDescription(), scenarioOutcome.getTestSteps().size() + 1));
        nestedStep.addChildStep(nextStep);
        nestedStep.setDuration(nextStep.getDuration() + nestedStep.getDuration());
      }
    }

    if (nestedStep.getDuration() == 0) {
      nestedStep.setDuration(testOutcome.getDuration());
    }
    scenarioOutcome.recordStep(nestedStep);
  }