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