Sleep vs Until In Protractor Tests

December 03, 2018

angular js and protractor

End-to-end testing in Angular is an easy task to get started with - but can be tricky to do well.

The point of end-to-end testing is to simulate a user going through your site or app - performing navigation and interacting with form elements, buttons, and other components. End-to-end tests should ensure that core business functionality is working at all times. Protractor is the end-to-end testing framework used by angular; it handles assertions and state while providing a nice wrapper around selenium to do the actual web driving.

Apps created with ng new [your-app-name] come with a protractor config file and a sample test out of the box. To run, just enter the command ng e2e. I like to organize my tests into page objects; so far I’ve found this to be the best approach across a number of applications. There are a ton of options you can either throw in to your config file or pass in on the command line, including pointing your tests at the deployed URL instead of the local build. This can come in handy for regression testing in a live environment.

One thing I’ve noticed lately when working with other developers on writing protractor tests is a common overuse of the browser.sleep() method. This method tells the browser to wait for a set amount of time, and is often used as the first go-to when dealing with conditions that require time to elapse before a test can be executed. I’ve seen people use sleep to wait on screens to render, http calls to return, validation to happen, and numerous other situations.

The problem with browser.sleep() is that it tells selenium to wait for a hard-coded period of time. The time needs to be chosen arbitrarily, and can often be more time than is necessary. If you’re running tests on deployed containers, the opposite problem can happen and the manual sleeps you’ve written while developing on your dev machine aren’t long enough anymore!

If only there were a better way…

Oh, wait… there is!

Enter browser.wait(). This method will let your tests wait just long enough for a given condition (protractor.ExpectedConditions - I usually alias this as ‘until’). Just about every place you have browser.sleep in your end-to-end tests it should be replaced by browser.wait. Here’s a quick sample of how to use it:

import {browser, by, element, protractor} from 'protractor';

const until = protractor.ExpectedConditions;

export class SampleTest {

  static viewContractDetails(){

    const myToggle = element(by.css('[data-toggle-test-hook]'));

    // hidden text that will be shown when the toggle is clicked
    const myText = element(by.css('[data-text-test-hook]'));

    browser.wait(until.elementToBeClickable(myToggle), 5000, 'My toggle taking too long to appear in the DOM');

    myToggle.click();

    browser.wait(until.visibilityOf(myText), 5000, 'My text taking too long to appear in the DOM');

    expect(myText.isVisible()).toEqual(true);

  }


}

It’s as easy as that! So go ahead, trade in sleep for wait, and enjoy your much-less-buggy e2e testing experience!


John D Potts

John D Potts

Web developer and speaker in Charlotte, NC.