🚀🧪 Boosting Efficiency: Running E2E Tests Concurrently with Cypress and GitHub Actions

May 19, 2024 (5mo ago)

Motivation

As software projects grow, so does the time required for end-to-end (E2E) testing. In our team, running all E2E tests sequentially was taking up to 7 minutes, which significantly slowed down our development process. We needed a solution to reduce this wait time and improve our workflow efficiency without relying on Cypress Cloud services.

sequential E2E tests

Solution

To address this, I created a GitHub CI workflow that runs all E2E tests concurrently using Cypress. This approach leverages GitHub Actions to parallelize test execution, reducing the overall runtime to just 90 seconds—the duration of the longest single test. This significant improvement has been well-received by my colleagues, who are thrilled with the enhanced productivity and reduced waiting times.

conurrent E2E tests

concurrently E2E tests by running each spec as designated job

Workflow Description

Here's a breakdown of the GitHub CI workflow that I implemented to run E2E tests concurrently:

Build and Cache the Application

The first job, build-app-and-cache, checks out the code, installs dependencies, builds the application, and caches the dist and node_modules directories:

jobs:
  build-app-and-cache:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4
      - name: Install dependencies
        run: |
          yarn install --frozen-lockfile --legacy-peer-deps
      - name: Build app
        run: yarn build
      - name: Cache dist
        uses: actions/cache@v4
        with:
          path: dist
          key: dist-${{ github.run_id }}
      - name: Cache node_modules
        uses: actions/cache@v4
        with:
          path: node_modules
          key: node_modules-${{ github.run_id }}

Create a Test Matrix

The create-matrix job sets up a dynamic matrix to identify all Cypress spec files and output them for parallel execution:

  create-matrix:
    runs-on: ubuntu-latest
    outputs:
      matrix: ${{ steps.set-matrix.outputs.matrix }}
    steps:
      - name: Checkout
        uses: actions/checkout@v4
      - name: Set matrix
        id: set-matrix
        run: |
          echo "matrix=$(echo -n '{"include":['; find ./cypress/e2e/specs -name '*.spec.ts' -exec echo -n "{\"file\":\"{}\"}," \; | sed 's/,$//'; echo -n ']}')" >>$GITHUB_OUTPUT

Run E2E Tests Concurrently

The run-e2e-tests job restores the cached directories, installs necessary packages, and runs the Cypress tests concurrently using the matrix configuration:

  run-e2e-tests:
    needs:
      - build-app-and-cache
      - create-matrix
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix: ${{fromJson(needs.create-matrix.outputs.matrix)}}
    steps:
      - name: Checkout
        uses: actions/checkout@v4
      - name: Restore dist cache
        uses: actions/cache@v4
        with:
          path: dist
          key: dist-${{ github.run_id }}
      - name: Restore node_modules cache
        uses: actions/cache@v4
        with:
          path: node_modules
          key: node_modules-${{ github.run_id }}
      - name: Install test dependencies
        run: |
          yarn global add concurrently cypress
      - name: Run e2e tests
        env:
        run: |
          concurrently --success first --kill-others "DEBUG=cypress:server cypress run -C cypress.config.js --e2e -b chrome --spec ${{ matrix.file }}" "node cypress.server.mjs"

Complete the Workflow

Finally, the accomplish-e2e-tests job confirms the successful completion of the tests:

  accomplish-e2e-tests:
    needs:
      - run-e2e-tests
    runs-on: ubuntu-latest
    steps:
      - name: Check
        run: echo "E2E tests completed successfully"

Summary

This new CI workflow has drastically cut down the time required for running E2E tests from 7 minutes to just 90 seconds. By leveraging GitHub Actions to parallelize the tests, we’ve managed to streamline our development process significantly. My colleagues and I are delighted with the newfound efficiency, which allows us to iterate faster and maintain high-quality standards in our codebase.

⚙️️

Vue, Yarn, Cypress, E2E-Tests

v1.10.0