December 01, 2024
9 minutes read
Automation testing has become an integral part of modern software development, and tools like Playwright have made it seamless to perform end-to-end testing. However, executing these tests in a continuous integration pipeline can be challenging without proper setup. In this guide, we will go through the steps to run Playwright tests in a Jenkins pipeline using Docker, ensuring an efficient and scalable testing process. By the end of this post, you’ll have a clear understanding of setting up Jenkins with Docker, connecting agent nodes, and creating pipelines to build and run tests.
Before starting, ensure you have the following:
Docker Desktop
installed on your local machine.Docker Hub
account created for managing Docker images.Before starting, let us look at the architecture. Jenkins Controller/Agent Architecture
allows distributed builds, where tasks are delegated to agents for execution. This architecture improves scalability and resource utilization.
Controller Node
Agent Node
Communication Flow
To set up Jenkins using Docker, create a docker-compose.yml file. Organize your directory as follows:
jenkins-docker/
├── docker-compose.yml
└── volumes/
├── master/
└── node/
Here’s the docker-compose.yml file:
services:
jenkins:
image: jenkins/jenkins:lts-jdk17
user: root
ports:
- 8080:8080
- 50000:50000
volumes:
- ./volumes/master:/var/jenkins_home
environment:
- JAVA_OPTS="-Dhudson.model.DirectoryBrowserSupport.CSP="
Explanation
jenkins
: Define service which will be created by Docker Compose.
jenkins/jenkins:lts-jdk17
: Docker image to create the container
user
: We have specified user as root
to run the container with root privileges. This is necessary for certain administrative tasks (like installing plugins, setting permissions, or managing files)
ports
will map the ports on the host to the container. 8080:8080
maps the Jenkins web UI. 50000:50000
maps the port used for Jenkins agent communication
volumes
: Mounts a host directory (./volumes/master) to the container’s Jenkins home directory (/var/jenkins_home). This will persist Jenkins data even if the container is deleted.
JAVA_OPTS
: Configure JVM options for Jenkins.
-Dhudson.model.DirectoryBrowserSupport.CSP=
: Disables Jenkins Content Security Policy. Although not recommended in production, but useful for embedding resources like images or styles in Jenkins view.
To start Jenkins, run:
docker-compose up
Once Jenkins service has started, you can acces Jenkins at http://localhost:8080
on your host machine.
Once complete, the Jenkins files will be available in the volumes/master
directory.
Follow these steps to connect an agent:
Set up an agent
NODE1
as the node name, select Permanent Agent
, and configure the Remote root directory with the path to the node directory on your host.Now you will see a new node NODE1
is created which will be displayed with the Built-in Node.
Click on the NODE1
and you will see the instructions to run the agent.
Navigate to node
directory in your local machine from the terminal and run the commands provided by Jenkins to connect the node.
Tip: Set the number of executors for the Built-in Node to 0 to ensure jobs only run on connected agents.
Built-in Node
> Configure
Number of executers
to 0 and click on Save.You can use the Playwright Cucumber Framework or your own Playwright project. For this guide, we will use Docker to build the test environment and Jenkins to execute the tests.
This framework is built using Playwright and Cucumber. Instead of using the default Playwright command to execute tests, a custom
index.ts
file has been created to run the tests using the Cucumber runner.To execute the tests, run the command
npm run cucumber <tag_name>
Predefined tags, such as
smoke
,regression
, etc., are specified in theindex.ts
file. Replace<tag_name>
with one of these predefined values to run the corresponding test suite.
We need to install below plugins inside Jenkins:
To install the plugins,
Manage Jenkins
> Plugins
> Available Plugins
To run jenkins again, run docker-compose up
again.
Create a Dockerfile
in your project:
FROM mcr.microsoft.com/playwright:v1.48.2-noble
WORKDIR /app
COPY . /app
RUN npm install
ENTRYPOINT ["sh", "-c", "npm run cucumber ${TEST_TARGET}"]
Explanation
Base Image
FROM mcr.microsoft.com/playwright:v1.48.2-noble
uses Playwright docker image to build our docker image.
Set Working Directory
WORKDIR /app
sets the working directory inside the container to /app
. All subsequent commands and operations (e.g., COPY, RUN) will be executed relative to this directory.
Copy Files
COPY . /app
Copies the contents of the current directory (on the host) into the container’s /app directory.
Install Dependencies
RUN npm install
Installs Node.js dependencies from the package.json file.
Entry Point
ENTRYPOINT
Defines the command to execute when the container starts.
Manage Jenkins
> Credentials
(global)
under Domains column.Username with password
Create a Jenkinsfile
in your project:
pipeline {
agent any
stages {
stage('Build Image') {
steps {
sh "docker build -t=<username>/playwright:latest ."
}
}
stage('Push Image') {
environment {
DOCKER_HUB = credentials('dockerhub-creds')
}
steps {
sh 'echo ${DOCKER_HUB_PSW} | docker login -u ${DOCKER_HUB_USR} --password-stdin'
sh "docker push <username>/playwright:latest"
sh "docker tag <username>/playwright:latest <username>/playwright:${env.BUILD_NUMBER}"
sh "docker push <username>/playwright:${env.BUILD_NUMBER}"
}
}
}
post {
always {
sh "docker logout"
sh "docker system prune -f"
}
}
}
Explanation
Agents
agent any
Stages
The pipeline has two primary stages:
stage('Build Image')
<username>/playwright:latest
.**Note: **
<username>
refers to your Docker Hub username. Replace<username>
with your actual Docker Hub username wherever it is mentioned.
stage('Push Image')
docker push <username>/playwright:latest
pushes the latest version of the Docker image to Docker Hubdocker tag <username>/playwright:latest <username>/playwright:${env.BUILD_NUMBER}
tags the image with the jenkins build number (e.g., 1, 2, etc.)docker push <username>/playwright:${env.BUILD_NUMBER}
pushed the versioned image to Docker HubPost
post
docker logout
logs out from Docker Hubdocker system prune -f
cleans up unused docker dataCreate a New Pipeline
Pipeline
and click OK.Pipeline script from SCM
.git
.Branch Specifier
for your repository. (e.g., */main
)Clean before checkout
.Jenkinsfile
(ensure the Jenkinsfile is located in the root directory of your repository).Build the Image
Build Now
.For running our tests, we will be creating a separate jenkins pipeline. Create another directory for running tests (e.g., playwright-runner) and include Jenkinsfile and Docker Compose file.
In the root directory, create a docker-compose.yml
file:
services:
playwright-test:
image: <username>/playwright
environment:
- TEST_TARGET
- BROWSER_CHOICE
volumes:
- ./reports:/app/reports
Explanation
Services
playwright-test
: defines the serviceImage
image
: We will be using the prebuild image <username>/playwright
which contains the Playwright test environment.Environment Variables
environment
: Passes enviroment variables to the container.TEST_TARGET
: This will be used to pass the specific tags to run the test.BROWSER_CHOICE
: This will be used to pass the specific browser.Volumes
volumes
: Mounts ./reports
directory on host to /app/reports
directory on container.
In the same directory, create a Jenkinsfile
file:
pipeline {
agent any
parameters {
choice choices: ['login', 'smoke', 'regression', 'faker'], name: 'TEST_TARGET'
choice choices: ['chromium', 'firefox'], name: 'BROWSER_CHOICE'
}
stages {
stage('Run Test') {
steps {
sh "docker-compose up --pull=always"
script {
def rerunExists = sh(script: '[ -f reports/rerun.txt ] && [ -s reports/rerun.txt ]', returnStatus: true) == 0
if(rerunExists) {
error("Some tests failed.")
}
}
}
}
}
post {
always {
sh "docker-compose down"
archiveArtifacts artifacts: 'reports/*.html, reports/*.json', followSymlinks: false
}
}
}
Explanation
Agent
agent any
: Run pipeline on any available agent.Parameters
parameters
: Allows users to provide input when triggering the pipeline.Stages
stage('Run Test')
: Defines the stage for the pipeline.docker-compose up --pull=always
: Launches the Dockerized testing environment defined in the docker-compose.yml file pulling the latest image.script
: Uses a shell script to check if the reports/rerun.txt file exists and is non-empty. If its not, the pipeline fails with an error.Post
always
: Defines actions that are always executed regardless of the pipeline’s success or failure.docker-compose down
: Shuts down the Docker containers and cleans up any associated resources.archiveArtifacts artifacts
: Collects test reports (e.g., HTML and JSON files) from the reports directory and stores them in Jenkins as build artifacts.Now setup a github repository and push the code.
Create New Pipeline
Pipeline
and click OK.Pipeline script from SCM
.git
.playwright-runner
. (For private repositories, set up credentials for GitHub in Jenkins and select the credentials here.)Branch Specifier
for your repository (e.g., */main
).Clean before checkout
.Jenkinsfile
. (ensure the Jenkinsfile is located in the root directory of your repository)Run Pipeline
Click Build Now.
Note: The first build will run with the default parameters specified in the Jenkinsfile, as you will not be provided with parameter choices initially.
Run with Parameters
View Build Artifacts
Once the pipeline is executed, you can check the build artifacts attached to the pipeline job.
This guide has covered the complete setup to run Playwright tests in a Jenkins pipeline using Docker. From configuring Jenkins with Docker to creating pipelines for building and running tests, each step ensures a streamlined and scalable testing process. Using this setup, you can integrate your Playwright tests seamlessly into your CI/CD pipeline and maintain a robust testing environment.