Seth Lutske
Seth Lutske

Parallelizing Cypress with Jenkins, AWS, and Sorry Cypress

Parallelizing Cypress with Jenkins, AWS, and Sorry Cypress

If you're using Jenkins, and you have access to cloud compute resources, you can run cypress in parallel across multiple virtual machines. This will significantly cut down your cypress run time. This article is a recipe for how to do that.

This blog post is a courtesy of Seth Lutske. The original publication can be found here.


Cypress.io is an elegant end-to-end test runner for any front end project, and has become an industry standard. But for many enterprise-level projects, cypress tests stack up, and can take lots of time to run. This can slow down your CI/CD builds, and ultimately your project's development.

If you're using Jenkins, and you have access to cloud compute resources, you can run cypress in parallel across multiple virtual machines. This will significantly cut down your cypress run time. This article is a recipe for how to do that.

What you will need

  • Your project, which includes cypress tests
  • A Jenkins server
  • Cloud compute resources (AWS EC2 instances, OpenStack instances, etc.)

We use historical data to improve parallelization strategy. That results in shorter and consistent runs duration.

Running Cypress in Parallel with Jenkins on cloud
Running Cypress in Parallel with Jenkins on cloud

When I first began experimenting with these tools, I struggled to understand how they all worked together. Let's set it up step by step.

Create your Jenkins agents

Jenkins can coordinate tasks across different agents, so you'll need to create some virtual machines and add them as Jenkins nodes.

Set up your VMs

You'll need to fire up some instances on your preferred cloud provider. Launch an instance, and in your preferred way (ssh, PuTTY, etc.), make sure you install at least these requirements on your instances:

  • Node and npm (Required by Cypress and likely your project)
  • Java (required by Jenkins)
  • Requirements for Cypress
  • Any other system requirements your project needs to run

I recommend setting up one instance with all your needs, then creating a snapshot of that instance. You can launch more instances from that snapshot, making the creation of new Jenkins agents very quick.

Add your VMs to Jenkins as Nodes

Now that your VMs are ready, add them to Jenkins as Nodes. For a quick read on how to do that, check out this tutorial

Set up Sorry Cypress

Cypress.io's documentation explains that to run cypress tests in parallel, all you have to do is run the command:

cypress run --record --key=abc123 --parallel

What's implied (poorly) is that this requires use of the Cypress.io dashboard service. This is a paid service, and it requires uploading your project's code to a third party cloud service.

If this doesn't work for you, Sorry Cypress to the rescue! Sorry Cypress allows you to host a Cypress dashboard on your own cloud services and use it to coordinate parallel cypress testing.

For the cloud-based approach that we are taking, here are a few quick setup steps:

  1. Create a new cloud instance that will be the dedicated to running the Sorry-Cypress suite of applications. Note this will not necessarily require the same boilerplate installations as your other instances. It will not be used as a Jenkins agent, but your Jenkins agents and the Sorry-Cypress instance must be able to communicate via http.
  2. Install docker and docker-compose on your Sorry-Cypress instance. Once installed, its a breeze to install and run the entire Sorry-Cypress suite of applications using their docker-compose script.

Now you have your own sorry-cypress dashboard running on your own cloud resources. To check it, navigate to your-sorry-cypress-instance-ip:8080, and you'll see your dashboard.

Utilizing Sorry-Cypress

In order to get your project to actually use sorry cypress, you'll need to make some small changes. In your cypress.json, add a projectId of sorry-cypress:

// cypress.json:

{
  "baseUrl": "http://localhost:3000",
  "projectId": "sorry-cypress",
  ...otherOptions
}

You'll also want to install cy2 in your project, which will help guide cypress towards your custom cypress dashboard URL.

For more details, see the full Sorry-Cypress Documentation: https://docs.sorry-cypress.dev/

Setting up Parallelization in Jenkins

Now that all the pieces are in place, its time to orchestrate them with Jenkins. Let's say we created 3 instances to be used as Jenkins agents, named “agent-1”, “agent-2”, and “agent-3”. We tell Jenkins to run cypress in parallel across these agents in a pipeline script:

stage ('Cypress'){
    parallel {
        stage('Cypress 1') {
            agent {
                node {
                    label 'agent-1'
                }
            }
            steps {
                sh 'npm install --silent'
                sh 'npm start & npx wait-on http://localhost:3000'
                sh "CYPRESS_API_URL=\"http://Sorry-Cypress-Instance-IP:1234/\" npx cy2 run --record --key XXX --parallel --ci-build-id env.BUILD_ID"
            }
        }
        stage('Cypress 2') {
            agent {
                node {
                    label 'agent-2'
                }
            }
            steps {
                sh 'npm install --silent'
                sh 'npm start & npx wait-on http://localhost:3000'
                sh "CYPRESS_API_URL=\"http://Sorry-Cypress-Instance-IP:1234/\" npx cy2 run --record --key XXX --parallel --ci-build-id env.BUILD_ID"
            }
        }
        stage('Cypress 3') {
            agent {
                node {
                    label 'agent-3'
                }
            }
            steps {
                sh 'npm install --silent'
                sh 'npm start & npx wait-on http://localhost:3000'
                sh "CYPRESS_API_URL=\"http://Sorry-Cypress-Instance-IP:1234/\" npx cy2 run --record --key XXX --parallel --ci-build-id env.BUILD_ID"
            }
        }
    }
}

You can see that each parallel stage is running the same steps, but on a different node. Let's break down what steps are being run:

  • npm install --silent - install the project on the agent
  • npm start & npx wait-on http://localhost:3000 — starts the project and waits for it to be available on port 3000 (your particular project may differ)

The third command is more complicated, so let's break that down further:

  • CYPRESS_API_URL=\"http:Sorry-Cypress-Instance-IP:1234/\" - sets the cypress api url environment variable to our personal sorry-cypress directory url. Use your Sorry-Cypress instance IP of course
  • cy2 - a cy alternative that utilizes the CYPRESS_API_URL environment variable
  • run --record --key XXX --parallel - the standard cypress parallelization command — the key can be anything, sorry-cypress does not actually use it
  • --ci-build-id env.BUILD_ID — all parallel stages will use the same BUILD_ID, which allows the Sorry-Cypress director to associate the different parallel stages with the same build and not repeat the same tests across nodes

Now when your Jenkins job runs, it will run cypress tests in parallel across as many nodes as you define. Let's revisualize all our pieces in a more organized fashion:

Running Cypress in Parallel with Jenkins on cloud
Running Cypress in Parallel with Jenkins on cloud

Conclusion

Cypress tests are a great way to make sure your UI behaves as expected, but testing cake take time and slow down your dev process. If you've got cloud resources, use them. With a careful orchestration of resources using Jenkins, you can cut down your testing time significantly.

More Resources

Parallelization on Sorry Cypress using Jenkins