A central part of testing Angular apps is to be able to automate the end-to-end testing so you don’t manually have to click through the app every time. This sounds reasonable in theory but often end-to-end tests can be fragile and expensive to maintain. When end-to-end tests become flaky they start to become useless:
This post covers some tricks for solving this by creating some helpers that make the tests more stable and simple to write.
These helpers are designed to make your test behave more like a real tester, by including behavior such as wait for an element to be visible, retry expects if the expect is not true immediately and retry flaky tests, that eg. has an unstable dependency.
Wait for element
A good pattern for selecting an element is to wait for it to be available and then select it. That way you don’t need to worry about eg. some spinner overlay to disappear before selecting.
This is implemented using the Browser.Wait method, which will periodically evaluate if an expression is true and then resolve a promise if the expression is true within the specified timeout.
Expect or retry
This is similar to “wait for element” but will instead wait for a provided boolean expression to become true until a given timeout.
This is again done using the Browser.Wait method, by evaluating a provided boolean expression and determine if it is true. If true this will return a resolved promise with true or else it will keep evaluating till the timeout runs out.
Retry test
Retry tests should be used when a test simply can’t be made stable with the previous helpers. This can often be caused by an external dependency that end-to-end test is calling. Often you will see end-to-end tests mock out the external dependency, but if you somehow need to involve the external dependency to create a meaningful test, this is the helpers to use.
A good tool to setup retry in protractor is Protractor-retry.
Conclusion
In this post, we looked at how to fix flaky protractor tests using three helpers. First, the element helper will ensure an element is visible before it is expected on. Second, the wait for expect helper will wait for a boolean expression to be true until a given timeout. Third, if a test can’t be made stable with the above two helpers, simply replaying the test might be the way to deal with that.
You can find a complete code example on my Github.
Thanks for reading. Remember to comment, share and follow me on Twitter.
Do you want to become an Angular architect? Check out Angular Architect Accelerator.
Pingback: End-To-End Testing with Protractor: A Pragmatic Guide to Get Started in Your Team – Christian Lüdemann IT()
Pingback: Why I Moved from Protractor to Cypress and the 7 Steps to Cypress E2E Testing Success – Christian Lüdemann()
Pingback: The Ten Commandments of Angular Development – Christian Lüdemann()