Ketan's Musings

Where he blogs about his eclipse musings

Reusing Functional Tests – Part 1

with 7 comments

While writing some tests for SWTBot, there was quite some code duplication that could be removed by using some simple test patterns. This is part of a series of articles about how test code could be written better. This example uses SWTBot as a driver to drive an Eclipse application used by ACME Corporation.

Here is a snippet of a Test Case that creates an account in ACME Corporation’s customer management system.

public void testCreatesAccount() throws Exception {
    bot.menu("Accounts").menu("New").click();
    // nice wizard
    bot.shell("Create a new account").activate();
    bot.textWithLabel("Name:").setText("Will Coyote");
    bot.textWithLabel("Email:").setText("will@coyote");
    bot.button("Next>").click();
    // yet another wizard
    bot.shell("Address Details").activate();
    bot.textWithLabel("Mailing Address:").setText("Will Coyote, middle of, nowhere");
    bot.button("Finish").click();

    assertThatAccountIsCreated("Will Cooyte", "will@coyote.com");
}

That’s a great start to begin writing tests. But there’s the problem: What happens if the test fails somewhere and the “Create a new account” or the “Address Details” window remains open ? This means that the rest of the tests fail or do not run at all. Not a problem, tearDown() to the rescue:

protected void tearDown() throws Exception {
    closeWindow("Create a new account");
    closeWindow("Address Details");
}

private void closeWindow(String windowTitle) throws Exception {
    try {
    bot.shell(windowTitle).close();
    } catch (WidgetNotFoundException e) {
        // do nothing if the window is not found
    }
}

Now we write a test that tests if you’re able to create two users with the same name.

public void testShouldNotCreateTwoAccountsWithTheSameName() throws Exception {
    bot.menu("Accounts").menu("New").click();
    // nice wizard
    bot.shell("Create a new account").activate();
    bot.textWithLabel("Name:").setText("Will Coyote");
    bot.textWithLabel("Email:").setText("will@coyote");
    bot.button("Next>").click();
    // yet another wizard
    bot.shell("Address Details").activate();
    bot.textWithLabel("Mailing Address:").setText("Will Coyote, middle of, nowhere");
    bot.button("Finish").click();

    assertThatAccountIsCreated("Will Cooyte", "will@coyote.com");

    bot.menu("Accounts").menu("New").click();
    // nice wizard
    bot.shell("Create a new account").activate();
    bot.textWithLabel("Name:").setText("Will Coyote");
    bot.textWithLabel("Email:").setText("will@coyote");
    bot.button("Next>").click();
    // yet another wizard
    bot.shell("Address Details").activate();
    bot.textWithLabel("Mailing Address:").setText("Will Coyote, middle of, nowhere");
    bot.button("Finish").click();

    assertThatAccountIsNotCreated("Will Cooyte", "will@coyote.com");
}

Duplication, not a big deal, some bit of refactoring and you get to this. This also reduces the number of places where you’ll need to fix the test, if the label on one of the screens change.

public void testCreatesAccount() throws Exception {
    createAccount("Will Coyote", "will@coyote", "Will Coyote, middle of, nowhere");
    assertThatAccountIsCreated("Will Cooyte", "will@coyote.com");
}

public void testShouldNotCreateTwoAccountsWithTheSameName() throws Exception {
    createAccount("Will Coyote", "will@coyote", "Will Coyote, middle of, nowhere");
    assertThatAccountIsCreated("Will Cooyte", "will@coyote.com");
    createAccount("Will Coyote", "will@coyote", "Will Coyote, middle of, nowhere");
    assertThatAccountIsNotCreated("Will Cooyte", "will@coyote.com");
}

private void createAccount(String name, String email, String snailMail) throws WidgetNotFoundException, TimeoutException {
    bot.menu("Accounts").menu("New").click();
    // nice wizard
    bot.shell("Create a new account").activate();
    bot.textWithLabel("Name:").setText(name);
    bot.textWithLabel("Email:").setText(email);
    bot.button("Next>").click();
    // yet another wizard
    bot.shell("Address Details").activate();
    bot.textWithLabel("Mailing Address:").setText(snailMail);
    bot.button("Finish").click();
}

In the next article, you’ll get to see how you can reuse code better by using Screen Objects

Written by Ketan

June 21st, 2008 at 12:48 pm

Posted in eclipse

Tagged with , ,

7 Responses to 'Reusing Functional Tests – Part 1'

Subscribe to comments with RSS or TrackBack to 'Reusing Functional Tests – Part 1'.

  1. Hi! I want to know about your idea of using screen objects. When are you going to write part 2?

    Leo Arias

    4 Sep 08 at 5:34 am

  2. @Leo, hold on for a couple of days. I’m already writing this one and it’s still a draft.

    Ketan

    6 Sep 08 at 8:50 am

  3. cool, I’ll be waiting.

    Leo Arias

    12 Sep 08 at 9:06 pm

  4. Is Screen Object the same concept as a Page Object?

    http://code.google.com/p/webdriver/wiki/PageObjects

    Jason Yip

    15 Oct 08 at 2:58 pm

  5. @Jason,

    Yes, that is the same concept — Providing classes that expose operations/services that users can perform on a page rather than the raw UI controls.

    Ketan

    15 Oct 08 at 5:47 pm

  6. [...] SWTBot also provides a recorder, what’s its current state? The recorder was developed as a proof of concept, and has not been touched much. It lacks support for a lot of controls, and does not record all operations, although it is quite trivial to add support for these. The recorder records code in an intermediate format, similar to an Abstract Syntax Tree. This representation can then be output in a language of your choice, currently it supports Java, but even Ruby is possible. On another note: Record and playback is not the recommended way to write tests (see TestingGUIApplications and Recording vs. Coding). Primarily because the complete script for a workflow (or all the scripts) need to be recorded again for tiny changes. SWTBot recommends using the PageObject/ScreenObject pattern (or see reusing functional tests). [...]

  7. Great Article.

    When comes Part 2 about the using of screen objects?

    Rob Meier

    17 Aug 09 at 2:45 pm

Leave a Reply

IMPORTANT! To be able to proceed, you need to solve the following simple math (so we know that you are a human) :-)

What is 5 + 9 ?
Please leave these two fields as-is: