In a Playwright config, what does naming a project in another project's dependencies guarantee?
answer
- Ordering declared in the config
- An array of project names
- What happens downstream on failure
- The mirrored property for cleanup
basics
~10 sIt guarantees ordering: every test in the named project finishes before the dependent project starts, and if any of them fails, the dependent project's tests are skipped rather than run.
solid answer
~50 sA project's `dependencies` array holds the **names** of other projects that must run to completion first, so Playwright orders the run as a graph rather than a list. The usual shape is a setup project that selects preparation files with `testMatch: /.*\.setup\.ts/`, which the real projects then list in `dependencies`. If any test in the dependency fails, dependent projects are skipped, keeping one broken precondition from producing a wall of misleading failures. Cleanup is the mirror image: the setup project carries `teardown: '<project name>'`, and that project runs once, after the setup project and everything depending on it has finished. The advantage over an out-of-band script is that a setup project is made of real tests, so it gets fixtures, retries, a trace and a report entry. `dependencies` exists since Playwright 1.31 and `teardown` since 1.34.
code
typescript · 20 linesimport { defineConfig, devices } from '@playwright/test';
export default defineConfig({
projects: [
{
name: 'console-setup',
testMatch: /.*\.setup\.ts/,
teardown: 'console-teardown',
},
{
name: 'console-teardown',
testMatch: /.*\.teardown\.ts/,
},
{
name: 'admin-console',
use: { ...devices['Desktop Chrome'] },
dependencies: ['console-setup'],
},
],
});go deeper
Recall that dependencies holds project names and that those projects run first. Be able to read a config and say which project the runner starts with.
Explain the mechanics: the graph, how testMatch keeps preparation files out of the normal projects, the skip behaviour on failure, and where the teardown property is declared.
Show why this beats an external script for a real suite: traces and retries on preparation steps, small blast radius, and cleanup that runs once after every dependent finishes.
Own the graph's shape. Decide how many setup projects a suite should have, what each one may assume, and what the arrangement costs across a sharded pipeline.
## The guarantee `dependencies` gives you A project in `playwright.config.ts` may carry a `dependencies` array holding the **names of other projects**. The rule is simple and total: every test in every named project runs to completion before any test of the dependent project starts. Playwright builds a graph from these arrays and executes it in order, so a project named in `dependencies` is a hard precondition, not a hint. The array holds project names, never file paths or fixture names. `dependencies` has been available since Playwright 1.31, and the companion `teardown` property since 1.34. ## The setup-project idiom The project that runs first is an ordinary project whose tests happen to be preparation steps. Two things make it work: - It selects its own files with `testMatch`, typically a pattern such as `/.*\.setup\.ts/`, so the preparation files are claimed by it. - The real test projects use a pattern that does not match those files, so a preparation step never runs twice or as part of the normal suite. Because a setup project is a project, its bodies are real `test()` calls: they get fixtures, web-first assertions, retries and a trace, and they show up in the report like anything else. That is the whole appeal of the idiom over an out-of-band script. ## Failure and skip behaviour 1. A dependency project runs. If all of its tests pass, the graph continues. 2. If any test in it fails, Playwright does not run the projects that depend on it -- their tests are reported as skipped rather than failed. 3. The distinction is deliberate: a hundred red tests caused by one broken precondition would bury the real cause, so the report shows one failure and a wall of skips pointing at it. ## Teardown, and where the property goes `teardown` is set **on the setup project**, and its value is the name of another project. That named project runs after the setup project and everything depending on it has finished. Reading the config top-to-bottom, the pairing looks like this: | Property | Where it is declared | What it names | When the named project runs | |---|---|---|---| | `dependencies` | On the project that needs the precondition | Projects that must finish first | Before this project's tests | | `teardown` | On the setup project | One cleanup project | After the setup project and all its dependents finish | A common shape for an internal admin console suite: a `console-setup` project prepares the environment, several browser projects depend on it, and `console-setup` declares `teardown: 'console-teardown'` so the cleanup runs exactly once, after the last dependent project is done -- not after each one. ## Things the graph does not do - It does not deduplicate work per dependent. A setup project listed by four projects still runs once. - It does not make the dependency's fixtures visible to the dependent project; the two share only what they leave behind on disk or in the system under test. - It does not survive across invocations. A sharded CI matrix runs the graph inside every shard. - It is not a way to order tests inside a single project; that is what `test.describe.serial` and file ordering are for. ## Why teams move to it Before project dependencies existed, "run this first" meant `globalSetup`, a plain function outside the runner with no fixtures, no trace and no report entry. Expressing the same precondition as a project keeps it inside the test model, so when the preparation step breaks at 3am the failure looks like every other failure: a named test, a trace to open, and a retry policy that already applies to it. ## Reading a graph you did not write Three lines of a config tell you the whole order. Find the projects with no `dependencies` -- those start the run. Follow each `dependencies` array to see what waits on what. Then look for a `teardown` property, which is declared on a setup project and names the cleanup project that closes the phase out. Anything else -- file ordering, array position, alphabetical names -- has no effect on the order at all, which is exactly why the graph is worth keeping small enough to hold in your head.
- Four projects list the same setup project in dependencies. How many times does it run?Once per invocation of `playwright test`. The dependency graph is deduplicated, so the setup project executes a single time and all four dependents wait for that one execution. Sharding is the exception worth remembering: each shard is its own invocation, so the setup project runs once inside every shard.
- Why are dependent tests reported as skipped rather than failed when the setup project fails?Because they never ran, and marking them failed would hide the single real cause behind hundreds of red results. One failure plus a block of skips points straight at the broken precondition, and it also keeps flaky-test statistics honest, since tests that were never attempted do not count as failures.
saying these in an interview costs you the question
- Thinks dependencies lists file paths rather than project names
- Believes dependent tests still run after a failed dependency
- Puts the teardown property on the dependent project
- Thinks a setup project runs once per dependent project
- Assumes fixtures created in the setup project reach the dependents