Implementing the Tests
As work progresses, you will flesh out the details. However, acceptance tests are high-level communication tools, and we don't want to dive into the technical details too soon. Doing so would make the tests too rigid and fragile.
Instead, we describe the test in more high-level terms, as a series of reusable steps, in a similar manner to the way a tester would plan a manual test script. You can think of this process as using a custom testing DSL for your application. Once we have laid out these steps, we will move on to implementing the details.
Here is what our test steps look like in this example:
using "thucydides"
thucydides.tests_story SearchForArtifactsByName
thucydides.uses_steps_from DeveloperSteps
scenario "A developer looks for an existing Maven artifact by name and group id", {
given "the developer is on the Maven Central search page", {
developer.opens_the_search_page()
}
when "the user searches for artifacts with the name 'thucydides'", {
developer.searches_for 'Thucydides'
}
then "the thucyidides core artifact should appear in the results list", {
developer.should_see_artifacts_where(the("ArtifactId", is("thucydides")),
the("GroupId", is("net.thucydides")))
}
}
Steps are implemented as Java methods. In this case, the steps are implemented in a Java class called DeveloperSteps. The thucydides.uses_steps.from instruction creates and configures an instance of this class, and makes it available in the easyb story as the developer variable.
It is also perfectly possible to implement the acceptance criteria as plain JUnit tests. The test we just saw could also be implemented as shown here:
@RunWith(ThucydidesRunner.class)
@Story(Application.Search.SearchForArtifactsByName.class)
public class WhenSearchingForArtifacts {
@Managed
WebDriver driver;
@ManagedPages(defaultUrl = "http://search.maven.org")
public Pages pages;
@Steps
public DeveloperSteps developer;
@Test
public void should_search_for_artifacts_by_name() {
developer.opens_the_search_page();
developer.searches_for("Thucydides");
developer.should_see_artifacts_where(
the("ArtifactId", is("thucydides")),
the("GroupId", is("net.thucydides")));
}
}
The test steps are just normal annotated Java methods, implemented in a fairly ordinary class that are referred to as a "Step Library." The simplest way to create a Step Library class is to extend the ScenarioSteps class, as shown in the following example:
public class DeveloperSteps extends ScenarioSteps {
public DeveloperSteps(Pages pages) {
super(pages);
}
@Step
public void opens_the_search_page() {
onSearchPage().open();
}
@Step
public DeveloperSteps searches_for(String search_terms) {
onSearchPage().enter_search_terms(search_terms);
onSearchPage().starts_search();
return this;
}
@Step
public void should_see_artifacts_where(PropertyMatcher... matchers) {
shouldMatch(onSearchResultsPage().getSearchResults(), matchers);
}
private SearchPage onSearchPage() {
return getPages().get(SearchPage.class);
}
private SearchResultsPage onSearchResultsPage() {
return getPages().get(SearchResultsPage.class);
}
}
The methods in a Step Library can either implement the test details directly or, for more complex test cases, break the step down further into sub-steps.


