Skip to content

Posts tagged ‘Thucydides’

31
Dec

Thucydides Release 0.9.229


There have been many releases since the last release notes were published, so this entry will summarize some of the highlights that are included in release 0.9.229 (though many came out in releases previous to that). Some of the highlights include:

  • Added support for Selenium 2.39.0
  • Testing AngularJS is made easier with support for the ng-model attribute in the Thucydides @FindBy annotation. Suppose you have this AngularJS input field:
<input ng-model="angularField" value="Model value" />

You can now find this directly using the Thucydides @FindBy:

import net.thucydides.core.annotations.findby.FindBy
 @FindBy(ngModel = "angularField")
 public WebElementFacade ngModelField;
  • Support for nested page objects – you can have page object fields inside other page objects. This makes it easier to write page objects for smaller reusable sections of the screen.
  • You don’t need to override the constructors for ScenarioSteps and PageObjects any more
  • You can provide your own webdriver instance using the ‘webdriver.provided.type’. Just implement the DriverSource interface. For example, you could implement a class like this:
package com.acme
public class MyFunkyDriverSourceImpl implements DriverSource {
    public WebDriver newDriver() {
       return new FunkyWebDriver();
    }
}

Then just run the tests with the following properties (e.g. in the thucyiddes.properties file or on the command line):

webdriver.driver = provided
 webdriver.provided.type = funky
 webdriver.provided.funky = com.acme.MyFunkyDriverSourceImpl
  • Lots of improvements to the reports, including:
    • Reports now have the option to hide the pie chart on the aggregate pages
    • Test reports now display the date and time of the report generation on each page.
    • You can use the ‘show.related.tags’ system property to display (default) or hide related tag statistics on the dashboard
    • Support for reporting on releases/versions by integrating with JIRA (there will be a full article on this feature shortly)
    • Support for integration with 3rd party test management software such as the JIRA Zephyr plugin to report on manual as well as automated tests
  • Many bug fixes

If you are still on an older version, update your dependencies today!

Advertisements
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…

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.
25
Dec

Faster Web Tests with Parallel Batches in Thucydides


Web tests are as a rule much slower than other types of tests, but they can be sped up significantly by running them in parallel. However, this is often harder to implement than it sounds. The latest version of Thucydides (version 0.6.0) comes with support for running parallel test batches, making this task much easier.

Web tests make good candidates for concurrent testing, in theory at least, but the implementation can be tricky. For example, although it is easy enough to configure both JUnit and easyb to run tests in parallel, running several webdriver instances of Firefox in parallel on the same display, for example, tends to become unreliable.

The natural solution in this case is to split the web tests into smaller batches, and to run each batch on a different machine and/or on a different virtual display. When each batch has finished, the results can be retrieved and aggregated into the final test reports.

However splitting tests into batches by hand tends to be tedious and unreliable – it is easy to forget to add a new test to a batch, for example, or have unevenly-distributed batches.

The latest version of Thucydides lets you do this automatically, by splitting your test cases evenly into batches of a given size. In practice, you run a build job for each batch. You need to specify two parameters when you run each build: the total number of batches being run (thucydides.batch.count), and the number of the batch being run in this build (thucydides.batch.number).

For example, the following will divide the test cases into 3 batches (“thucydides.batch.count”), and only run the first test in each batch (thucydides.batch.number):

mvn verify -Dthucydides.batch.count=3 -Dthucydides.batch.number=1

This will only work with the JUnit integration. However this feature is also now supported in easyb (as of easyb version 1.5), though using different parameters. When using the Thucydides easyb integration, you also need to provide the equivalent options for easyb:

mvn verify -Deasyb.batch.count=3 -Deasyb.batch.number=1

If you have both easyb and JUnit Thucydides tests, you will need to specify both options.

Parallel web tests on Jenkins

This approach is easy to set up on Jenkins using a multi-configuration build. In the following screenshot, we are running a multi-configuration build to run web tests across three batches. We use a single user-defined parameter (BATCH_NUMBER) to define the batch being run, passing this parameter into the Maven build job properties we discussed above.

The most robust way to aggregate the build results from the different batches is to set up a second build job that runs after the test executions, and retrieves the build results from the batch jobs. You can use the Jenkins Copy Artifacts plugin to do this. First, ensure that the multi-configuration build archives the Thucydides reports, as shown here:

This build will then trigger another, freestyle build job. This job needs to copy the Thucydides report artifacts from the matrix build jobs into the current workspace, and then run the mvn thucydides:aggregate command to generate the Thucydides aggregate reports. The matrix build job reports need to be copied one-by-one for each batch, as the current version of the Copy Artifacts plugin does not support copying from multiple projects in the same action.

Then make sure you publish the generated HTML reports (which will be in the target/site/thucydides directory) for easy access to the test results.

This simple example shows a parallel test running 3 batches – this brought the test execution time from 9 minutes to slightly over 1 minute. Results will vary, of course, but a typical real-world set of web tests would have a larger number of batches.

26
Sep

Using Selenium 2.6 ExpectedConditions with Thucydides


Selenium 2.6 provides a new API that allows more fluent wait conditions, such as waiting for several fields to be visible or enabled. This has been integrated into the Thucydides PageObject class with a helper method to make it a bit easier to use. Read more »

26
Sep

Thucydides 0.4.8 Released


A new version of Thucydides – version 0.4.8 – is now available in the Maven repositories.

One of the most important improvements in this latest version is that it uses Selenium 2.6, which supports all versions of Firefox from 3.0 to 7. Previous versions of Selenium did not work well with Firefox 6 and 7.

Other improvements have been made in the reporting features. By default, Thucydides opens a browser with a width of around 1000px. Sometimes, this is not enough, and you need a larger window to see all of the elements on your page in the screenshots. Thucydides 0.4.8 lets you define the witdh of the browser Thucydides opens via the thucydides.browser.width command line option. Read more »