A Cypress beforeEach hook throws: what happens to the rest of that suite?
answer
- One error, many tests never attempted
- The blamed test may be blameless
- Two statuses that both mean not run
- A passing body can still fail on teardown
- The message names the hook and the suite
basics
~20 sThe test the hook was running for is reported as failed, and every remaining test in that suite is marked skipped rather than run, because the same hook would fail for each of them. A root-level hook skips all remaining tests.
solid answer
~40 sCypress attributes the hook error to the test the hook was serving, so that test is reported **failed**, with a message appended along the lines of "Because this error occurred during a `before each` hook we are skipping the remaining tests in the current suite". The rest of the `describe` block is then reported **skipped** — not passed, not pending — since the hook would fail identically for each of them. A root-level hook has no enclosing suite, so it skips all remaining tests in the spec. `before` and `afterEach` failures cascade the same way, and a failing `afterEach` fails a test whose body passed. Read a skipped count as unknown coverage, not as success: a run showing one failure and fourteen skips has learned nothing about fourteen tests.
go deeper
Know that a hook failure does not stay contained: the test it was serving fails and the others in that block do not run, so fixing the hook is the first move.
Explain the cascade precisely — which test is blamed, which block stops, and how a root-level hook differs from one inside a describe — and distinguish skipped from pending.
Show how you read such a report in CI: locating the real failure in the hook's Command Log section, treating skipped counts as lost coverage, and reshaping fat hooks so one broken prerequisite stops fewer tests.
Own the policy: how much a shared hook may take on before it becomes a single point of failure for a whole block, and what the pipeline reports when a run's coverage is partially unknown.
## What Cypress does the moment a hook throws When a `beforeEach` fails, Cypress attributes the error to the **test the hook was running for**. That test is reported as **failed**, and the error carries an appended sentence naming the hook and the consequence, in the shape: > Because this error occurred during a `before each` hook we are skipping the remaining tests in the > current suite: `Borrowing flow` Then it stops running that block. The reasoning is blunt and correct: the hook would fail identically for every remaining test, so re-running it fourteen more times buys fourteen more copies of the same stack trace. If the hook was declared at the **root** of the spec rather than inside a `describe`, there is no enclosing suite to stop at, and the message says it is skipping all of the remaining tests instead. The same treatment applies to `before` and to `afterEach`. A failing `afterEach` is the one people find surprising: the test body may have passed, but the hook error still fails the test and takes the rest of the block with it. ## Three words that are not synonyms Cypress inherits Mocha's four statuses, and a report is unreadable if you blur the middle two. | Status | What it means | Typical cause | |---|---|---| | **passed** | ran to the end with no failing assertion | — | | **failed** | an assertion failed or a command errored | the defect, or a broken hook | | **pending** | Cypress was told not to run it | `it.skip()`, the `xit()` alias, an empty `it('title')` body | | **skipped** | Cypress meant to run it but could not | a `before`, `beforeEach` or `afterEach` failed | **Pending is a decision you made. Skipped is a consequence you did not choose.** A run that reports one failure and fourteen skipped tests has not told you that fourteen tests are fine; it has told you it never learned anything about them. Treat the skipped count as unknown coverage for that run, not as a clean bill of health. ## Reading the report A useful order of questions when a suite comes back mostly skipped: 1. **Find the failed test, not the first one alphabetically.** The failure is attributed to the test the hook was serving, so the named test is often perfectly healthy. 2. **Read the appended sentence.** It names which hook — `before all` or `before each` — and which suite title stopped. That tells you whether one block or the whole file went down. 3. **Look above the test in the Command Log.** The failing command sits in the hook's own section, not in the test body, which is why the test's commands look empty. 4. **Ask what the hook depends on.** A hook that visits a route, seeds the catalogue, or reads a fixture is depending on something outside the test, and that dependency is what broke. 5. **Check whether the skipped tests would even have passed.** They are unknowns; do not report the run as "one failing test". There is one extra wrinkle worth knowing: Cypress does not re-attempt a test when a `before all` or an `after all` hook fails, and the error says so explicitly when attempts were configured. A per-test retry cannot rescue a broken suite-level hook. ## Keeping a hook from taking the block down The fix is almost never "wrap the hook in a try/catch". It is to make the hook do less, and to make what it does robust: - **Seed through the API, not the UI.** A `beforeEach` that clicks through the catalogue to create a borrow record has as many failure modes as a test; one that posts the record with `cy.request()` or a `cy.task()` has very few. - **Keep navigation and assertions apart.** Assertions inside a hook turn an unrelated regression into a whole-suite outage. Assert in the test. - **Put required resets in `before`/`beforeEach`, never in `after`/`afterEach`.** Teardown is not guaranteed to run, and a teardown that fails takes the block with it as well. - **Split the block.** If one hook is the shared prerequisite for fourteen tests, it is also a single point of failure for fourteen tests. Two smaller `describe` blocks with narrower hooks fail smaller. - **Watch for hooks that grow.** A hook that has accumulated a login, a seed, a cookie and a feature flag is where a spec's flakiness usually lives.
- In a Cypress report, what is the difference between a pending test and a skipped one?Pending is deliberate: the test has no body, was marked with `it.skip()` or `xit()`, or was excluded from the current browser. Skipped means Cypress intended to run the test but a shared `before`, `beforeEach` or `afterEach` failed first. Pending is a choice you can review; skipped is coverage the run lost.
- Why does Cypress skip the remaining tests instead of running them after a hook fails?Because the hook is shared: it would fail the same way for every remaining test in that block, producing identical failures and no new information. Stopping keeps the report readable and the run short. It also means the fix is to repair the hook, not to look for a pattern across the failures.
saying these in an interview costs you the question
- Reads skipped tests as tests that passed
- Debugs the named failing test instead of the hook
- Thinks a retry can rescue a failing before all hook
- Assumes an afterEach failure cannot fail the test
- Puts assertions in a hook shared by many tests