Package net.thucydides.core.model

Source Code of net.thucydides.core.model.WhenRecordingNewTestOutcomes

package net.thucydides.core.model;

import com.google.common.collect.ImmutableList;
import net.thucydides.core.annotations.Issue;
import net.thucydides.core.annotations.Issues;
import net.thucydides.core.annotations.Story;
import net.thucydides.core.annotations.Title;
import net.thucydides.core.issues.IssueTracking;
import net.thucydides.core.issues.SystemPropertiesIssueTracking;
import net.thucydides.core.pages.Pages;
import net.thucydides.core.statistics.model.TestRunTag;
import net.thucydides.core.statistics.model.TestStatistics;
import net.thucydides.core.steps.ScenarioSteps;
import net.thucydides.core.steps.StepFailureException;
import net.thucydides.core.util.EnvironmentVariables;
import net.thucydides.core.util.MockEnvironmentVariables;
import org.joda.time.DateTime;
import org.junit.Assert;
import org.junit.Before;
import org.junit.ComparisonFailure;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.WebDriverException;

import java.util.Arrays;
import java.util.List;

import static ch.lambdaj.Lambda.extract;
import static ch.lambdaj.Lambda.on;
import static net.thucydides.core.matchers.ThucydidesMatchers.hasFilenames;
import static net.thucydides.core.matchers.dates.DateMatchers.isBetween;
import static net.thucydides.core.model.TestResult.*;
import static net.thucydides.core.model.TestStepFactory.*;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

public class WhenRecordingNewTestOutcomes {


    TestOutcome testOutcome;

    class AUserStory {
    }

    class SimpleTestScenario {
        @Issue("#ISSUE-123")
        public void should_do_this() {
        }

        @Issue("#ISSUE-456")
        public void should_do_that() {
        }

        public void should_do_something_else() {
        }

        @Issue("#789")
        public void should_do_some_other_thing() {
        }
    }

    @Story(AUserStory.class)
    @Issue("#ISSUE-123")
    class SomeTestScenario {
        @Issue("#ISSUE-123")
        public void should_do_this() {
        }

        @Issue("#ISSUE-456")
        public void should_do_that() {
        }

        public void should_do_something_else() {
        }

        @Issue("#789")
        public void should_do_some_other_thing() {
        }
    }

    @Story(AUserStory.class)
    @Issues({"#ISSUE-123", "#ISSUE-456"})
    class SomeOtherTestScenario {
        @Issues({"#ISSUE-123", "#ISSUE-789"})
        public void should_do_this() {
        }

        @Issue("#ISSUE-123")
        public void should_do_that() {
        }

        public void should_do_something_else() {
        }
    }

    @Story(AUserStory.class)
    class SomeAnnotatedTestScenario {
        @Title("Really should do this!")
        public void should_do_this() {
        }

        public void should_do_that() {
        }
    }

    @Story(AUserStory.class)
    class SomeAnnotatedTestScenarioWithAnIssue {
        @Title("Really should do this! (#ISSUE-123)")
        public void should_do_this() {
        }

        public void should_do_that() {
        }
    }

    @Story(AUserStory.class)
    class SomeAnnotatedTestScenarioWithManyIssues {
        @Issue("#ISSUE-456")
        @Issues({"#ISSUE-100", "#ISSUE-200"})
        @Title("Really should do this! (#ISSUE-123)")
        public void should_do_this() {
        }

        public void should_do_that() {
        }
    }

    @Story(AUserStory.class)
    @Issue("#ISSUE-100")
    class SomeAnnotatedTestScenarioWithDuplicatedIssues {
        @Issues({"#ISSUE-100", "#ISSUE-200"})
        public void should_do_this() {
        }

        public void should_do_that() {
        }
    }

    @Story(AUserStory.class)
    @Issue("#123")
    class ATestScenarioWithIssuesWithNoPrefix {
        public void should_do_this() {
        }

        @Issue("#456")
        public void should_do_that() {
        }

        public void should_do_something_else() {
        }
    }

    @Before
    public void prepareAcceptanceTestRun() {
        MockitoAnnotations.initMocks(this);
        testOutcome = TestOutcome.forTest("should_do_this", SomeTestScenario.class);
    }

    @Test
    public void a_test_outcome_can_be_initialized_directly_from_a_story() {
        testOutcome = TestOutcome.forTest("should_do_this", AUserStory.class);

        Assert.assertThat(testOutcome.getUserStory().getName(), is("A user story"));
    }

    @Test
    public void a_test_outcome_should_record_the_tested_method_name() {
        TestOutcome outcome = TestOutcome.forTest("should_do_this", SomeTestScenario.class);

        assertThat(outcome.getMethodName(), is("should_do_this"));
    }

    @Test
    public void should_report_failures_or_errors_outside_of_steps() {
        TestOutcome outcome = TestOutcome.forTest("should_do_this", SomeTestScenario.class);
        outcome.recordStep(forASuccessfulTestStepCalled("The user opens the Google search page"));

        assertThat(outcome.hasNonStepFailure(), is(false));
        outcome.determineTestFailureCause(new AssertionError("test failed"));
        assertThat(outcome.hasNonStepFailure(), is(true));
    }

    @Test
    public void a_test_outcome_should_record_the_start_time() {
        DateTime beforeDate = DateTime.now();
        TestOutcome outcome = TestOutcome.forTest("should_do_this", SomeTestScenario.class);
        DateTime afterDate = DateTime.now();
        assertThat(outcome.getStartTime(), isBetween(beforeDate, afterDate));
    }

    /**
     * Case for JUnit integration, where a test case is present.
     */
    @Test
    public void a_test_outcome_title_should_be_based_on_the_tested_method_name_if_defined() {
        TestOutcome outcome = TestOutcome.forTest("should_do_this", SomeTestScenario.class);

        assertThat(outcome.getTitle(), is("Should do this"));
    }

    @Test
    public void a_qualified_test_outcome_title_should_be_based_on_the_tested_method_name_with_a_qualifier() {
        TestOutcome outcome = TestOutcome.forTest("should_do_this", SomeTestScenario.class);

        TestOutcome qualifiedQutcome = outcome.withQualifier("with-this-value");
        assertThat(qualifiedQutcome.getTitle(), is("Should do this [with-this-value]"));
    }

    @Test
    public void a_test_outcome_title_can_be_overriden_using_the_Title_annotation() {
        TestOutcome outcome = TestOutcome.forTest("should_do_this", SomeAnnotatedTestScenario.class);

        assertThat(outcome.getTitle(), is("Really should do this!"));
    }


    @Test
    public void a_test_outcome_result_can_be_overridden() {
        TestOutcome outcome = TestOutcome.forTest("should_do_this", SomeAnnotatedTestScenario.class);
        outcome.setAnnotatedResult(TestResult.IGNORED);

        assertThat(outcome.getResult(), is(TestResult.IGNORED));
    }

    @Test
    public void once_a_test_outcome_result_is_marked_pending_it_cannot_be_redefinedn() {
        TestOutcome outcome = TestOutcome.forTest("should_do_this", SomeAnnotatedTestScenario.class);
        outcome.setAnnotatedResult(TestResult.PENDING);
        outcome.setAnnotatedResult(TestResult.IGNORED);

        assertThat(outcome.getResult(), is(TestResult.PENDING));
    }

    @Test
    public void a_qualified_test_outcome_title_should_contain_the_qualifier() {
        TestOutcome outcome = TestOutcome.forTest("should_do_this", SomeAnnotatedTestScenario.class);
        TestOutcome qualifiedQutcome = outcome.withQualifier("with-this-value");
        assertThat(qualifiedQutcome.getTitle(), is("Really should do this! [with-this-value]"));
    }

    @Test
    public void a_test_outcome_should_record_issue_numbers_from_the_Issue_annotation() {
        TestOutcome outcome = TestOutcome.forTest("should_do_this", SomeTestScenario.class);

        assertThat(outcome.getIssues(), hasItem("#ISSUE-123"));
    }

    @Test
    public void a_test_outcome_should_record_issue_keys_using_the_project_key_if_not_provided() {
        TestOutcome outcome = TestOutcome.forTest("should_do_some_other_thing", SomeTestScenario.class);
        EnvironmentVariables environmentVariables = new MockEnvironmentVariables();

        environmentVariables.setProperty("thucydides.project.key", "ISSUE");
        outcome.setEnvironmentVariables(environmentVariables);


        assertThat(outcome.getIssueKeys(), hasItem("ISSUE-789"));
    }

    @Test
    public void a_test_outcome_should_record_issue_keys_without_the_hash_prefix() {
        TestOutcome outcome = TestOutcome.forTest("should_do_this", SomeTestScenario.class);

        assertThat(outcome.getIssueKeys(), hasItem("ISSUE-123"));
    }

    @Test
    public void a_test_outcome_can_have_no_issues() {
        TestOutcome outcome = TestOutcome.forTest("should_do_this", SomeAnnotatedTestScenario.class);

        assertThat(outcome.getIssues().size(), is(0));
    }

    @Test
    public void a_test_outcome_can_be_associated_with_an_issue() {
        TestOutcome outcome = TestOutcome.forTest("should_do_this", SomeAnnotatedTestScenario.class);

        outcome.isRelatedToIssue("#ISSUE-999");
        outcome.isRelatedToIssue("#ISSUE-000");
        assertThat(outcome.getIssues(), hasItems("#ISSUE-000", "#ISSUE-999"));
    }

    @Mock
    IssueTracking issueTracking;

    @Test
    public void the_test_outcome_title_should_contain_links_to_the_issues() {
        when(issueTracking.getIssueTrackerUrl()).thenReturn("http://my.issue.tracker/MY-PROJECT/browse/ISSUE-{0}");
        TestOutcome outcome = TestOutcome.forTest("should_do_this", SomeAnnotatedTestScenarioWithAnIssue.class).usingIssueTracking(issueTracking);

        assertThat(outcome.getTitleWithLinks() , is("Really should do this! (#<a target=\"_blank\" href=\"http://my.issue.tracker/MY-PROJECT/browse/ISSUE-ISSUE-123\">ISSUE-123</a>)"));
    }



    @Test
    public void should_be_able_to_add_extra_issues() {
        TestOutcome outcome = TestOutcome.forTest("should_do_this", SomeTestScenario.class);
        List<String> extraIssues = Arrays.asList("#ISSUE-456", "#ISSUE-789");
        outcome.addIssues(extraIssues);
        assertThat(outcome.getIssues(), hasItems("#ISSUE-123", "#ISSUE-456", "#ISSUE-789"));
    }

    @Test
    public void a_test_outcome_should_not_inject_issue__links_from_the_Issue_annotation_if_not_configured() {
        TestOutcome outcome = TestOutcome.forTest("should_do_this", SomeTestScenario.class);

        assertThat(outcome.getFormattedIssues(), is("(#ISSUE-123)"));
    }

    @Test
    public void a_test_outcome_should_know_what_issues_there_are() {
        TestOutcome outcome = TestOutcome.forTest("should_do_this", SomeTestScenario.class);

        assertThat(outcome.getIssues(), hasItem("#ISSUE-123"));
    }

    @Test
    public void a_test_outcome_should_know_what_issues_there_are_in_the_title() {
        TestOutcome outcome = TestOutcome.forTest("should_do_this", SomeAnnotatedTestScenarioWithAnIssue.class);

        assertThat(outcome.getIssues(), hasItem("#ISSUE-123"));
    }


    @Test
    public void should_find_all_the_issues_in_a_test() {
        TestOutcome outcome = TestOutcome.forTest("should_do_this", SomeAnnotatedTestScenarioWithManyIssues.class);

        assertThat(outcome.getIssues(), hasItems("#ISSUE-123", "#ISSUE-456", "#ISSUE-100", "#ISSUE-200"));
    }


    @Test
    public void a_test_outcome_should_inject_issue_links_from_the_Issue_annotation_if_requested() {
        MockEnvironmentVariables environmentVariables = new MockEnvironmentVariables();
        environmentVariables.setProperty("jira.url", "http://my.jira");
        IssueTracking issueTracking = new SystemPropertiesIssueTracking(environmentVariables);

        TestOutcome outcome = TestOutcome.forTest("should_do_this", SomeTestScenario.class)
                .usingIssueTracking(issueTracking);

        assertThat(outcome.getFormattedIssues(), is("(#<a target=\"_blank\" href=\"http://my.jira/browse/ISSUE-123\">ISSUE-123</a>)"));
    }

    @Test
    public void a_test_outcome_should_inject_multiple__issue_links_from_the_Issue_annotation_if_requested() {
        MockEnvironmentVariables environmentVariables = new MockEnvironmentVariables();
        environmentVariables.setProperty("jira.url", "http://my.jira");
        IssueTracking issueTracking = new SystemPropertiesIssueTracking(environmentVariables);

        TestOutcome outcome = TestOutcome.forTest("should_do_this", SomeOtherTestScenario.class)
                .usingIssueTracking(issueTracking);

        assertThat(outcome.getFormattedIssues(), is("(#<a target=\"_blank\" href=\"http://my.jira/browse/ISSUE-123\">ISSUE-123</a>, #<a target=\"_blank\" href=\"http://my.jira/browse/ISSUE-456\">ISSUE-456</a>, #<a target=\"_blank\" href=\"http://my.jira/browse/ISSUE-789\">ISSUE-789</a>)"));
    }


    @Test
    public void a_test_outcome_should_also_inject_issue_links_from_the_Issue_annotation_at_the_class_level() {
        TestOutcome outcome = TestOutcome.forTest("should_do_that", SomeTestScenario.class);

        assertThat(outcome.getFormattedIssues(), is("(#ISSUE-123, #ISSUE-456)"));
    }

    @Test
    public void a_test_outcome_should_record_multiple_issues() {
        TestOutcome outcome = TestOutcome.forTest("should_do_this", SomeOtherTestScenario.class);

        assertThat(outcome.getFormattedIssues(), is("(#ISSUE-123, #ISSUE-456, #ISSUE-789)"));
    }

    @Test
    public void a_test_outcome_should_record_multiple_issues_and_single_issues() {
        TestOutcome outcome = TestOutcome.forTest("should_do_that", SomeOtherTestScenario.class);

        assertThat(outcome.getFormattedIssues(), is("(#ISSUE-123, #ISSUE-456)"));
    }

    @Test
    public void a_test_outcome_should_record_multiple_issues_at_class_level() {
        TestOutcome outcome = TestOutcome.forTest("should_do_something_else", SomeOtherTestScenario.class);

        assertThat(outcome.getFormattedIssues(), is("(#ISSUE-123, #ISSUE-456)"));
    }

    @Test
    public void a_test_outcome_should_also_inject_issue_links_from_the_Issue_annotation_when_only_at_the_class_level() {
        TestOutcome outcome = TestOutcome.forTest("should_do_something_else", SomeTestScenario.class);

        assertThat(outcome.getFormattedIssues(), is("(#ISSUE-123)"));
    }


    @Test
    public void the_test_outcome_formatted_issues_should_contain_unique_links_to_duplicated_issues() {
        when(issueTracking.getIssueTrackerUrl()).thenReturn("http://my.issue.tracker/MY-PROJECT/browse/{0}");
        TestOutcome outcome = TestOutcome.forTest("should_do_this", SomeAnnotatedTestScenarioWithDuplicatedIssues.class).usingIssueTracking(issueTracking);

        assertThat(outcome.getFormattedIssues() , is("(#<a target=\"_blank\" href=\"http://my.issue.tracker/MY-PROJECT/browse/ISSUE-100\">ISSUE-100</a>, #<a target=\"_blank\" href=\"http://my.issue.tracker/MY-PROJECT/browse/ISSUE-200\">ISSUE-200</a>)"));
    }

    @Test
    public void a_test_outcome_title_can_be_overriden_manually() {
        TestOutcome outcome = TestOutcome.forTest("should_do_this", SomeTestScenario.class);
        outcome.setTitle("My custom title");
        assertThat(outcome.getTitle(), is("My custom title"));
    }

    @Test
    public void a_test_outcome_title_can_be_overriden_manually_even_with_an_annotation() {
        TestOutcome outcome = TestOutcome.forTest("should_do_this", SomeAnnotatedTestScenario.class);
        outcome.setTitle("My custom title");
        assertThat(outcome.getTitle(), is("My custom title"));
    }

    /**
     * Case for easyb integration, where we use a Story class directly.
     */
    @Test
    public void a_test_outcome_title_should_be_the_method_name_if_no_test_class_is_defined() {
        net.thucydides.core.model.Story story = net.thucydides.core.model.Story.from(AUserStory.class);

        TestOutcome outcome = TestOutcome.forTestInStory("Some scenario", story);

        assertThat(outcome.getTitle(), is("Some scenario"));
    }


    @Test
    public void should_record_simple_test_steps() {

        assertThat(testOutcome.getTestSteps().size(), is(0));

        testOutcome.recordStep(forASuccessfulTestStepCalled("The user opens the Google search page"));
        testOutcome.recordStep(forASuccessfulTestStepCalled("The user searches for Cats"));

        assertThat(testOutcome.getTestSteps().toString(),
                is("[The user opens the Google search page, The user searches for Cats]"));
    }

    @Test
    public void should_record_nested_test_steps() {

        testOutcome.recordSteps(ImmutableList.of(forASuccessfulTestStepCalled("Step 1"),forASuccessfulTestStepCalled("Step 2")));
        testOutcome.startGroup();
        testOutcome.recordSteps(ImmutableList.of(forASuccessfulTestStepCalled("Step 2.1"),forASuccessfulTestStepCalled("Step 2.2")));
        testOutcome.endGroup();
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 3"));

        assertThat(testOutcome.getTestSteps().toString(),
                is("[Step 1, Step 2 [Step 2.1, Step 2.2], Step 3]"));
    }

    @Test
    public void should_record_deeply_nested_test_steps() {

        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 1"));
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 2"));
        testOutcome.startGroup();
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 2.1"));
        testOutcome.startGroup();
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 2.1.1"));
        testOutcome.startGroup();
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 2.1.1.1"));
        testOutcome.endGroup();
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 2.1.2"));
        testOutcome.endGroup();
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 2.2"));
        testOutcome.endGroup();
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 3"));

        assertThat(testOutcome.getTestSteps().toString(),
                is("[Step 1, Step 2 [Step 2.1 [Step 2.1.1 [Step 2.1.1.1], Step 2.1.2], Step 2.2], Step 3]"));
    }

    @Test
    public void should_count_test_steps() {

        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 1"));
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 2"));
        testOutcome.startGroup();
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 2.1"));
        testOutcome.startGroup();
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 2.1.1"));
        testOutcome.startGroup();
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 2.1.1.1"));
        testOutcome.endGroup();
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 2.1.2"));
        testOutcome.endGroup();
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 2.2"));
        testOutcome.endGroup();
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 3"));

        assertThat(testOutcome.getStepCount(), is(3));
    }

    @Test
    public void should_count_deeply_nested_test_steps() {
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 1"));
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 2"));
        testOutcome.startGroup();
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 2.1"));
        testOutcome.startGroup();
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 2.1.1"));
        testOutcome.startGroup();
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 2.1.1.1"));
        testOutcome.endGroup();
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 2.1.2"));
        testOutcome.endGroup();
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 2.2"));
        testOutcome.endGroup();
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 3"));

        assertThat(testOutcome.getNestedStepCount(), is(8));
    }

    @Test
    public void the_returned_test_steps_list_should_be_read_only() {
        testOutcome.recordStep(forASuccessfulTestStepCalled("The user opens the Google search page"));

        List<TestStep> testSteps = testOutcome.getTestSteps();
        assertThat(testOutcome.toString(), is("Should do this:The user opens the Google search page"));

        try {
            testSteps.add(new TestStep("Some other step"));
            fail("An UnsupportedOperationException exception should have been thrown");
        } catch (UnsupportedOperationException e) {
            assertThat(testOutcome.toString(), is("Should do this:The user opens the Google search page"));
        }
    }

    @Test
    public void the_acceptance_test_case_is_successful_if_all_the_tests_are_successful() {
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 1"));
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 2"));
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 3"));

        assertThat(testOutcome.getResult(), is(SUCCESS));
        assertThat(testOutcome.isSuccess(), is(true));
    }

    @Test
    public void a_test_case_with_no_steps_should_be_considered_successful_if_no_exceptions_occur() {
        assertThat(testOutcome.getResult(), is(SUCCESS));
        assertThat(testOutcome.isSuccess(), is(true));
        assertThat(testOutcome.isPending(), is(false));

    }

    @Test
    public void should_list_screenshots_in_steps() {
        testOutcome.recordStep(forASuccessfulTestStepCalled("step_1"));
        testOutcome.recordStep(forASuccessfulTestStepCalled("step_2"));
        testOutcome.recordStep(forASuccessfulTestStepCalled("step_3"));

        assertThat(testOutcome.getScreenshots(), hasFilenames("step_1.png", "step_2.png", "step_3.png"));
    }

    @Test
    public void should_know_if_an_outcome_has_screenshots() {
        testOutcome.recordStep(forASuccessfulTestStepCalled("step_1"));
        testOutcome.recordStep(forASuccessfulTestStepCalled("step_2"));
        testOutcome.recordStep(forASuccessfulTestStepCalled("step_3"));

        assertThat(testOutcome.hasScreenshots(), is(true));
    }

    @Test
    public void should_list_screenshots_for_leaf_steps_in_nested_steps() {
        testOutcome.recordStep(forASuccessfulTestStepCalled("step_1"));
        testOutcome.recordStep(forASuccessfulTestStepCalled("step_2"));
        testOutcome.startGroup();
        testOutcome.recordStep(forASuccessfulTestStepCalled("step_2.1"));
        testOutcome.startGroup();
        testOutcome.recordStep(forASuccessfulTestStepCalled("step_2.1.1"));
        testOutcome.startGroup();
        testOutcome.recordStep(forASuccessfulTestStepCalled("step_2.1.1.1"));
        testOutcome.endGroup();
        testOutcome.recordStep(forASuccessfulTestStepCalled("step_2.1.2"));
        testOutcome.endGroup();
        testOutcome.recordStep(forASuccessfulTestStepCalled("step_2.2"));
        testOutcome.endGroup();
        testOutcome.recordStep(forASuccessfulTestStepCalled("step_3"));

        List<String> screenshots = extract(testOutcome.getScreenshots(), on(Screenshot.class).getFilename());
        assertThat(screenshots, hasItems("step_1.png", "step_2.1.1.1.png",
                "step_2.1.2.png", "step_2.2.png", "step_3.png"));
    }

    @Test
    public void a_screenshot_without_an_error_message__returns_an_empty_string() {
        Screenshot screenshot = new Screenshot("step_1.png", "Step 1", 800);
        assertThat(screenshot.getErrorMessage(), is(""));
    }

    @Test
    public void a_failing_screenshot_records_the_error_message() {
        Screenshot screenshot = new Screenshot("step_1.png", "Step 1", 800, new FailureCause(new AssertionError("Element not found")));
        assertThat(screenshot.getErrorMessage(), is("Element not found"));
    }

    @Test
    public void a_failing_step_should_the_error_message_for_errors_with_complex_constructors() {
        Screenshot screenshot = new Screenshot("step_1.png", "Step 1", 800, new FailureCause(new ComparisonFailure("oh crap", "a","b")));
        assertThat(screenshot.getError().getMessage(), is("oh crap expected:<[a]> but was:<[b]>"));
        assertThat(screenshot.getError().getStackTrace().length, is(greaterThan(0)));
    }

    @Test
    public void the_acceptance_test_case_is_a_failure_if_one_test_has_failed() {

        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 1"));
        testOutcome.recordStep(forABrokenTestStepCalled("Step 2", new AssertionError("Oh bother!")));
        testOutcome.recordStep(forASkippedTestStepCalled("Step 3"));

        assertThat(testOutcome.getResult(), is(FAILURE));
        assertThat(testOutcome.isFailure(), is(true));
    }

    @Test
    public void the_acceptance_test_case_is_an_error_if_one_test_has_thrown_a_non_assertion_exception() {

        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 1"));
        testOutcome.recordStep(forABrokenTestStepCalled("Step 2", new WebDriverException("Oh bother!")));
        testOutcome.recordStep(forASkippedTestStepCalled("Step 3"));

        assertThat(testOutcome.getResult(), is(ERROR));
        assertThat(testOutcome.isError(), is(true));
    }

    @Test
    public void if_a_step_fails_the_error_message_should_be_returned_with_the_result() {

        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 1"));
        testOutcome.recordStep(forABrokenTestStepCalled("Step 2", new AssertionError("Oh bother!")));
        testOutcome.recordStep(forASkippedTestStepCalled("Step 3"));


        TestStep failingStep = testOutcome.getTestSteps().get(1);
        assertThat(failingStep.getErrorMessage(), is("Oh bother!"));
    }

    @Test
    public void the_acceptance_test_case_is_failing_if_multiple_tests_have_failed() {

        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 1"));
        testOutcome.recordStep(forABrokenTestStepCalled("Step 2", new AssertionError("Oh bother!")));
        testOutcome.recordStep(forABrokenTestStepCalled("Step 3", new AssertionError("Oh bother!")));
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 4"));

        assertThat(testOutcome.getResult(), is(FAILURE));
    }

    @Test
    public void the_acceptance_test_case_is_failing_if_a_test_step_failed() {

        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 1"));
        testOutcome.recordStep(forABrokenTestStepCalled("Step 2", new StepFailureException("Oh bother",new AssertionError("Oh bother!"))));
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 4"));

        assertThat(testOutcome.getResult(), is(FAILURE));
    }

    @Test
    public void the_acceptance_test_case_is_in_error_if_a_test_step_has_an_error() {

        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 1"));
        testOutcome.recordStep(forABrokenTestStepCalled("Step 2", new StepFailureException("Oh bother",new NoSuchElementException("Can't find element"))));
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 4"));

        assertThat(testOutcome.getResult(), is(ERROR));
    }

    @Test
    public void the_acceptance_test_case_is_in_error_if_multiple_tests_have_failed_or_are_broken() {

        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 1"));
        testOutcome.recordStep(forABrokenTestStepCalled("Step 2", new AssertionError("Oh bother!")));
        testOutcome.recordStep(forABrokenTestStepCalled("Step 3", new WebDriverException("Oh deary me!")));
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 4"));

        assertThat(testOutcome.getResult(), is(ERROR));
    }

    @Test
    public void the_acceptance_test_case_is_pending_if_at_least_one_test_is_pending_and_none_have_failed() {

        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 1"));
        testOutcome.recordStep(forAPendingTestStepCalled("Step 2"));
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 3"));
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 4"));

        assertThat(testOutcome.getResult(), is(PENDING));
    }

    @Test
    public void the_acceptance_test_case_is_failing_if_there_is_a_failure_even_with_pending_test_cases() {

        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 1"));
        testOutcome.recordStep(forAPendingTestStepCalled("Step 2"));
        testOutcome.recordStep(forABrokenTestStepCalled("Step 3", new AssertionError("Oh bother!")));
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 4"));

        assertThat(testOutcome.getResult(), is(FAILURE));
    }

    @Test
    public void the_acceptance_test_case_is_ignored_if_all_test_cases_are_ignored() {

        testOutcome.recordStep(forAnIgnoredTestStepCalled("Step 1"));
        testOutcome.recordStep(forAnIgnoredTestStepCalled("Step 2"));
        testOutcome.recordStep(forAnIgnoredTestStepCalled("Step 3"));
        testOutcome.recordStep(forAnIgnoredTestStepCalled("Step 4"));

        assertThat(testOutcome.getResult(), is(IGNORED));
    }

    @Test
    public void if_one_test_is_ignored_among_others_it_will_not_affect_the_outcome_for_failing_tests() {

        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 1"));
        testOutcome.recordStep(forAPendingTestStepCalled("Step 2"));
        testOutcome.recordStep(forABrokenTestStepCalled("Step 3", new AssertionError("Oh bother!")));
        testOutcome.recordStep(forAnIgnoredTestStepCalled("Step 4"));
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 5"));

        assertThat(testOutcome.getResult(), is(FAILURE));
    }

    @Test
    public void if_one_test_is_ignored_among_others_it_will_not_affect_the_outcome_for_pending_tests() {

        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 1"));
        testOutcome.recordStep(forAPendingTestStepCalled("Step 2"));
        testOutcome.recordStep(forABrokenTestStepCalled("Step 3", new AssertionError("Oh bother!")));
        testOutcome.recordStep(forAnIgnoredTestStepCalled("Step 4"));
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 5"));
        testOutcome.recordStep(forAPendingTestStepCalled("Step 6"));

        assertThat(testOutcome.getResult(), is(FAILURE));
    }

    @Test
    public void if_one_test_is_ignored_among_others_it_will_not_affect_the_outcome_for_successful_tests() {

        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 1"));
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 2"));
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 3"));
        testOutcome.recordStep(forAnIgnoredTestStepCalled("Step 4"));

        assertThat(testOutcome.getResult(), is(SUCCESS));
    }

    @Test
    public void the_model_should_provide_the_number_of_successful_test_steps() {

        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 1"));
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 2"));
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 3"));

        assertThat(testOutcome.getSuccessCount(), is(3));
    }

    @Test
    public void the_model_should_provide_the_number_of_successful_test_steps_in_presence_of_other_outcomes() {

        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 1"));
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 2"));
        testOutcome.recordStep(forAnIgnoredTestStepCalled("Step 3"));
        testOutcome.recordStep(forABrokenTestStepCalled("Step 4", new AssertionError("Oh bother!")));
        testOutcome.recordStep(forASkippedTestStepCalled("Step 5"));

        assertThat(testOutcome.getSuccessCount(), is(2));
    }

    @Test
    public void the_model_should_provide_the_number_of_failed_test_steps() {

        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 1"));
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 2"));
        testOutcome.recordStep(forAnIgnoredTestStepCalled("Step 3"));
        testOutcome.recordStep(forABrokenTestStepCalled("Step 4", new AssertionError("Oh bother!")));
        testOutcome.recordStep(forABrokenTestStepCalled("Step 5", new AssertionError("Oh bother!")));
        testOutcome.recordStep(forASkippedTestStepCalled("Step 6"));

        assertThat(testOutcome.getFailureCount(), is(2));
    }

    @Test
    public void the_model_should_provide_the_number_of_ignored_test_steps() {

        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 1"));
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 2"));
        testOutcome.recordStep(forAnIgnoredTestStepCalled("Step 3"));
        testOutcome.recordStep(forABrokenTestStepCalled("Step 4", new AssertionError("Oh bother!")));
        testOutcome.recordStep(forABrokenTestStepCalled("Step 5", new AssertionError("Oh bother!")));
        testOutcome.recordStep(forASkippedTestStepCalled("Step 6"));
        testOutcome.recordStep(forASkippedTestStepCalled("Step 7"));
        testOutcome.recordStep(forASkippedTestStepCalled("Step 8"));
        testOutcome.recordStep(forASkippedTestStepCalled("Step 9"));

        assertThat(testOutcome.getIgnoredCount(), is(1));
    }

    @Test
    public void the_model_should_provide_the_number_of_skipped_test_steps() {

        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 1"));
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 2"));
        testOutcome.recordStep(forAnIgnoredTestStepCalled("Step 3"));
        testOutcome.recordStep(forABrokenTestStepCalled("Step 4", new AssertionError("Oh bother!")));
        testOutcome.recordStep(forABrokenTestStepCalled("Step 5", new AssertionError("Oh bother!")));
        testOutcome.recordStep(forASkippedTestStepCalled("Step 6"));
        testOutcome.recordStep(forASkippedTestStepCalled("Step 7"));
        testOutcome.recordStep(forASkippedTestStepCalled("Step 8"));
        testOutcome.recordStep(forASkippedTestStepCalled("Step 9"));

        assertThat(testOutcome.getSkippedCount(), is(4));
        assertThat(testOutcome.getSkippedOrIgnoredCount(), is(5));
    }

    @Test
    public void the_model_should_provide_the_number_of_pending_test_steps() {

        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 1"));
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 2"));
        testOutcome.recordStep(forAnIgnoredTestStepCalled("Step 3"));
        testOutcome.recordStep(forABrokenTestStepCalled("Step 4", new AssertionError("Oh bother!")));
        testOutcome.recordStep(forABrokenTestStepCalled("Step 5", new AssertionError("Oh bother!")));
        testOutcome.recordStep(forASkippedTestStepCalled("Step 6"));
        testOutcome.recordStep(forAPendingTestStepCalled("Step 7"));
        testOutcome.recordStep(forAPendingTestStepCalled("Step 8"));
        testOutcome.recordStep(forAPendingTestStepCalled("Step 9"));

        assertThat(testOutcome.getPendingCount(), is(3));
    }


    @Test
    public void a_test_run_with_only_successful_tests_is_successful() {

        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 1"));
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 2"));
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 3"));

        assertThat(testOutcome.getResult(), is(TestResult.SUCCESS));
    }

    @Test
    public void an_acceptance_test_run_can_contain_steps_nested_in_step_groups() {
        testOutcome.recordStep(forASuccessfulTestStepCalled("A Group"));
        testOutcome.startGroup();
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 1"));
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 2"));
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 3"));
        testOutcome.endGroup();

        assertThat(testOutcome.getTestSteps().size(), is(1));
    }


    private void createNestedTestSteps() {
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 0"));
        testOutcome.recordStep(forASuccessfulTestStepCalled("A group"));
        testOutcome.startGroup();
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 1"));
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 2"));
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 3"));
        testOutcome.recordStep(forASuccessfulTestStepCalled("Another group"));
        testOutcome.startGroup();
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 4"));
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 5"));
        testOutcome.endGroup();
        testOutcome.endGroup();
    }

    @Test
    public void an_acceptance_test_run_can_contain_step_groups_nested_in_step_groups() {
        createNestedTestSteps();
        assertThat(testOutcome.getTestSteps().size(), is(2));
    }

    @Test
    public void when_test_steps_are_nested_step_count_should_include_all_steps() {
        createNestedTestSteps();
        assertThat(testOutcome.countTestSteps(), is(6));
    }

    @Test
    public void an_acceptance_test_run_can_count_all_the_successful_nested_test_steps() {
        createNestedTestRun();
        assertThat(testOutcome.getSuccessCount(), is(6));
    }

    @Test
    public void an_acceptance_test_run_can_count_all_the_failing_nested_test_steps() {
        createNestedTestRun();

        assertThat(testOutcome.getFailureCount(), is(3));
    }

    @Test
    public void an_acceptance_test_run_can_count_all_the_pending_nested_test_steps() {
        createNestedTestRun();

        assertThat(testOutcome.getPendingCount(), is(4));
    }

    @Test
    public void an_acceptance_test_run_can_count_all_the_ignored_nested_test_steps() {
        createNestedTestRun();

        assertThat(testOutcome.getIgnoredCount(), is(1));
    }

    @Test
    public void an_acceptance_test_run_can_count_all_the_skipped_test_steps() {
        createNestedTestRun();

        assertThat(testOutcome.getSkippedCount(), is(1));
    }

    private void createNestedTestRun() {
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 0"));
        testOutcome.recordStep(forASuccessfulTestStepCalled("A group"));
        testOutcome.startGroup();
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 1"));
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 2"));
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 3"));
        testOutcome.recordStep(forABrokenTestStepCalled("Step 7", new AssertionError("Oh bother!")));
        testOutcome.recordStep(forAPendingTestStepCalled("Step 10"));
        testOutcome.recordStep(forASuccessfulTestStepCalled("Another group"));
        testOutcome.startGroup();
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 4"));
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 5"));
        testOutcome.recordStep(forAnIgnoredTestStepCalled("Step 6"));
        testOutcome.recordStep(forABrokenTestStepCalled("Step 7", new AssertionError("Oh bother!")));
        testOutcome.recordStep(forABrokenTestStepCalled("Step 8", new AssertionError("Oh bother!")));
        testOutcome.recordStep(forASkippedTestStepCalled("Step 9"));
        testOutcome.recordStep(forAPendingTestStepCalled("Step 10"));
        testOutcome.recordStep(forAPendingTestStepCalled("Step 11"));
        testOutcome.recordStep(forAPendingTestStepCalled("Step 12"));
        testOutcome.endGroup();
        testOutcome.endGroup();
    }

    @Test
    public void a_test_group_with_only_successful_tests_is_successful() {

        testOutcome.recordStep(forASuccessfulTestStepCalled("A group"));
        testOutcome.startGroup();
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 1"));
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 2"));
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 3"));
        testOutcome.endGroup();

        TestStep aGroup = testOutcome.getTestSteps().get(0);
        assertThat(aGroup.getResult(), is(TestResult.SUCCESS));
    }


    @Test
    public void a_test_group_with_a_failing_test_fails() {

        testOutcome.startGroup("A group");
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 1"));
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 2"));
        testOutcome.recordStep(forABrokenTestStepCalled("Step 3", new AssertionError("Oh bother!")));
        testOutcome.recordStep(forASkippedTestStepCalled("Step 4"));
        testOutcome.recordStep(forAnIgnoredTestStepCalled("Step 5"));
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 4"));
        testOutcome.endGroup();

        TestStep aGroup = testOutcome.getTestSteps().get(0);
        assertThat(aGroup.getResult(), is(TestResult.FAILURE));
    }


    @Test
    public void a_test_group_with_a_pending_test_is_pending() {

        testOutcome.startGroup("A group");
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 1"));
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 2"));
        testOutcome.recordStep(forAPendingTestStepCalled("Step 3"));
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 4"));
        testOutcome.endGroup();

        TestStep aGroup = testOutcome.getTestSteps().get(0);
        assertThat(aGroup.getResult(), is(TestResult.PENDING));
    }

    @Test
    public void a_test_group_with_only_ignored_tests_is_ignored() {

        testOutcome.startGroup("A group");
        testOutcome.recordStep(forAnIgnoredTestStepCalled("Step 1"));
        testOutcome.recordStep(forAnIgnoredTestStepCalled("Step 2"));
        testOutcome.recordStep(forAnIgnoredTestStepCalled("Step 3"));
        testOutcome.endGroup();
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 4"));

        TestStep aGroup = testOutcome.getTestSteps().get(0);
        assertThat(aGroup.getResult(), is(TestResult.IGNORED));
    }

    @Test
    public void a_test_run_with_a_nested_group_containing_a_failure_is_a_failure() {
        testOutcome.startGroup("A group");
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 1"));
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 2"));
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 3"));
        testOutcome.startGroup("Another group");
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 4"));
        testOutcome.recordStep(forABrokenTestStepCalled("Step 5", new AssertionError("Oh bother!")));
        testOutcome.endGroup();
        testOutcome.endGroup();

        assertThat(testOutcome.getResult(), is(TestResult.FAILURE));
    }

    @Test
    public void a_test_group_with_a_nested_group_containing_a_failure_is_a_failure() {
        testOutcome.startGroup("A group");
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 1"));
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 2"));
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 3"));
        testOutcome.startGroup("Another group");
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 4"));
        testOutcome.recordStep(forABrokenTestStepCalled("Step 5", new AssertionError("Oh bother!")));
        testOutcome.endGroup();
        testOutcome.endGroup();

        TestStep aGroup = testOutcome.getTestSteps().get(0);
        assertThat(aGroup.getResult(), is(TestResult.FAILURE));
    }

    class MyApp {
        class MyUserStory {
        }
    }

    @Test
    public void an_acceptance_test_relates_to_a_user_story() {
        net.thucydides.core.model.Story story = net.thucydides.core.model.Story.from(MyApp.MyUserStory.class);
        TestOutcome testOutcome = TestOutcome.forTestInStory("some_test", story);

        assertThat(testOutcome.getUserStory().getName(), is("My user story"));
    }

    @Test
    public void an_acceptance_test_title_is_the_title_of_the_user_story() {
        net.thucydides.core.model.Story story = net.thucydides.core.model.Story.from(MyApp.MyUserStory.class);
        TestOutcome testOutcome = TestOutcome.forTestInStory("some_test", story);

        assertThat(testOutcome.getStoryTitle(), is("My user story"));
    }

    @Test
    public void the_complete_test_name_should_include_the_story_and_the_method_name() {
        net.thucydides.core.model.Story story = net.thucydides.core.model.Story.from(MyApp.MyUserStory.class);
        TestOutcome testOutcome = TestOutcome.forTestInStory("some_test", story);
        assertThat(testOutcome.getCompleteName(), is("My user story:some_test"));
    }

    @Test
    public void the_complete_test_name_should_include_the_test_case_if_defined_and_the_method_name() {
        TestOutcome testOutcome = TestOutcome.forTest("should_do_this", SimpleTestScenario.class);
        assertThat(testOutcome.getCompleteName(), is("Simple test scenario:should_do_this"));
    }

    @Test
    public void an_acceptance_test_records_the_original_story_class() {
        net.thucydides.core.model.Story story = net.thucydides.core.model.Story.from(MyApp.MyUserStory.class);
        TestOutcome testOutcome = TestOutcome.forTestInStory("some_test", story);
        assertThat(testOutcome.getUserStory().getStoryClassName(), is(MyApp.MyUserStory.class.getName()));
    }

    @Test
    public void we_can_record_the_lifetime_of_a_test_run() throws InterruptedException {
        Thread.sleep(100);
        testOutcome.recordDuration();
        assertThat(testOutcome.getDuration(), is(greaterThanOrEqualTo(10L)));
        assertThat(testOutcome.getDuration(), is(lessThan(5000L)));
        assertThat(testOutcome.getDurationInSeconds(), is(lessThan(5.0)));
    }

    class SimpleScenarioSteps extends ScenarioSteps {

        public SimpleScenarioSteps(final Pages pages) {
            super(pages);
        }
    }

    @Test
    public void scenario_steps_should_have_a_sensible_toString() {
        Pages pages = mock(Pages.class);
        SimpleScenarioSteps steps = new SimpleScenarioSteps(pages);

        assertThat(steps.toString(), is("SimpleScenarioSteps"));
    }

    @Test
    public void should_be_able_to_obtain_a_link_to_the_saucelabs_video() {
        testOutcome = TestOutcome.forTest("should_do_this", SomeTestScenario.class);
        testOutcome.setSessionId("1234");
        assertThat(testOutcome.getVideoLink(), is("http://saucelabs.com/jobs/1234"));
    }

    @Test
    public void should_be_able_to_find_the_last_step() {
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 1"));
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 2"));
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 3"));

        assertThat(testOutcome.lastStep().getDescription(), is("Step 3"));
    }


    @Test
    public void should_be_able_to_find_the_last_step_in_a_group() {

        testOutcome.recordStep(forASuccessfulTestStepCalled("Group 1"));
        testOutcome.startGroup();
        testOutcome.recordStep(forASuccessfulTestStepCalled("Group 2"));
        testOutcome.startGroup();
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 1"));
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 2"));
        testOutcome.recordStep(forASuccessfulTestStepCalled("Step 3"));

        assertThat(testOutcome.lastStep().getDescription(), is("Step 3"));
    }

    @Test
    public void should_calculate_the_overall_success_rate_from_provided_statistics() {
        TestStatistics statistics = new TestStatistics(10L, 7L, 3L,
                                                       ImmutableList.of(SUCCESS,SUCCESS,SUCCESS,SUCCESS,SUCCESS,SUCCESS,SUCCESS,FAILURE,FAILURE,FAILURE),
                                                       ImmutableList.of(new TestRunTag("MYPROJECT","A story","story")));

        testOutcome.setStatistics(statistics);
        assertThat(testOutcome.getOverallStability(), is(0.7));
    }

    @Test
    public void should_calculate_the_recent_success_rate_from_provided_statistics() {
        TestStatistics statistics = new TestStatistics(10L, 7L, 3L,
                ImmutableList.of(SUCCESS,SUCCESS,SUCCESS,SUCCESS,SUCCESS,SUCCESS,SUCCESS,FAILURE,FAILURE,FAILURE),
                ImmutableList.of(new TestRunTag("MYPROJECT","A story","story")));

        testOutcome.setStatistics(statistics);
        assertThat(testOutcome.getRecentStability(), is(0.7));
    }

    @Test
    public void should_count_the_recent_test_runs_from_provided_statistics() {
        TestStatistics statistics = new TestStatistics(8L, 5L, 3L,
                ImmutableList.of(FAILURE,FAILURE,PENDING,SUCCESS,SUCCESS,SUCCESS,SUCCESS,SUCCESS),
                ImmutableList.of(new TestRunTag("MYPROJECT","A story","story")));

        testOutcome.setStatistics(statistics);
        assertThat(testOutcome.getRecentTestRunCount() , is(8L));
        assertThat(testOutcome.getRecentFailCount() , is(2));
        assertThat(testOutcome.getRecentPassCount() , is(5));
        assertThat(testOutcome.getRecentPendingCount() , is(1));
    }
}
TOP

Related Classes of net.thucydides.core.model.WhenRecordingNewTestOutcomes

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.