Automated tests only deliver value when they run on every change. Here's how I set up Playwright suites on the two CI platforms I use most.
CircleCI
CircleCI's strengths are caching and parallelism. Cache the browser binaries and
node_modules, then split specs across containers with the built-in test
splitting.
version: 2.1
jobs:
e2e:
docker:
- image: mcr.microsoft.com/playwright:v1.48.0-jammy
parallelism: 4
steps:
- checkout
- restore_cache:
keys:
- deps-{{ checksum "pnpm-lock.yaml" }}
- run: pnpm install --frozen-lockfile
- save_cache:
key: deps-{{ checksum "pnpm-lock.yaml" }}
paths:
- node_modules
- run: pnpm playwright test --shard=$((CIRCLE_NODE_INDEX+1))/$CIRCLE_NODE_TOTALBitbucket Pipelines
Bitbucket Pipelines is simpler and tightly integrated with Bitbucket repos. Use
the official Playwright image and Bitbucket's caches to avoid reinstalling
browsers each run.
pipelines:
pull-requests:
"**":
- step:
name: E2E
image: mcr.microsoft.com/playwright:v1.48.0-jammy
caches:
- node
script:
- pnpm install --frozen-lockfile
- pnpm playwright testKeep feedback fast
- Shard long suites across containers so wall-clock time stays low.
- Cache dependencies and browser binaries — installs dominate cold runs.
- Fail fast on PRs, but keep a fuller nightly run for cross-browser coverage.
- Upload artifacts (traces, videos, HTML reports) so failures are debuggable without re-running locally.
The platform matters less than the habit: every push should give the team a clear green or red within a few minutes.