Parallelize Cypress in CircleCI

2021-10-04 3 min

Cypress offers the option to run tests in parallel. But running in parallel implies the recording feature which involves creating an account in the cypress Dashboard. Of course, it is free for a limited amount of results. And I’m sure is good but the parallelization feature is not an option without using the Cypress Dashboard service.

Anyway, there’s always an alternative solution.

The cypress command supports passing as an argument a matching list of files to test by using the —-spec operator.

cypress run --spec cypress/integration/hello.spec.js, cypress/integration/bye.spec.js

Even a glob pattern.

cypress run --spec cypress/integration/**/*.js

Therefore, we can use this feature to parallelize tests in the CI. But, let’s put this aside for now and configure the test job.

A job config looks as follows.

jobs:
  test:
    docker:
      - image: cimg/node:16.10.0
    parallelism: 2
    steps:
      - checkout
	  - run: npm run cypress

As you see, the only thing you need to do to parallelize a job is by adding the parallelism key to the configuration. In this example, we choose 2 parallel processes. We also could have chosen 4 or more cores. The number of processes does not affect the setup.

The next step is to split the tests files into two groups. One for each process.

For this matter, CircleCI offers a helpful command to split tests conveniently named circleci tests split.

The splitting command must be provided by a list of files to split. CircleCI has already tackled that issue with the command circleci tests glob.

The pipeline of both commands looks as follows.

circleci tests glob "cypress/integration/**/*.js" | circleci tests split --split-by=timings

Notice that the division has been done by timings. This means that the tests will be divided evenly ensuring that the processes take about the same amount of time.

To complete the command, store the returned list of test files in a variable.

TEST_FILES="$(circleci tests glob "cypress/integration/**/*.js" | circleci tests split --split-by=timings)"

The list of files returned from circleci tests split is a string of filenames separated by spaces. Cypress only accepts a list of filenames separated by commas.

I did not find if circleci tests split accepts a separator argument but we can replace the spaces by commas using the following bash syntax.

${TEST_FILES//$'\n'/','}

The first two forward slashes (//) mean that the change applies to all occurrences. The next value ($'\n') is the pattern that must be replaced — a space. And after the next forward slash delimiter, is the value to replace with — a comma.

The complete configuration is as shown below.

jobs:
  test:
	docker:
	  - image: cimg/node:16.10.0
	parallelism: 2
	  steps:
        - checkout
		- run: 
          name: Integration tests
          command: |
            TEST_FILES="$(circleci tests glob "cypress/integration/**/*.js" | circleci tests split --split-by=timings)"
            npm run cypress --spec ${TEST_FILES//$'\n'/','}

And that’s all it takes. Cypress now runs in parallel.

Hope it helps.

Sources