In Cypress, how far should a suite go to hand-shape its Command Log with Cypress.log() and { log: false }?
answer
- Write for the reader, not the author
- One entry per domain step
- Silence plumbing, never evidence
- Hand-written entries rot quietly
- Judge the artefact, not the call count
basics
~20 sFar enough that a failing run reads as domain steps to someone without the spec open, and no further. Add a Cypress.log() entry where a helper would otherwise be one opaque line; silence plumbing with { log: false }. Hand-written entries rot, so each must earn its upkeep.
solid answer
~50 sSet the bar by the reader, not the author: the person who opens a failing run at 3am without the spec in front of them. Use `Cypress.log()` where a custom command would otherwise appear as one opaque line and the data that explains its failure — a ticket id, a status code, a response body — exists only inside it. Use `{ log: false }` on the plumbing underneath: polling loops, setup requests, entries that repeat what the parent already says. Both cost maintenance, and a `consoleProps` naming fields the API stopped returning is worse than none. So the rule is one entry per **domain step**, not per HTTP call, plus a hard line: never silence a command whose failure is the thing you would need to see. A silenced command still runs and still fails the test — you have only deleted the line that said where.
go deeper
Know the two levers exist: Cypress.log() adds an entry for a custom command, and { log: false } hides a command's entry without changing what it does.
Explain why silencing a command is behaviour-neutral but evidence-negative, and give one case each where adding and removing an entry is the right call.
Show the operating view: which helper you would give a hand-written entry after triaging real failures, and how you would tell a noisy log from an uninformative one.
Own the standard and its cost. Say who the log is written for, why hand-written entries are code that rots, and what moves the line when a rotation rather than an author triages the suite.
## The question behind the question `Cypress.log()` and `{ log: false }` pull in opposite directions on the same surface. One **adds** an entry Cypress could not have written for you; the other **removes** entries Cypress wrote that nobody needs. Both are cheap to write once and are paid for forever, and both change what a future reader sees when a support-ticket suite fails in CI at three in the morning. So the useful framing is not "how much logging is good" but **who is reading, and what do they have?** The author of a spec, running it locally with the file open, needs almost none of this. Whoever is triaging a run they did not write, from a recorded artefact, has only the Command Log — and every entry you silenced is a sentence they cannot read. ## Where the line usually sits **Add a `Cypress.log()` entry when:** - A custom command is a black box whose failure would otherwise read as a single opaque line with no indication of which internal step broke. - The data that explains a failure only exists inside the command — an id, an HTTP status, a response body — and would otherwise be discarded when the command returns. - The helper represents a **domain step** a reader would name out loud: "assign the ticket", "seed twelve open tickets". Those are the units a triage narrative is written in. **Silence with `{ log: false }` when:** - One helper fires many near-identical commands — a poll loop, a batch of setup requests — and the entries are repetition rather than information. - An inner command's entry says nothing the parent entry does not already say. - An argument would be rendered into the log and should not be. **Do neither when** the command is already legible. Cypress's built-in entries are good; rewriting `cy.get('[data-cy=ticket-row]')` into a prettier line is churn with a maintenance bill. ## The costs people underweight 1. **Hand-written entries drift.** `consoleProps` closing over `res.body.assignedAgent` keeps compiling long after the API renamed the field; it just quietly prints `undefined`. A stale `consoleProps` is worse than none, because it looks authoritative. Anything you hand-write here needs to be as maintained as the assertions. 2. **Silence is invisible.** `{ log: false }` changes no behaviour: the command still runs, and if it fails the test still fails. What you removed is the line that would have said *where*. A suite that has silenced its setup is a suite whose setup failures all look alike. 3. **Every entry is also a decision about what a recorded run carries.** Whoever reads the run later sees exactly the entries you left. That is a legibility budget, not a free surface. 4. **Effort concentrates in the wrong place.** Log shaping is satisfying work with visible output, which makes it easy to spend an afternoon on a helper that has never failed while a genuinely opaque one stays opaque. ## A defensible standard For a team, I would write it down roughly as: 1. **One log entry per domain step.** A custom command that means something to the business gets exactly one entry, with `displayName` short enough to scan and `message` carrying the identifying value. 2. **`consoleProps` carries what you would ask for first.** The identifiers and the response fields you would want if the step failed — no more, so there is less to rot. 3. **`{ log: false }` on the plumbing inside that command**, never on the step itself. 4. **Never silence the command whose failure is the interesting one.** If you are unsure, leave it logged; noise is recoverable, missing evidence is not. 5. **Review the artefact, not the code.** The test of whether a helper's log entry is good is reading a run where it failed. Judging by counting `Cypress.log()` calls in review measures the wrong thing. ## Where the line honestly moves - **Who triages.** A suite whose failures are read only by the person who wrote them can afford opacity. A suite triaged by a rotation cannot, and the rotation is exactly who cannot afford to reconstruct a helper's internals. - **How long a helper has lived.** A brand-new command has not earned hand-maintained `consoleProps` yet. One that three people have debugged has. - **How the failure is read.** If failures are usually reproduced locally in open mode, the log matters less because the reader can pause and step. If they are read from a recorded run, the log is the whole story. - **How volatile the API is.** Against a stable internal API, `consoleProps` naming response fields is cheap. Against one changing weekly, keep it to identifiers you own. ## The answer, compressed Shape the log until a failing run reads as a sequence of domain steps to someone without the spec, and stop. Reach for `{ log: false }` to remove repetition, never to remove evidence. Treat every hand-written entry as code that must be maintained, and let the ones nobody has ever needed stay unwritten.
- A Cypress helper silences its inner commands with { log: false } and then fails. What has the team lost?The location. The silenced command still ran and its failure still failed the test, so the run is correctly red — but the entry that would have said which internal step broke is gone, leaving one opaque line. That is the asymmetry to reason from: silencing is free when everything passes and expensive exactly when it does not. Silence repetition, not the step whose failure you would need to read.
- How would you stop hand-written Cypress consoleProps from drifting away from the API?Keep them small and anchored to things you own — the identifiers the test passed in — rather than mirroring a response shape that changes underneath you. Anything derived from a response should be read from one place the suite already parses, so a rename breaks a test rather than silently printing `undefined`. And review them the way you review assertions: by reading a run where the helper failed, not by reading the call.
saying these in an interview costs you the question
- Treats more logging as unconditionally better
- Silences setup commands to make a run look tidy
- Thinks { log: false } stops the command running
- Writes consoleProps for helpers that never fail
- Judges log shaping by counting calls in review