Running Cypress Tests in Parallel on Multiple GitHub Actions Containers
This post walks through configuring your existing Cypress tests to execute in parallel on multiple GitHub Actions containers using the Cypress cypress-split
plugin.
The cypress-split
plugin will handle running the tests in parallel for you similar to how Cypress Cloud does but is a free solution without the extra features of Cypress Cloud.
TL;DR
See this repo for an example solution using the cypress-split
Cypress plugin to run tests in parallel on multiple GitHub Actions containers.
If you wish to use a different CI for your tests you can refer to the official documentation here.
For these steps I will be referencing this example Cypress repo which runs tests from 3 files.
Install cypress-split Package
In your existing Cypress test framework install the cypress-split
package as a dev dependency.
npm i -D cypress-split
Call Cypress Split from Cypress Config
In your cypress.config.js
file add the require to import function cypressSplit
form cypress-split
.
Call the cypressSplit
function with on
and config
arguments within the setupNodeEvents
object and be sure to return config
const { defineConfig } = require('cypress')
const cypressSplit = require('cypress-split')
module.exports = defineConfig({
e2e: {
baseUrl: 'https://www.testingnotebook.com',
setupNodeEvents(on, config) {
cypressSplit(on, config)
return config
},
},
})
Create your GitHub Workflow
Below is an example of a GitHub Action Workflow which is using this plugin to run the tests in quiet mode.
You can see the strategy is set as 3 contains and the plugin read environment variables strategy.job-total
& strategy.job-index
to split the test specs per machine, uncomment these values to use.
If any tests fail then a screenshot of the failing test will be published to the job artifacts.
If you don't have a workflow created yet save the below snippet in .github/workflows/main.yml
.
name: Cypress Tests
on:
push:
branches:
- main
schedule:
- cron: '0 13 * * 0'
jobs:
build:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
containers: [1, 2, 3]
steps:
- name: Checkout repo
uses: actions/checkout@v2
- name: Run Cypress tests
uses: cypress-io/github-action@v5
with:
quiet: true
env:
SPLIT: # environment variable called strategy.job-total see https://github.com/testingnotebook/cypress-split-example/blob/main/.github/workflows/main.yml#L21
SPLIT_INDEX: # environment variable called strategy.job-index see https://github.com/testingnotebook/cypress-split-example/blob/main/.github/workflows/main.yml#L22
- name: Upload screenshots
uses: actions/upload-artifact@v3.1.3
if: failure()
with:
name: cypress-screenshots
path: cypress/screenshots
If you are working with GitHub Actions on VSCode you can install an extension like GitHub Actions by Mathieu Dutour to help with the validation. Or you can edit the workflow file directly from GitHubs online editer.
Test Your Workflow
In the e2e
directory there are 3 spec files called about.cy.ts
, homepage.cy.ts
and post.cy.ts
so each agent should one of the 3 files.
Below is the output from each agent showing the 3 files were successfully split as expected. You can see the output of these builds on this repo
Agent 1
cypress-split: there are 3 found specs
cypress-split: chunk 1 of 3
cypress-split: specs from the current directory /home/runner/work/cypress-split-example/cypress-split-example
k spec
- -----------------------
1 cypress/e2e/about.cy.js
about
✓ should avatar and author (2260ms)
1 passing (2s)
Agent 2
cypress-split: there are 3 found specs
cypress-split: chunk 2 of 3
cypress-split: specs from the current directory /home/runner/work/cypress-split-example/cypress-split-example
k spec
- --------------------------
1 cypress/e2e/homepage.cy.js
home page - recent posts
✓ should contain recent posts elements (1588ms)
1 passing (2s)
Agent 3
cypress-split: there are 3 found specs
cypress-split: chunk 3 of 3
cypress-split: specs from the current directory /home/runner/work/cypress-split-example/cypress-split-example
k spec
- ----------------------
1 cypress/e2e/post.cy.js
post
✓ should contain recent posts elements (1817ms)
1 passing (2s)
For more information on this package see the official readme.
The code used for this post can be found here.