Utilizing Github actions, to run multiple Cypress specs in parallel
Starting at the route of your project create a .github/workflows/ directory. This is where you will be defining and creating your different workflows. Each workflow will be responsible for running their own set of jobs and steps.
Workflow Name
name: Cypress Automation
Workflow Schedule
I like to set both a cron schedule as well as a workflow dispatch. The dispatch will allow for manually triggering these jobs if you ever find it necessary to.
on:
schedule:
- cron '0 14 * * *'
workflow_dispatch:
Environment Variables
Usually this is where you would read in any defined secrets you already have stored in your github repository secrets. Note that Cypress environment variables should be prefixed with CYPRESS_
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CYPRESS_TEST_ENV: 'staging'
Workflow Jobs
Note that jobs run in parallel and there are a couple variations you can do to write these more efficiently.
The most basic way I would define my jobs is as follow:
jobs:
e2e_can_chrome:
name: Canada End-To-End Suite(Chrome)
runs-on: ubuntu-latest
timeout-minutes: 50
steps:
- name: Checkout
uses: actions/checkout@v2
# Install NPM dependencies, cache them correctly
# and run all Cypress tests
- name: Setup Report
run: yarn clean:reports
- name: Clean Cache
run: yarn cache clean
- name: Install Dependencies
run: yarn install
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Canada E2E on Chrome
uses: cypress-io/github-action@v2
with:
browser: chrome
spec: cypress/integration/web-client/canada/end.to.end.spec.ts
env:
# pass the Dashboard record key as an environment variable
CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
# Recommended: pass the GitHub token lets this action correctly
# determine the unique run id necessary to re-run the checks
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CYPRESS_COUNTRY_HEADER: 'ca'
CYPRESS_COUNTRY_SHORT_CODE: 'CAN'
CYPRESS_STORE_ID: '3001'
- name: Copy Screenshots
run: yarn copy:screenshots
if: failure()
- name: Notify Slack
run: yarn alert:slack
if: failure()
- name: generate report
if: always()
run: yarn generate:report
- name: Upload Report
uses: actions/upload-artifact@v2
if: always()
with:
name: Canada Chrome End-To-End Report
path: cypress/reports/mochareports/
Some things to note from above:
The if conditions that can be seen above will allow me to control when to run certain steps. I utilize this in order to run a yarn command to send slack alerts on when a job is not successful
The env noted above allows you to override any defined env variables defined on the higher upper scope of you workflow file. This can be useful when trying to define env variables that are specific for just one specific test run. Example of this would maybe you want to run the same script for two different countries.
The artifact upload is useful to save or upload reports or html files to an artifact making it available for download on Github
Optimizations
The downside to structuring your workflow files as I outlined above is eventually you end up with too many jobs that your workflow file becomes far too big. As you would be creating a single job for every spec file you have.
One better way to handle this limitation is to utilize the strategy matrix expansion. This would essentially spin up multiple containers to run test in.
jobs:
setup:
name: Run 3 test in parallel
runs-on: ubuntu-20.04
strategy:
fail-fast: false
matrix:
# run 3 copies of the current job or set of specs in parallel
containers: [1, 2, 3]
However this method comes with a heavy cost. It requires setting up recording to the Cypress Dashboard. A paid subscription with the utilization of the cypress dashboard is needed.