Skip to content

Sensible patterns and practices πŸ˜‡

Atomic tests βš›οΈ

  • Write targeted tests
  • No more than 2 assertions per test 2️⃣
  • Outcome of one test should not cause another to fail

πŸ’‘Follow TRIMS πŸ‘- Richard Bradshaw, Ministry of testing

Use explicit waits πŸ›‘

  • Avoid writing hardcoded sleeps/implicit waits

Use API βš™οΈ or DB for data setup/teardown

Set application state ⏩ using:

  • API
  • Inject JS
  • Cookies
  • Modify DB

Arrange act assert ❀️

  • Setup state => Perform a test => Assert => Cleanup

Run tests in parallel from the start πŸƒ πŸƒ πŸƒ

  • Atomic tests + parallel 🀝
  • Use Selenium Grid πŸ‘
  • Create a new webdriver instance for every test
  • Don't use static keyword/shared state

Page object

  • Write page objects for components within pages
  • Naming that clarifies intent

Fluent pattern πŸƒ

To do with 2 notes added

@Test(groups = Tags.REGRESSION)
public void testToDoItemsLeft() {
    HomePage home = new HomePage(driver);
    home.addTodo("Get work done");
    home.addTodo("relax");
    ...
}
@Test(groups = Tags.REGRESSION)
public void testToDoItemsLeft() {
    // More readable πŸ˜„
    HomePage home = new HomePage(driver)
            .addTodo("Get work done")
            .addTodo("relax");
    ...
}

How is this enabled?

πŸ’‘return either the current page object or the next page object to enable fluent methods

public HomePage addTodo(String todoNote) {
        enterText(todo, todoNote);
        pressEnter(todo);
        return this;
    }

Can use this in assertions as well

// TestNG assert
Assert.assertEquals(addedTodosText, note);

// Google truths fluent assert
assertThat(addedTodosText).isEqualTo(note);

Page factory

  • Easily specify WebElement/s to be found
  • Use @CacheLookup to keep WebElement for static elements
public class HomePage extends BasePage {
    public HomePage(WebDriver driver) {
        super(driver);
        PageFactory.initElements(driver, this);
    }

    @FindBy(css = "#root input")
    WebElement todo;

    @FindBy(xpath = "//ul[@class='todo-list']//label")
    List<WebElement> todos;

    String addedNote =
            "//ul[@class='todo-list']//label[contains(text(), '%s')]";

    ...

    public HomePage addTodo(String todoNote) {
        enterText(todo, todoNote);
        pressEnter(todo);
        return this;
    }
    ...
}

Screenplay pattern

  • Follows SOLID principles and takes a user centric view of writing automated acceptance tests
  • Check out Serenity BDD

Builder pattern

  • Use this to construct complex data objects instead of multiple constructor params