Organizing Tests, Logging In, Controlling State
- Anti-Pattern: Sharing page objects, using your UI to log in, and not taking shortcuts.
- Best Practice: Test specs in isolation, programmatically log into your application, and take control of your application's state.
Selecting Elements
- Anti-Pattern: Using highly brittle selectors that are subject to change.
-
Best Practice: Use
data-*
attributes to provide context to your selectors and isolate them from CSS or JS changes
Selector | Recommended | Notes |
---|---|---|
cy.get('button').click() |
Never | Worst - too generic, no context |
cy.get('.btn.btn-large').click() |
Never | Bad. Coupled to styling. Highly subject to change |
cy.get('#main').click() |
Sparingly | Better. But still coupled to styling or JS event listeners. |
cy.get('[name=submission]').click() |
Sparingly | Coupled to the name attribute which has HTML semantics. |
cy.contains('Submit').click() |
Depends | Much better. But still coupled to text content that may change. |
cy.get('[data-cy=submit]').click() |
Always | Best. Isolated from all changes. |
Assigning Return Values
-
Anti-Pattern: Trying to assign the return value of Commands with
const
,let
, orvar
. - Best Practice: Use closures to access and store
Visiting External Sites
- Anti-Pattern: trying to visit or interact with sites or servers you do not control
-
Best Practice: Only test what you control. Try to avoid requiring a 3rd party server. When necessary, always use
cy.request()
to talk to 3rd party servers via their APIs.
Having tests rely on the state of previous tests
- Anti-Pattern: Coupling multiple tests together
- Best Practice: Tests should always be able to be run independently from one another and still pass.
Creating "tiny" tests with a single assertion
- Anti-Pattern: Acting like you're writing unit tests.
- Best Practice: Add multiple assertions and don't worry about it
Using after
or afterEach
hooks
-
Anti-Pattern: Using
after
orafterEach
hooks to clean up state. - Best Practice: Clean up state before tests run.
Unnecessary Waiting
-
Anti-Pattern: Waiting for arbitrary time periods using
cy.wait(Number)
- Best Practice: Use route aliases or assertions to guard Cypress from proceeding until an explicit condition is met
Web Servers
-
Anti-Pattern: Trying to start a web server from within Cypress scripts with
cy.exec()
orcy.task()
. - Best Practice: Start a web server prior to running Cypress
Setting a global baseUrl
-
Anti-Pattern: Using
cy.visit()
without setting abaseUrl
. -
Best Practice: Set a
baseUrl
in your configuration file (cypress.json by default)
You can read our entire Best Practices Guide at https://docs.cypress.io/guides/references/best-practices
Top comments (1)
Thank you for sharing these valuable Cypress best practices! I've been exploring different resources to enhance my test automation skills, I recently came across another article titled 'Cypress Best Practices for Test Automation' that expands on some of the concepts you've covered here. It delves deeper into practical tips and techniques for optimizing test automation workflows with Cypress. Keep up the great work!"