100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
Testing

Assertions with should() and expect()

Learn the difference between Cypress's retrying should()/and() assertions and Chai's one-time expect() assertions, and when to use each.

Selectors & CommandsIntermediate8 min readJul 10, 2026
Analogies

Assertions with should() and expect()

Assertions are how a Cypress test declares what it expects to be true about the application, and Cypress bundles Chai, Chai-jQuery, and Sinon-Chai so you get a rich vocabulary of assertion chainers out of the box — things like 'be.visible', 'have.text', 'have.length', and 'have.been.calledOnce' for spies and stubs. Every assertion compares actual application state to an explicit expected value rather than merely observing that a command ran.

🏏

Cricket analogy: A third umpire doesn't just watch the replay; he checks it against a specific rule, like whether the bail was dislodged before the stumping was completed, similar to how a Cypress assertion checks the DOM against a specific expected condition rather than just observing it.

should() — Retrying, Subject-Chained Assertions

should() is chained directly onto a command like cy.get() and takes one or more chainer strings describing the expected condition, such as cy.get('.alert').should('be.visible'). Crucially, should() doesn't just check once: it re-runs the preceding cy.get() query and re-evaluates the condition repeatedly, which is what allows a test to wait naturally for an element that appears only after an animation or network response completes.

🏏

Cricket analogy: Hawk-Eye keeps re-tracking the ball's trajectory until it's confident the prediction is stable before showing the final verdict, similar to how cy.get('.alert').should('be.visible') keeps re-querying the alert element and re-checking visibility until the assertion passes or times out.

javascript
cy.get('.alert')
  .should('be.visible')
  .and('contain', 'Success');

cy.get('.cart-count').should('have.text', '3');

expect() — One-Time, Explicit Assertions

expect() is Chai's standalone assertion function, typically used inside a cy.then() callback to check a value you've already captured, for example expect(price).to.be.greaterThan(0). Unlike should(), expect() performs its check exactly once against the value passed in — it has no awareness of the DOM and doesn't retry, so it's best suited for verifying computed or derived JavaScript values rather than waiting on asynchronous UI state.

🏏

Cricket analogy: Once the ball is dead and the over is complete, the scorer records that ball's outcome permanently in the book without re-checking it later, similar to how expect(text).to.equal('Sold Out') inside a cy.then() callback checks a captured value once, without Cypress retrying it.

Chai also offers a BDD-style assert API (assert.equal(a, b)) as an alternative to expect(). Both work identically inside cy.then(); expect() is more common because its fluent, readable syntax (expect(x).to.equal(y)) matches the chainer style used elsewhere in Cypress tests.

Choosing the Right Assertion Style

As a rule of thumb, use should() (or and()) for anything checking live DOM state, since retry-ability is exactly what makes UI assertions reliable against asynchronous rendering. Reach for expect() inside cy.then() when you need to run custom JavaScript logic on a captured value — like summing an array of prices pulled from the DOM — where Cypress's built-in chainers alone can't express the check.

🏏

Cricket analogy: A team analyst uses live ball-by-ball tracking to judge current match momentum but a separate post-match report to calculate season averages, similar to using should() for live, retrying DOM checks and expect() inside cy.then() for one-off computed value checks.

Chaining multiple, loosely related conditions onto a single should() (or worse, burying several expect() calls inside one cy.then()) can make a failing test hard to diagnose, since you only see that 'the assertion' failed. Prefer separate should()/and() calls, or clearly named expect() checks, so a failure points precisely at which condition broke.

  • Cypress bundles Chai, Chai-jQuery, and Sinon-Chai, giving access to chainers like be.visible, have.text, and have.been.calledOnce.
  • should()/and() chain onto a command and re-run both the query and the assertion until it passes or times out.
  • expect() is Chai's standalone assertion, typically used inside cy.then() to check an already-captured value once.
  • expect() does not retry — it's best for verifying computed or derived JavaScript values, not live DOM state.
  • Prefer should() for anything checking live, asynchronous UI state.
  • Avoid overloading a single should() chain or cy.then() callback with unrelated checks, since it obscures which condition actually failed.

Practice what you learned

Was this page helpful?

Topics covered

#Testing#CypressStudyNotes#TestingQA#AssertionsWithShouldAndExpect#Assertions#Should#Expect#Retrying#StudyNotes#SkillVeris