This lesson collects commonly asked Cypress interview questions, from fundamentals through advanced topics like network stubbing and CI integration, with clear, concise answers you can use to prepare.
Pro Tip
When asked a conceptual question, briefly define the concept, then immediately walk through a tiny, concrete code example, this consistently reads as stronger, more practical understanding than a definition alone.
Extended Cypress Interview Q&A
The following questions go deeper than the quick reference table above, with fuller
explanations for each answer.
1. How does Cypress's architecture differ from Selenium's?
Cypress runs directly inside the browser, in the same run loop as the application under
test, giving it native access to the DOM, network layer, and JavaScript execution
context. Selenium drives a browser externally over the WebDriver protocol, sending
remote commands to a driver process. This is why Cypress supports automatic
retry-ability and native network interception without extra tooling, while Selenium
typically needs explicit waits and separate proxy tools for similar network control.
2. Explain how Cypress's automatic retrying works.
When a query command like cy.get() is chained with an assertion like
.should(), Cypress doesn't run each once. It re-runs the entire chain,
re-querying the DOM and re-checking the assertion, repeatedly, until it passes or the
configured timeout elapses. This lets tests tolerate natural asynchronous timing (data
loading, animations) without needing manual, fixed-duration waits.
3. What is the difference between an implicit and an explicit assertion?
Implicit assertions use .should()/.and() and are
automatically retried as part of the command chain. Explicit assertions use
expect() or assert(), typically inside a .then()
callback, and run exactly once, at the moment that line executes. Implicit assertions
are generally preferred for their built-in retry-ability.
4. Why is cy.wait(ms) generally discouraged?
A fixed-duration wait guesses how long an operation will take. If the guess is too
short, the test remains flaky; if too long, the whole suite runs slower than
necessary for no benefit. Waiting on a specific aliased network request with
cy.wait('@alias'), or waiting on a real DOM condition with
.should(), resolves exactly when the real condition becomes true instead.
5. What selector strategy does Cypress recommend, and why?
Cypress recommends dedicated data-cy (or data-testid)
attributes as the primary selector strategy, since they carry no styling or JavaScript
behavior and won't break when a class name or markup structure changes for unrelated,
purely visual reasons. CSS classes and structural selectors are more likely to break
during normal refactors that have nothing to do with actual functional correctness.
6. How would you test that an API call returns an error correctly?
Use cy.intercept() to stub the relevant endpoint with an error status code
and body, for example a 500 or 404, then trigger the action that calls it and assert
the application shows the appropriate error state in the UI. This makes error
scenarios reliably testable without needing to reproduce a real backend failure on
demand.
7. What is the difference between cy.intercept() and cy.request()?
cy.intercept() observes or stubs requests that your application itself
makes as it runs in the browser. cy.request() is the test acting as its
own HTTP client, making a direct request outside of any application code, commonly
used for fast setup or direct API contract testing.
8. What problem does cy.session() solve?
Repeating a full UI login in every test that requires authentication adds significant,
unnecessary time and an extra point of failure unrelated to what's actually under
test. cy.session() caches the resulting cookies/storage from a setup
function (often an API-based login) and restores it instantly on subsequent tests
using the same session id, dramatically speeding up authenticated test suites.
9. What's the difference between cy.spy() and cy.stub()?
cy.spy() wraps an existing function so calls are recorded, while letting
the real implementation still execute normally. cy.stub() replaces a
function's implementation entirely, useful when the real behavior is unwanted,
expensive, or has side effects that need to be prevented during the test.
10. How does Cypress component testing differ from end-to-end testing?
Component testing mounts a single UI component directly, using your project's real
build tooling, without a full running application, router, or backend. End-to-end
testing drives the full application through a real browser exactly as a user would.
Component testing is faster and more isolated; E2E testing provides broader,
full-integration confidence.
11. How would you debug a test that passes locally but fails in CI?
Start by checking environment differences: environment variables, base URLs, timing
(CI machines can be slower), and whether the CI application build/start step
completed correctly before tests ran. Reviewing the CI run's screenshots and videos
(if configured) usually narrows this down quickly, followed by checking for hidden
test order or shared-state dependence that a different CI parallelization might expose.
12. What causes a Cypress test to be flaky, and how would you fix it?
Common causes include fixed-duration waits, shared or order-dependent state between
tests, unstubbed real network variability, and ambiguous selectors matching multiple
or unstable elements. The fix generally involves replacing fixed waits with
assertion-based waits, resetting state per test, stubbing network responses, and
switching to stable, dedicated selectors.
13. How do you handle authentication in Cypress tests without slowing down the suite?
Combine an API-based login (bypassing the UI entirely for setup purposes) with
cy.session() to cache the resulting authenticated state across tests.
Reserve actual UI-driven login testing for a small number of tests specifically
covering the login flow itself.
14. What's the recommended way to run Cypress in CI?
Run it headlessly via cypress run, after the application under test has
started and a real health check (not a fixed sleep) confirms it's ready. Cache
node_modules and the Cypress binary to avoid slow, repeated downloads, and
upload screenshots/videos as artifacts on failure for later debugging.
15. How would you decide what to cover with E2E tests versus component or API tests?
Use API-level tests (via cy.request()) for thorough, fast validation of
an endpoint's contract and edge cases. Use component tests for a component's various
prop/state permutations in isolation. Reserve full E2E tests for critical,
high-value user journeys that need genuine full-stack confidence, avoiding redundant
coverage of the same logic at multiple levels.