Simple E2E test suite with Cypress
application under test: http://angularjs.realworld.io/
๐ฅ Goals
- keep it simple - no 'custom' abstractions/functions/utils/helpers (use what Cypress provides)
- tests are easily readable
- project is easily understandable even to people without previous JS or Cypress knowledge
- use shortcuts to avoid repeating/testing the same UI actions over and over again
โ๏ธ Setup
git clone https://github.com/helenanull/cypress-example.git
- cd to
cypress-example
folder and runnpm install
โ๏ธ Run tests
- If you installed Cypress via npm:
-
cypress test runner (cypress open):
npm run cy:open:web
ORcypress open --env device=web
(change web to mob to switch to mobile view)
-
cypress headless mode (cypress run):
npm run cy:run:web
ORcypress run --env device=web
-
- If you installed Cypress zip:
- import
cypress-example
folder and you are good to go
- import
๐ก Information
๐งช Tests:
๐ Tests are located in cypress/integration
folder
๐ Custom commands are located in cypress/support
folder (.cmd.js
suffix)
๐ Selectors (CSS selectors) are located in cypress/selectors
folder [only difference from cypress default project structure] - not using page object model(POM) design pattern but keeping selectors (only selectors) separately Read more
๐ ๏ธ Configuration
Config files:
cypress.json
- Main config file where default behavior of Cypress can be modified. More infoplugins/index.js
- Plugins file is where we can programmatically alter the resolved configuration More info
This test suite is supporting multiple viewports (mobile and desktop).
One solution is to use cy.viewport() command inside the test, to change the viewports, but very often websites also check user agent to get the device information(and show the mobile view). Since user agent is something we can't change in the middle of the test, we need to pass config value when launching tests. In cypress.json
we have a device
parameter and in plugins file index.js
, we decide viewports and user agent parameter values based on device value.
๐ IDE setup and recommended extensions
- VS Code with following extensions:
- ESLint - to keep your code tidy
- Add Only - enables to add/remove
.only
with one click - VScode-icons
โ Q&A
- Why keep selectors separately (not hard-coded to tests)
- tests are much more readable - css selectors are by design hard to read - even if we add data-test attributes. We might need a 2nd child or want to verify that a selector is a child for another element, like
.class2 > ul:nth-child(2)
(alternativeget().find()
orget().parent()
is bad practice because of this ) - in large projects, we might need to re-use the same selectors. Example: in login test, we want to verify that login was successful and for that, we check settings link visibility in header. But the same settings link is also used in header test.
- selector and test logic is separated - when selector is updated, we just need to update 1 selector file and not multiple tests
- tests are much more readable - css selectors are by design hard to read - even if we add data-test attributes. We might need a 2nd child or want to verify that a selector is a child for another element, like
- Is it still E2E test if we use API's instead of UI?
- all functionality should be tested from UI once. There is no reason to repeat the same UI actions over and over again in each test. Edit article example. End result will be the same - it will catch exactly the same bugs as
full flow/user journey
test would find, (we need to be careful not to leave 'gaps' though) - tests are just separated and independent with this approach, test suite is still E2E. Example: We have a bug where login button is not working - our settings test would pass(if there are no bugs in settings), but login test would still fail.
- all functionality should be tested from UI once. There is no reason to repeat the same UI actions over and over again in each test. Edit article example. End result will be the same - it will catch exactly the same bugs as