Implementing Cypress Testing into a Codefresh Pipeline

Cypress.io is a next generation front end testing tool built for the modern web. It is utilized by developers or QA engineers building web applications using modern JavaScript frameworks.

They are an extremely robust end-to-end testing platform, and are very extensible. Cypress can test anything that runs in a browser. This makes it a very powerful tool, and perfect to implement into a CI/CD pipeline. For this we’ll need an application to work with.

The Kitchen Sink

Today, we’re going to use a sample application published by the Cypress.io team called Kitchen Sink, and will show how to integrate Cypress testing into a Codefresh pipeline.

Kitchen Sink GIF

This also works out because Codefresh is not included in the example pipeline configs here, so we will have a chance to contribute the finished pipeline YAML to the project so others can use it to implement Cypress testing into their Codefresh pipelines.

The Pipeline

I have cloned the source repository in GitHub so we can use it as we see fit. I created a fresh pipeline in Codefresh, and it defaults to a basic 3-stage Pipeline. For the purposes of this demo, we’re going to nuke the Build stage out and just go with Clone and Test.

Default Pipeline YAML

Clone Stage

When you setup your pipeline in Codefresh, it asks you for some information, such as the Git reposity. From there, it automatically sets up the Clone stage for you. This makes things very easy, and we didn’t even have to make any changes to it.

steps:
  clone:
    title: "Cloning repository"
    type: "git-clone"
    repo: "vtimd/codefresh-blog"
    # CF_BRANCH value is auto set when pipeline is triggered
    # Learn more at codefresh.io/docs/docs/codefresh-yaml/variables/
    revision: "${{CF_BRANCH}}"
    git: "github"
    stage: "clone"

Test Stage

Let’s take a look at the default YAML for the test stage:

  test:
    title: "Running test"
    type: "freestyle" # Run any command
    image: "ubuntu:latest" # The image in which command will be executed
    working_directory: "${{clone}}" # Running command where code cloned
    commands:
      - "ls"
    stage: "test"

This gives us all the information that we will need to setup the proper test phase. So let’s break it down and make the changes we need to make. We’re going to leave the title and type as-is because the title is fine, and we are making a Freestyle task. For more info on tasks in Codefresh, check out this page.

The first change will be to the image lime. This is the container image that the Codefresh runtime will use for the stage. To make CI implementation easier, Cypress has a container image ready to go on Docker Hub. We’ll update the YAML replacing the stock Ubuntu image with our cypress image:

image: cypress/base

We’re going to leave the working_directory as it is, because we want to be working in the directory copied from GitHub in the Clone stage. The next section we’re getting into is building out the commands. This is the meat and potatoes of how we make this work. This stage loads the runtime container, then executes the commands inside the container environment. Let’s break down the commands, in order:

- npm ci

The first command is ‘npm ci’. We use this instead of ‘npm run’ to intiate the install of the required dependencies. This command starts by flushing out any modules used in any previous runs, to ensure a clean run.

This is what you should see in the output from the pipeline:

NPM CI

- npm run cy:verify

Next we’re going to run ‘npm run cy:verify’. This is going to run a check to make sure Cypress can run inside of the runtime environment.

The output of which will look like:

NPM RUN CY VERIFY

- (npm run start:ci &)

Now we need to start and run the app. We’re doing that with ‘npm run start:ci’. In order to make sure that this command runs in the background, we use the & symbol so that bash knows to background it. Though, this causes a syntax error. Due to issues with the execution of the commands in the runtime environment, I needed to put this command in parentheses. The error shown when you don’t do this looks like this:

BASH ERROR

With this change it is able to successfully execute the command, thus running the app in the background.

- npm run e2e

Now we need to execute the test against the app. To do this, we’ll run the ‘npm run e2e’ command. This runs the Cypress tests against the app. You will will see output in the pipeline similar to the following:

NPM RUN E2E

TEST RUNNING

And that’s it. We have made all the code alterations to the original YAML that we need to make the Cypress tests execute successfully in our Codefresh runtime environment. This is the chunk of code that we end up with in the final Pipeline YAML:

  test:
    title: "Running Cypress test"
    type: "freestyle" # Run any command
    image: cypress/base
    working_directory: "${{clone}}" # Running command where code cloned
    commands:
      - npm ci
      - npm run cy:verify
      - (npm run start:ci &)
      - npm run e2e
    stage: "test"

Conclusion

And with that, we run the pipeline and see that it successfully executes! It takes about 3 minutes and 12 seconds to clone the repo, load the environment, and run the tests.

SUCCESSFUL EXECUTION

To wrap things up, you can see that with pretty minimal effort, we were able to take a sample application, build a small test step, and successfully execute a Cypress test in a Codefresh pipeline. If you have any questions, or input, feel free to reach out on Twitter!

-Tim D. – Cloud and Developer Advocate