Playwright example
This example packages an existing Playwright suite. The same pattern works for Cypress, WebdriverIO, or pytest: start from an image with the browsers installed, copy the suite in, and point its reporters at TestFleet_ARTIFACTS_DIR.
Directorycustomer-portal/
Directorysrc/ the application
- …
Directorye2e/
Directorytests/
- checkout.spec.ts
- Dockerfile
- package.json
- playwright.config.ts
Configure the reporters
Section titled “Configure the reporters”Read the target from the environment, and write the JUnit report, the HTML report, and traces into the artifacts directory. Outside TestFleet the variable is not set, so a local run writes to test-results/ as usual.
import { defineConfig } from "@playwright/test"
const artifacts = process.env.TestFleet_ARTIFACTS_DIR ?? "test-results"
export default defineConfig({ testDir: "./tests", // Failed tests stay failed: TestFleet should see what a user would see retries: 0, reporter: [ ["list"], ["junit", { outputFile: `${artifacts}/junit.xml` }], ["html", { outputFolder: `${artifacts}/playwright-report`, open: "never" }], ], outputDir: `${artifacts}/results`, use: { baseURL: process.env.BASE_URL, screenshot: "only-on-failure", trace: "retain-on-failure", video: "retain-on-failure", },})The list reporter prints one line per test, which is what you follow live on the run page.
Write the Dockerfile
Section titled “Write the Dockerfile”Use Microsoft’s Playwright image with the same version as @playwright/test in your package.json. It contains the browsers and their system dependencies, and a non-root user, pwuser.
# Keep the version in step with @playwright/test in package.jsonFROM mcr.microsoft.com/playwright:v1.56.0-noble
WORKDIR /suiteCOPY package.json package-lock.json ./RUN npm ciCOPY . .
# The artifacts directory must belong to the user the suite runs asRUN mkdir -p /TestFleet/artifacts && chown -R pwuser:pwuser /TestFleet
USER pwuser# Exec form: Playwright receives SIGTERM directly when a run is cancelledCMD ["npx", "playwright", "test"]Leave the test definition’s command empty: the image’s CMD runs the suite.
Build and publish
Section titled “Build and publish”TestFleet pulls the image from a registry on every run of a tag, so the image has to be pushed. Tag it with the application’s version, so the suite tested is the suite that belongs to the release.
docker buildx build --platform linux/amd64,linux/arm64 \ -t ghcr.io/acme/portal-e2e:1.4.2 --push e2e/Build for linux/arm64 too if TestFleet runs on an ARM host. The Playwright images exist for both platforms.
For a private registry, an admin adds its credentials under Registries once. See Registries.
Configure it in TestFleet
Section titled “Configure it in TestFleet”-
Environment: add
BASE_URL, and the test user’s credentials as secret variables, for exampleE2E_USERandE2E_PASSWORD. -
Test definition: image
ghcr.io/acme/portal-e2e:1.4.2, no command. Browser suites usually want:- a timeout that covers a slow day, for example 30 minutes
- 2 or more CPUs and 4096 MiB of memory, depending on the number of workers
- the default 2048 MiB of shared memory; Chromium crashes with Docker’s default of 64 MiB
-
Run now. The run page shows the
listoutput live; when the run is finished, the tests panel shows each test’s result, and the artifacts panel links the HTML report and the traces.
Keep it in step with the application
Section titled “Keep it in step with the application”The application’s pipeline builds and pushes the E2E image with the same version as the application, deploys, and then asks TestFleet to test that version:
sh ci/testfleet-run.sh customer-portal e2e staging 1.4.2This updates the test definition’s tag, starts a run, streams its log, and fails the pipeline unless the run passed. See Run tests from a pipeline.
- Workers: Playwright uses half the CPU cores it sees by default. With a CPU limit, set
workersexplicitly, for exampleworkers: 2for a 2-CPU limit, so the browsers are not starved. - Sharding: a large suite can be split into several test definitions with the same image that run in parallel. Each gets the full command, one argument per line:
npx,playwright,test,--shard=1/3, and so on for2/3and3/3. Raise the environment’s concurrency limit so they can run at the same time. - Viewing traces: a trace is a
.zipin the artifacts. Download it and open it withnpx playwright show-trace trace.zip, or drop it on trace.playwright.dev.