When you install Playwright for the first time, you get three projects by default: Chromium, Firefox, and WebKit. This creates a false feeling that Playwright projects configuration is only about cross-browser testing. Not really true. You can do a lot more with projects, like grouping and running your tests in ways that actually match how your team works.
Let's dive in.
Do You Really Need Cross-Browser Testing?
Here is a little secret while nobody is listening. Most engineers run their tests just in Chrome. I know some of you might say, "Hey, we have requirements to run in Safari or Firefox." Yeah, sometimes that is a requirement. But if your tests pass in Chrome, you have about an 80% chance they work just fine in other browsers too.
Why?
Chrome holds roughly 70-80% of the browser market share. If your application works correctly in Chrome, it is very likely safe to release. So instead of spending resources on cross-browser execution, you can use projects for something that will actually help you organize your test suite.
Let's see how.
How to Configure Playwright Projects for Test Groups
So let's move on. We run our tests only in Chrome. What do we use the projects section for?
Remove the extra browsers and create two Chrome-based projects with different purposes:
// playwright.config.tsimport { defineConfig, devices } from '@playwright/test';export default defineConfig({ projects: [ { name: 'SmokeTests', use: { ...devices['Desktop Chrome'] }, testMatch: /.*smoke.spec.ts/ }, { name: 'RegressionTests', use: { ...devices['Desktop Chrome'] }, testIgnore: /.*smoke.spec.ts/ }, ],});
See what happened? The SmokeTests project uses testMatch to only run files matching smoke.spec.ts. The RegressionTests project uses testIgnore to run everything else.
Now your projects in the Playwright Test Runner reflect actual test categories, not browsers. You can click on "SmokeTests" or "RegressionTests" in VS Code and run exactly the group you need. Or target them from the command line:
npx playwright test --project=SmokeTests
Yes, that simple :)
How to Set Up Playwright Project Dependencies
Here is where it gets interesting. You can create dependencies between projects. Say you want to run regression tests only if your smoke tests pass first. Makes sense, right? Why run the full regression suite if the basics are already failing?
export default defineConfig({ projects: [ { name: 'SmokeTests', use: { ...devices['Desktop Chrome'] }, testMatch: /.*smoke\.spec\.ts/, }, { name: 'RegressionTests', use: { ...devices['Desktop Chrome'] }, testIgnore: /.*smoke\.spec\.ts/, dependencies: ['SmokeTests'], }, ],});
When you trigger RegressionTests, Playwright sees the dependency on SmokeTests. It runs all smoke tests first. If any smoke test fails, the regression project gets skipped entirely. No point running regression if the basics are broken.
Data Setup and Teardown with Playwright Projects
Projects are not limited to running actual test files. You can create dedicated projects for data setup and cleanup too.
Data Setup Project
Create a project that prepares test data before your smoke tests run:
export default defineConfig({ projects: [ { name: 'DataSetup', testMatch: /.*data-load.setup.ts/, teardown: 'DataCleanup', }, { name: 'SmokeTests', use: { ...devices['Desktop Chrome'] }, testMatch: /.*smoke\.spec\.ts/, dependencies: ['DataSetup'], }, { name: 'RegressionTests', use: { ...devices['Desktop Chrome'] }, testIgnore: /.*smoke\.spec\.ts/, dependencies: ['SmokeTests'], }, { name: 'DataCleanup', testMatch: /.*data-cleanup.setup.ts/, }, ],});
Look at the execution chain this creates:
DataSetupruns first, preparing the test dataSmokeTestsrun next (dependent onDataSetup)RegressionTestsrun after that (dependent onSmokeTests)DataCleanupruns at the very end (configured asteardownforDataSetup)
The teardown property does the magic here. By adding teardown: 'DataCleanup' to the DataSetup project, Playwright knows to execute the cleanup after all dependent projects finish. The data that was created in the database gets cleaned up automatically.
You can also have multiple dependencies for a single project. If your regression tests depend on two separate setup steps, just list them both:
{ name: 'RegressionTests', dependencies: ['SmokeProject1', 'SmokeProject2'],}
Both projects must pass before regression kicks in. And you see the flexibility here, right? You can organize your tests however it makes sense for your application.
Per-Project Configuration in Playwright
On the framework level, you have configurations like testDir, fullyParallel, forbidOnly, retries, and more. Almost all of these properties can also be set at the project level. And when you set them at the project level, they override the framework defaults.
Override Parallel Execution
Let's say your smoke tests must run sequentially, but regression tests can run in parallel:
export default defineConfig({ fullyParallel: true, // framework-level default projects: [ { name: 'SmokeTests', fullyParallel: false, // override: run sequentially testMatch: /.*smoke\.spec\.ts/, }, { name: 'RegressionTests', // inherits fullyParallel: true from framework level testIgnore: /.*smoke\.spec\.ts/, }, ],});
SmokeTests overrides the framework setting and runs tests in sequential order. RegressionTests inherits the framework-level fullyParallel: true. Easy!
Override Workers, Retries, and Timeouts
You can fine-tune each project with its own retries, workers, and timeout:
{ name: 'SmokeTests', retries: 0, // no retries for smoke tests timeout: 15000, // shorter timeout},{ name: 'RegressionTests', retries: 2, // allow retries for regression workers: 4, // limit parallel workers timeout: 60000, // longer timeout},
Override Use Options Per Project
The use block is available both at the framework level and the project level. You can override properties like baseURL, viewport, trace, and any other test option:
export default defineConfig({ use: { baseURL: 'https://staging.example.com', trace: 'off', }, projects: [ { name: 'SmokeTests', use: { ...devices['Desktop Chrome'], baseURL: 'https://production.example.com', // different environment trace: 'on', // enable traces for smoke tests viewport: { width: 1920, height: 1080 }, }, }, ],});
Running the same tests against different environments with different browser settings per project. No brainer at all!
Framework-Level vs Project-Level Configuration
Not all properties are available at the project level. For example, reporter is a framework-level only property. You cannot set a different reporter per project.
How do you know what is available where?
Go to the Playwright documentation. The TestConfig page lists all framework-level properties. The TestProject page lists what you can configure per project. And TestOptions covers everything available inside the use block.
Here is a quick reference:
Configuration | Framework Level | Project Level |
|---|---|---|
| Yes | Yes |
| Yes | Yes |
| Yes | Yes |
| Yes | Yes |
| Yes | No |
| Yes | No |
| Yes | Yes |
| Yes | Yes |
| Yes | Yes |
Documentation is your best friend. Always refer to it when you are unsure about what can be configured where.
How to Run Playwright Projects from the Command Line
By default, running npx playwright test executes all projects. To target a specific project, use the --project flag:
# Run only smoke testsnpx playwright test --project=SmokeTests# Run only regression tests (will also trigger dependencies)npx playwright test --project=RegressionTests# Run multiple specific projectsnpx playwright test --project=SmokeTests --project=RegressionTests
When you trigger a project that has dependencies, Playwright automatically runs the dependency projects first. So running --project=RegressionTests in our example also triggers SmokeTests and DataSetup automatically. You do not need to specify them manually.
In VS Code with the Playwright Test extension, you can see all your projects in the test runner sidebar. Click on the project name to filter tests by that project. If you want to learn how to set up Playwright in VS Code from scratch, check out that guide.
Best Practices for Playwright Projects Configuration
You are unlimited in how many projects you can create. But make sure you do not get lost with a long list. Keep them reasonably small and organized.
Use descriptive names like SmokeTests, RegressionTests, APITests, not Project1, Project2. If someone new joins the team, they should understand why each project exists just by reading the config file. If they can't, your project names need work.
Only create dependencies when the execution order truly matters. Unnecessary dependencies slow down your pipeline. And keep setup/teardown projects focused on one thing, whether that is preparing data, configuring state, or handling authentication with storage state. Do not combine unrelated setup tasks into a single project.
If your tests are flaky and you suspect it might be related to project configuration, check out the guide on how to fix Playwright flaky tests. You can also set up your projects to run in GitHub Actions CI/CD for automated execution on every pull request.
Final Thoughts
Think about projects as logical groups of tests with their own configuration, not just browser targets. Start simple, create a smoke and regression split. Add dependencies when you need execution order. Override per-project settings when different test groups need different configurations. And check the official Playwright documentation for the full list of options. You can also explore data-driven testing to combine with your project setup for even better test organization.
Playwright is growing in popularity in the market very quickly and will become a mainstream framework that replaces Selenium over time. Get the new skills at Bondar Academy with the Playwright UI Testing Mastery program. Start from scratch and become an expert to increase your value on the market!
Frequently Asked Questions
What are Playwright projects used for?
Playwright projects let you define logical groups of tests that run with their own configuration. While the default setup uses them for cross-browser testing, you can use projects to organize smoke tests, regression tests, data setup, teardown, and more.
How do Playwright project dependencies work?
You add a dependencies array to a project with the names of projects that must run first. If any test in a dependency project fails, the dependent project is skipped.
Can I override Playwright config settings per project?
Yes. Most configuration properties like fullyParallel, retries, timeout, workers, and all use options can be set at the project level. Some properties like reporter and globalSetup are only available at the framework level.
What is the teardown property in Playwright projects?
The teardown property specifies another project that should run after all dependent projects complete. It is commonly used for cleaning up test data that was created during a setup project.
How many Playwright projects can I create?
There is no limit. Create as many as you need, but keep the list organized. If your config file is hard to read, you probably have too many.
Should I run Playwright tests in all browsers?
Most of the time, Chrome alone covers about 80% of real user scenarios. Add cross-browser projects only when you know your application has browser-specific behavior that needs testing.
