Let's say you want to introduce Cypress End-to-End tests in your company. You probably already have a repository with lots of tests, and the CI build script is ... complicated. Can you add Cypress without modifying lots of installation and caching steps in the CI config file? Can you avoid your coworkers' anger?
Sure. At first, you can get away with not installing Cypress on CI. You can still run your initial tests (that are probably going to be simple) using a cypress/included Docker image with Cypress pre-installed.
Let's take an example application in bahmutov/todomvc-vercel. It is deployed to Vercel platform, and runs just the linting step using the GitHub Actions lint.yml workflow.
1 | name: lint |
Let's add Cypress NPM dependency.
1 | npm i -D cypress |
We can write a few tests, like this sanity spec.js
1 | /// <reference types="cypress" /> |
Let's see what happens next:
- the coworkers all get a Cypress binary on their machines the next time they run
npm install
oryarn install
. This binary is stored in the central folder on their machine, thus it is downloaded and unzipped once per Cypress version. It is 1-2 minute process, but that is acceptable. - the continuous integration server will install the Cypress binary on every workflow execution, to avoid this you need to configure Cypress caching. If you have a complicated CI workflow, this will be complicated.
We can take a middle path: we can use Cypress to run our tests without installing it on the CI during the NPM installation. Let's keep our lint workflow and just stop it from downloading the Cypress binary - since it is not going to run any Cypress tests.
1 | - name: Install dependencies |
By setting the environment variable CYPRESS_INSTALL_BINARY: 0
during the NPM installation step, we can skip the Cypress binary download. All our complicated workflows stay (almost) the same, and the caching during those workflows never sees any delays.
Let's move to the next task: we do want to run our Cypress tests after the deploy. Here is the simplest trick I know of: use cypress/included:x.y.z
Docker image, check out the source code to bring the specs to the local container, and call cypress run
to execute all tests. For example, after Vercel deploys the application, it triggers the GitHub deploy event. If the deploy is successful, we can grab the deployed URL and run Cypress tests against it.
1 | name: deploy |
You can see the tests running at bahmutov/todomvc-vercel/actions.
The cypress/included:x.y.z
container has the Chrome browser installed. You can see what is inside using the cypress info
command.
1 | # show the info about the browsers |
Nice - notice how fast the image executes, since nothing needs to be installed. On your CI, make sure to cache cypress/included:x.y.z
images to avoid pulling them from Docker Hub on each run.
Bonus: installing just Cypress plugins
After a while, you might add some Cypress plugins to your testing pipeline. Thus you would need to install them before running tests in the cypress/included
container. Just list the plugins to install explicitly.
1 | # if we did not _any_ Cypress plugins, we could skip the |
See the pull request #1. Of course, at this point you might set up NPM module caching just for the plugins.