Every optimisation in the previous lecture makes the same suite faster. This one questions whether the whole suite should run at all, which is a bigger lever and a harder conversation.
The default nobody chose. Most teams run everything on every commit because that is what the first pipeline did, and nobody revisited it. As the suite grows, that default quietly becomes the reason engineers stop waiting for tests.
Tier by risk and by speed.
Smoke, one to two minutes. Ten to twenty tests. Can users log in, load the main screen, and complete the core action? Runs on every commit, every branch, always. If this fails, nothing else matters.
Core, five to ten minutes. The critical journeys: checkout, the main create-read-update-delete flow, permissions. Runs on every pull request.
Full regression, as long as it takes. Everything. Runs on merge to the main branch, and nightly.
Deep, hours. Cross-browser matrices, large data volumes, long-running flows. Nightly or weekly.
The insight that makes this safe: a bug caught two hours later is nearly always fine; a suite engineers bypass catches nothing at all. You are trading a small increase in feedback latency for a large increase in whether the gate is respected.
Implementing it with tags.
describe('checkout completes with a valid card', { tags: ['@smoke', '@core'] }, () => { /* ... */ });
Then select at run time with a plugin such as @cypress/grep:
npx cypress run --env grepTags=@smoke
Keeping the tags honest is the part that decays. Two rules that hold up: a new test defaults to no tag, so it lands in full regression and someone must argue to promote it. And the smoke tier has a hard cap, twenty tests or two minutes. When someone wants to add one, something else must leave. A cap forces the prioritisation conversation that otherwise never happens.
Selective execution by change. The more advanced version: run only the tests affected by what changed. If the pull request touches only the checkout module, run checkout tests.
Be careful here, and be honest with your team about why. Mapping code changes to affected tests is approximate. A shared component change can affect anything. Most teams that do this successfully use it to prioritise (run likely-affected tests first, for fast feedback) rather than to exclude, keeping a full run on merge. That distinction is worth insisting on, because "we only ran the relevant tests" is how a regression reaches production with a green pipeline.
The delete conversation, again. Before optimising which tests run, ask which should exist. A test that has never failed in two years, on a screen with negligible traffic, is costing you on every run in every tier. Tiering it down is fine. Deleting it is often better and nobody will miss it.
How to present this to a manager. Not "we want to run fewer tests", which sounds like reducing quality. Say: "engineers currently wait forty minutes and have started merging without waiting, so the gate is not working. This plan gives them two-minute feedback on every commit and keeps full coverage on merge." That is the same change described as what it actually is.
Remember this: tier by risk, cap the fast tier, and prioritise rather than exclude when selecting by change.
Reference: cypress-grep.