I'll keep using Playwright in this series, but you can make similar optimizations with other tools.
The fact that unoptimized E2e tests are very slow.
Fortunately, you can fix that.
Obvious bad practices to avoid
Long tests
While it may seem obvious, it does slow your runs and it's a pain to debug.
Imagine, 45 lines of assertions, not to mention the setup.
Splitting long tests in to smaller tests is rewarding and can even help catch nasty glitches.
Manual waits
While some configurations can be tricky, using manual waits, such as await page.waitForTimeout(5000), is a bad choice.
Not only that it will slow your tests on purpose, but it's prone to race conditions and other async shifts that lead to flaky tests.
Just remove all occurrences of waitForTimeout.
Permissive configurations in playwright.config.ts
No specific config for CI/CD
You can leverage process.env.CI to apply specific configurations for your CI, as pipelines usually require different settings than your local machine.
Max retry/timeouts
Increasing max retries or timeouts just to make your tests pass is a time bomb, and will slow your CI.
I'm a big fan of retries: 0, but I'm also pragmatic:
// playwright.config.ts
retries: process.env.CI ? 2 : 1,
Alway trace on
Always-on traces will bloat your CI. Instead, you may use retain-on-failure:
// playwright.config.ts
use: {
trace: 'retain-on-failure',
},
This will trace all tests but delete the previous.
Definitely less obvious speed killer
Testing pure logic/validation
E2e tests are not meant to verify business rule calculations, date diffs, or form validation logic.
While you may think you're testing the UI (e.g., forms), you're actually re-assessing the internal logic.
Use web-first assertions instead and focus on what users see.
Back to the playwright.config.ts file
Each worker requires a browser process and an isolated Node.js process.
Too many or to few workers can kill your speed!
Workers run your tests in parallel. If you set max workers to 1, it becomes sequential:
npx playwright test --workers=1
I could recommend that:
// playwright.config.ts
workers: process.env.CI ? 1 : undefined,
It's just what you need for basic projects, and it opts out of parallel tests on CI (value set to 1).
The truth is there's no universal configuration, as usual, but it's better to make the CI config predictable, regardless of your context.
More tests vs. better coverage
More tests means more maintenance.
It's best if you review e2e tests regularly and ditch the potentially unnecessary ones.
Headless vs. headed mode
// playwright.config.ts
use: {
headless: false, // or true?
},
Headless means no GUI rendering, which seems good for CI pipelines.
In contrast, you may want a display for your local environment for debugging purposes.
Only enable headless mode where it's needed:
// playwright.config.ts
use: {
headless: !process.env.CI
},
Top comments (0)