Skip to content

Archive for

29
Feb

New features in Thucydides 0.7.10


The latest version of Thucydides (0.7.10) to be released has some great new features! Find out more below:

Flag a test as ‘pending’ or ‘ignored’ from within a test step/page object
This is useful if a test can’t be completed for reasons outside the scope of the test, which occasionally happens with acceptance tests. To do this, just call ‘Thucydides.pendingStep()’ or ‘Thucydides.ignoredStep()’, as shown here:

public String findFirstPartiallyPublishedBookingId() {
    String partiallyPublishedBookingId = null;
    try {
        partiallyPublishedBookingId = getFirstBookingIDWithStatus("Partially Published");
    } catch (NoMatchingBookingFoundError e) {
        Thucydides.pendingStep("No partially published booking available");
    }
    return partiallyPublishedBookingId;
}

Both methods take a message as an argument, which appears in the final report, on the screenshot corresponding to the step where this occured. Any steps following a pending step will be flagged as ‘ignored’. Any steps following a step marked as ‘ignored’ in this way will be executed normally.

Improved reporting
The reports in Thucydides 0.7.10 come with a brand new dashboard which provides you with a quick overview of the state of your tests, as well as many other improvements:

New, improved dashboard

Proxy support
If you need to use a proxy to access the web site you are testing, you can now do this by providing the system properties thucydides.proxy.http and thucydides.proxy.http_port. Note: This feature is currently supported for Firefox only.

Tell us what you think of the changes…

Advertisements
22
Feb

Managing state between steps


Sometimes it’s useful to be able to pass information between steps. For example, you might need to check that a client’s details that were entered into a registration form appear correctly on a confirmation page later on.

You could do this by storing the values in local variables, as illustrated in the following example:

@Test
public void "Search property when creating ad"() {
    login.login_as(UserAccount.A_DIVISION_WITHOUT_OPENS);
    property_owner.chooses_to_place_a_new_ad()
    property_owner.selects_ad_category_and_style("Houses For Sale", "Premium Ad Style")
    def publicationName = pages[PublicationDatesPage].publicationName;
    def publicationDate = pages[PublicationDatesPage].publicationDate;
    property_owner.presses_continue()

    publication_manager.select_first_existing_property()
    property_owner.publish_ad()

    def displayedPublicationName = pages[ConfirmationPage].getPublicationDate();
    def displayedPublicationDate = pages[ConfirmationPage].getPublicationName();
    assertThat(displayedPublicationDate, is(publicationDate));
    assertThat(displayedPublicationName, is(publicationName));
 }

The problem with this approach is that it tends to clutter up the steps, and it also leaks implementation details into the high-level tests. Another approach is to use the Thucydides test session, which is essentially a hash map allowing you to store variables for the duration of a single test. You can obtain this session map using the Thucydides.getCurrentSession() static method.

In the following example, we store the publication name and date, obtained from the current web page, in the test session.

@Step
public void notes_publication_name_and_date() {
    PublicationDatesPage page = pages().get(PublicationDatesPage.class);
    String publicationName = page.getPublicationName();
    DateTime publicationDate = page.getPublicationDate();

    Thucydides.getCurrentSession().put("publicationName", publicationName);
    Thucydides.getCurrentSession().put("publicationDate", publicationDate);
}
Then, in a step invoked later on in the test, you can check the values stored in the session:
public void checks_publication_details_on_confirmation_page() {
    ConfirmationPage page = pages().get(ConfirmationPage.class);
    String selectedPublicationName = (String) Thucydides.getCurrentSession().get("publicationName");
    DateTime selectedPublicationDate = (DateTime) Thucydides.getCurrentSession().get("publicationDate");
    assertThat(page.getPublicationDate(), is(selectedPublicationName));
    assertThat(page.getPublicationName(), is(selectedPublicationDate));
}
The end result is a more concise and high-level test:
@Test
public void "Search property when creating ad"() {
    login.login_as(UserAccount.A_DIVISION_WITHOUT_OPENS);
    property_owner.chooses_to_place_a_new_ad()
    property_owner.selects_ad_category_and_style("Houses For Sale", "Liner + Large Header + Attention Getter")
    property_owner.notes_publication_name_and_date()
    property_owner.presses_continue()
    publication_manager.select_first_existing_property()
    property_owner.publish_ad()
    property_owner.checks_publication_details_on_confirmation_page()
 }
Thucydides test session data is stored in a ThreadLocal variable, so it will work if tests are run in parallel. The test session is cleared at the start of each test, so test data stored from previous tests cannot interfere with the current test. If no variable is found with the requested name, the test will fail.
It is always preferable to keep the high-level acceptance tests as general as possible: using and comparing temporary variables at the test level clutters and distracts from the overall understanding of the test. Using the Thucydides test sessions can go a long way helping to do this.