I ran into some difficulties a few weeks ago when attempting to run Cypress tests as part of my CI script in Gitlab. The application I was working with has a Golang backend and the front end is generated with Nuxt. As this project had private dependencies, my CI script built the application in separate stages. One for the server and one to generate static files. This pattern worked well for creating a final Docker image.
However; when trying to add E2E tests as part of the flow, I rapidly ran into issues. The articles I came across in my search were either outdated or provided incomplete solutions. In case you run into similar issues, here's what I did to get this running.
1 - Create a New Dockerfile for Cypress
Cypress does have an official Docker image that comes with all of the dependencies to run Cypress, except Cypress itself. As I didn't want to create a package.json
, nor did I want to install a bunch of dependencies that I wouldn't need for this step, I opted to take care of it inside of the Dockerfile.
FROM cypress/base:10
WORKDIR /app
# This allows for creating a package.json within the Dockerfile itself
RUN npm init --yes
RUN npm i cypress
# Copying both the test files and the config for cypress
COPY cypress cypress
COPY cypress.json .
# I had a local copy of this script, but it is easily findable online
COPY wait-for-it.sh
RUN chmod +x wait-for-it.sh
2 - Create a Docker Compose File
Now that I had a Dockerfile to run the Cypress tests, the next step was to get it to run against my application. I already had an existing Dockerfile to assemble my application, so all I needed to get it running was Docker Compose.
version: "3"
services:
web:
build:
context: .
dockerfile: "docker/Dockerfile.web"
ports:
- "8080:8080"
cypress:
build:
context: .
dockerfile: "docker/Dockerfile.cypress"
depends_on:
- web
environment:
- CYPRESS_BASEURL=http://web:8080
command: [
"./wait-for-it.sh", "web:8080", "-s", "-t", "0", "--",
"npx", "cypress", "run"
]
Since I had added the wait-for-it.sh
script to my Dockerfile, I was able to ensure that my application was running and accessible before attempting to run any tests against it.
3 - Update .gitlab-ci.yml to Run E2E Tests
The final step was to get Gitlab to run the tests. I've added a simplified version of my .gitlab-ci.yml
file below. The key things to get this working were:
- Setting the entrypoint as an empty string.
- Most of the examples I came across for running Cypress involved setting a custom entrypoint. However; Gitlab will continue to run
sh
as the entrypoint. - After a lot of digging, I found the solution here: Gitlab Runner Issue #2692
- Most of the examples I came across for running Cypress involved setting a custom entrypoint. However; Gitlab will continue to run
- Having docker-compose exit when the Cypress container shut down.
- This is needed in order to prevent the build from hanging as well as fail the build if the tests fail.
image: docker:stable-git
services:
- docker:dind
variables:
ARTIFACTS_DIR: $CI_PROJECT_DIR/artifacts
GO_LINK_OPTIONS: -s
cache:
paths:
- node_modules/
stages:
- build-test
- e2e-test
before_script:
- set -e
- if [ "$CI_JOB_NAME" = "build-test:go" ]; then apk update && apk add --no-cache build-base git curl bash docker; fi
- mkdir -p $ARTIFACTS_DIR
build-test:node:
image: node:12
stage: build-test
artifacts:
expires_in: 1 day
paths:
- $ARTIFACTS_DIR/
script:
- npm ci
- npm test
- npm run generate
- cp -r .nuxt $ARTIFACTS_DIR/.nuxt
- cp -r dist $ARTIFACTS_DIR/dist
build-test:go
image: golang:1.12-alpine
stage: build-test
artifacts:
expires_in: 1 day
paths:
- $ARTIFACTS_DIR/
script:
- cd cmd
- go test ./...
- go build -ldflags=all=$GO_LINK_OPTIONS -o $ARTIFACTS_DIR/$CI_PROJECT_NAME .
test:integration:
image:
name: docker/compose:1.24.0
# needed in order to be able to run custom scripts
entrypoint: [""]
stage: e2e-test
dependencies:
- build-test:node
- build-test:go
artifacts:
expires_in: 1 day
paths:
- $ARTIFACTS_DIR/
script:
# Copy buld artifacts
- cp -r $ARTIFACTS_DIR/dist ./dist
- cp -r $ARTIFACTS_DIR/.nuxt ./.nuxt
- cp -r $ARTIFACTS_DIR/$CI_PROJECT_NAME ./cmd/$CI_PROJECT_NAME
- docker-compose build
# Without this the build will hang and will not fail on failing tests
- docker-compose up --abort-on-container-exit --exit-code-from cypress
I hope this helps you resolve similar issues you may be facing getting Cypress to work in your CI scripts.
Originally published on jessie.codes.
Top comments (0)