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 π
@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