Why testing a front-end application is so hard? What are the main challenges you need to face? Why do the tests fail without a clear reason? This talk is about good testing best practices and the tool that is become the de-facto standard of UI Testing: Cypress.
Please note: this is the spoken version of my "Some UI testing problems and the Cypress way" article.
There is not an orchestrating Bash script and an orchestrated browser, the tests work directly in the browser.
Topics:
- the Cypress Test List UI: allows easy test selection
- the Cypress Test Runner UI: allows understanding what happens in the app and in Cypress
- everything works in the browser: you do not need to go back and forth from the Bash to the browser
- everything is logged inside the browser' console: you do not need to aggregate logs anymore
- easier command understanding: less tools means more trivial understanding and debugging
Examples:
- logging from the test
- logging from the app
- accessing document.window' properties from the test
- rich assertion results are logged too
Everything is asynchronous by definition in browserland
Topics:
- there are not sync/async differences, everything is async by definition
- automatic waiting
Examples:
- retrieving and interacting with an element
- asserting about an element visibility
Debugging is typically hard in E2E testing. Cypress comes to the rescue with a lot of first-class utilities.
Topics:
- tests can be paused and resumed later
- the Cypress Test Runner allows time-travelling: you can analyze the DOM at every test step
- tests have not timeouts, commands have: if something goes wrong, you discover it as soon as possible, without waiting for the while test timeout
- DOM-related errors: when interacting with an element is not possible, Cypress tells you the reason why
- automatic screenshot and videos: in case of failures, watching a video is easier than reading the log
Examples:
- pausing a test programmatically
- time travelling in action
- DOM-related errors with a fixed div all over the contents
- checking failure video
E2E Testing is not so important due to its complexity. With full network stubbing, testing only the front-end application is easy and profitable.
Topics:
- full network stubbing
- network error simulation
Examples:
- stubbing the wrong request: how a malformed stub could be detected with Cypress
- stubbing the right request
- happy path testing
- edge case testing
Cypress can be used not only as a development tool but as even as the main development browser.
Topics:
- automating manual interactions while developing
- debugging with Chrome devtools
- installing the React and Redux devtools
To leverage Cypress' full potential and have stable and useful tests there are a lot of UI Testing best practices.
Topics:
- retrieving elements by their contents: consuming the app the same way the user does is really important in order to have user-centered tests
- AJAX request and response assertions: asserting about AJAX requests alleviates test failure debugging
- clock management: long duration tasks could be fastly tested by controlling browser clock
- running E2E tests just for the happy path: running a limited number of E2E tests saves you a lot of time
Examples:
- full UI Integration tests
- full E2E tests
- I bootstrapped this project with create-react-app
- it contains a super-simple authentication form
- it contains a fake server with artificial delays to simulate E2E testing slowness
- all the code is well commented, with a lot of links to the slide explanations
- I wrote the front-end app with a outside-in approach writing the acceptance test at the beginning. I have not tested it manually at all!
There are four main commands:
npm run start
: starts the (super simple) front-end app and the (fake) back-end appnpm run cy:open
: opens the Cypress UInpm test
: launches both the front-end and the back-end apps, and runs cypress in the non-visual mode. Remember killing the manually launched apps since it uses the same ports
- launch the front-end app and take a look at the
src/App.js
file - launch both the back-end app and Cypress
- launch the
authentication.integration.test.js
in Cypress and watch it running - open the
cypress/integration/authentication.integration.test.js
and explore it - then, move to the
cypress/integration/authentication.e2e.test.js
- in the end: run the
npm test
command
Do not forge to add a star to my (work in progress) UI Testing Best Practices book on GitHub 😊