Getting Started with Playwright
Learning objectives
- You know what Playwright is.
- You know how to setup Playwright for your project.
- You know how to run end-to-end tests with Playwright.
Playwright is a framework for writing E2E tests. It provides an API that can be used to write tests that simulate the behavior of a user using a browser, testing that the web application works as expected.
Starting to set up Playwright
We start from the project template that we have earlier worked on. The template has a server (in the folder api
), database migrations (in the folder flyway
), and a user interface (in the folder ui
).
tree --dirsfirst -L 1
.
├── api
├── flyway
├── ui
├── docker-compose.yml
└── project.env
The project also contains a docker-compose.yml
file that defines the services that are used in the project. The contents of the file is as follows.
services:
api:
build: api
restart: unless-stopped
volumes:
- ./api:/app
ports:
- 8000:8000
depends_on:
- database
env_file:
- project.env
database:
container_name: postgresql_database
image: postgres:16.1
restart: unless-stopped
env_file:
- project.env
database-migrations:
image: flyway/flyway:10.0.0-alpine
env_file:
- project.env
depends_on:
- database
volumes:
- ./flyway/sql:/flyway/sql
command: -connectRetries=60 -baselineOnMigrate=true migrate
ui:
build: ui
restart: unless-stopped
volumes:
- ./ui:/app
ports:
- 5173:5173
depends_on:
- api
Setting up Playwright
To setup Playwright, we run the command npm init playwright@latest playwright
in the root folder of the project. The command creates a folder called playwright
and initiates a project for running Playwright tests, asking us for guidelines for setting up the project. We pick JavaScript as the language for writing tests, use tests
as the location for end-to-end tests, do not add GitHub actions workflow, do not install playwright browsers, and do not install playwright operating system dependencies.
Once done, the project has a new folder playwright
with the following contents (omitting node_modules
).
cd playwright
tree --dirsfirst
.
├── node_modules
│ └── ...
├── tests
│ └── example.spec.js
├── tests-examples
│ └── demo-todo-app.spec.js
├── package.json
├── package-lock.json
└── playwright.config.js
The playwright.config.js
provides the configuration for Playwright. For our purpose, the configuration is a bit excessive, so let's cut it down. Modify the configuration to match the following.
const { defineConfig, devices } = require('@playwright/test');
/**
* @see https://playwright.dev/docs/test-configuration
*/
module.exports = defineConfig({
testDir: './tests',
reporter: 'list',
use: {
baseURL: 'http://localhost:5173',
trace: 'off',
},
projects: [
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
},
],
});
In effect, we declare the directory for the tests and ask for the test results to be printed in a list format. Furthermore, we use http://localhost:5173
for the starting point for the tests, do not collect test traces, and run the tests using Chromium.
If you have Chromium installed in your system, you can try running the tests using the command npx playwright test
. The command runs the tests and prints the results in the terminal.
npx playwright test
Running 2 tests using 1 worker
✓ 1 [chromium] › example.spec.js:4:1 › has title (2.7s)
✓ 2 [chromium] › example.spec.js:11:1 › get started link (2.4s)
2 passed (7.2s)
If you do not have Chromium, no worries. We'll be running the tests with Docker and will download the necessary components there.
Playwright and Docker
To run the tests with Docker, we need to create a Dockerfile for Playwright.
Before starting, remove the
tests-examples
andnode_modules
folders from from theplaywright
folder, and remove also thepackage-lock.json
file.
Create a file called Dockerfile
into the folder playwright
with the following contents.
FROM mcr.microsoft.com/playwright:v1.40.0-jammy
WORKDIR /app
COPY package*.json .
COPY *config.js .
RUN npm install
RUN npx playwright install chromium
COPY . .
CMD [ "npx", "playwright", "test" ]
The above configuration uses the image mcr.microsoft.com/playwright:v1.40.0-jammy
as the base image, creates a folder /app
to the image and copies the configuration files to the folder. Then, we install the dependencies and the Chromium browser, which are used to run the tests. This is followed by copying the rest of the contents (i.e., the tests) to the image and finally, at the last line, the image is configured to run the tests using the command npx playwright test
.
Next, we wish to add Playwright to the Docker Compose configuration to allow us to run the tests using Docker Compose. To do this, we add the following service to the docker-compose.yml
file.
playwright:
entrypoint: "/bin/true"
build: playwright
network_mode: host
depends_on:
- ui
volumes:
- ./playwright/tests:/app/tests
The above configuration creates a service called playwright
that uses the Dockerfile we just created. The entrypoint
is used to indicate that we do not wish to run the tests by default (i.e., whenever we run docker compose up
). The service is configured to use the host network, which allows the service to access applications running on the host machine. The service depends on the ui
service, which is the user interface of the application. Finally, the service is configured to map the tests in the folder playwright/tests
to the container.
With the adjustments to the configuration, run the command docker compose up --build
to start the services and to create the Playwright image -- this might take a while on the first run.
Running the tests
With the project running, we can run the tests. The tests are run using the command docker compose run --rm --entrypoint=npx playwright playwright test
in the root folder of the project. The command runs the tests and prints the results in the terminal, removing the created test container after it has finished.
docker compose run --rm --entrypoint=npx playwright playwright test
[+] Creating 3/0
✔ Container postgresql_database Running 0.0s
✔ Container folder-api-1 Running 0.0s
✔ Container folder-ui-1 Running 0.0s
Running 2 tests using 1 worker
✓ 1 [chromium] › example.spec.js:4:1 › has title (1.5s)
✓ 2 [chromium] › example.spec.js:11:1 › get started link (2.3s)
2 passed (6.1s)