React E2E Testing made easy using Cypress and Jenkins

jochen

Jochen Rui

Posted on September 22, 2021

React E2E Testing made easy using Cypress and Jenkins

What is End-To-End(E2E) Testing?

The primary goal of E2E Testing is to test the Application from the user's perspective. Thus regarding the Application as a Black Box - ignoring the internal logic and only testing what the Users see.

Drawbacks of E2E Testing

An error in the E2E Test Suite indicates that the User can't use the Application as intended. The problem is that we can't pinpoint the exact Line Of Code(LOC) that causes the error. Thus E2E Testing helps in finding significant errors but can't help in debugging them.

On the famous Testing Pyramid, E2E Tests can be found on top of Component and Integration Tests. As such there should be Unit and Integration Tests first. These help in catching errors early and debugging, thus increasing the pace of development.

image

Benefits of E2E Testing

E2E Tests are written in a way that resembles the User's way of operating our Application. As such E2E Tests gives great confidence in our Application by confirming that the key functionalities are working as intended from the User's point of view.

In addition to this E2E Tests ideally don't rely on Implementation Details, as such they are more robust and written in a way where fixing or updating them is fast and easy.

Practical Example

Now to the fun part: Code!

First we have to install Cypress

npm install cypress --save-dev
or
yarn add cypress --dev
Enter fullscreen mode Exit fullscreen mode

Then we can create a simple cypress.json configfile in the root directory

{
    // specify the baseUrl from which we 
    // serve our applications in the test environment
    "baseUrl": "http://localhost:3000",

    // depends on project: allows accessing shadow dom without calling .shadow()
    "includeShadowDom": true,

    // optional: only necessary cypress component testing
    // not needed if all we do is e2e testing 
    "component": {
        "testFiles": "**/*.spec.{js,ts,jsx,tsx}",
        "componentFolder": "src"
    },
}
Enter fullscreen mode Exit fullscreen mode

if our project is written in typescript we might want to add a tsconfig in the cypress subdirectory that extends our main tsconfig

cypress/tsconfig.json

{
  "compilerOptions": { "types": ["cypress"] },
  "extends": "../tsconfig.json",
  "include": ["integration/*.ts", "support/*.ts", "../node_modules/cypress"]
}
Enter fullscreen mode Exit fullscreen mode

Writing Tests

After we finished the basic setup and installation we can now start writing tests.

describe("Sample Test Suite", () => {
  beforeEach(() => {
    // intercept outgoing HTTP Requests by defining the endpoint and mocked response
    cy.intercept("GET", "/some_endpoint", {
      statusCode: 200,
      body: {"a":1},
    });
  });

  it("sample test", () => {
    // uses baseUrl defined in cypress.json configuration
    cy.visit("/landing-page");
    // access DOM Nodes via e.g. class, id, data-test-id
    // & interact with DOM
    cy.get('[data-test-id="add-button"]').click();
    cy.get(".some_class").should("exist");
  });
});
Enter fullscreen mode Exit fullscreen mode

In the example above we intercept Http Requests our application makes to the /some_endpoint endpoint. Thus we mock the backend and can run our tests without starting up a backend instance.

Now we can run the tests and see if our application works as intended. For this we can choose to run it with a UI and open chrome instance for easier debugging OR we can run it headless, e.g. for a quick run in CLI or as integrated step in our CI Pipeline in e.g. Jenkins, Azure Pipeline,...

Run Cypress in Dev Environment

To execute Cypress with an UI and controlled Chrome instance we can add this script to package.json

"cy:open": "node_modules/.bin/cypress open",
Enter fullscreen mode Exit fullscreen mode

adding this allows us to easily start the cypress UI in the terminal

npm run cy:open
Enter fullscreen mode Exit fullscreen mode

Jenkins Integration

To integrate Cypress into our Jenkins Pipeline, we can add these scripts to package.json

"cy:run": "node_modules/.bin/cypress run",
"ci:e2e": "start-server-and-test start http://localhost:3000 cy:run"
Enter fullscreen mode Exit fullscreen mode

In addition we need to install start-server-and-test for this solution

npm install --save-dev start-server-and-test
Enter fullscreen mode Exit fullscreen mode

This will ensure that our server is started before we try running our E2E Tests.

Now that all the preparations are done, we can add a step to our Jenkinsfile.

sh script: 'cd frontend; npm run ci:e2e'
Enter fullscreen mode Exit fullscreen mode

Now when a Jenkins Build is triggered we will see a new stage in our Pipeline that displays a report of our E2E Tests.

image

Additional Information and Troubleshooting:

Depending on the Docker Image used, we may need to install additional OS specific dependencies. For this we can add a DockerFile step

# Install cypress OS dependencies
RUN apt-get install -qy \
    libgtk2.0-0 libgtk-3-0 libgbm-dev libnotify-dev libgconf-2-4  \
    libnss3 libxss1 libasound2 libxtst6 xauth xvfb procps
Enter fullscreen mode Exit fullscreen mode
💖 💪 🙅 🚩
jochen
Jochen Rui

Posted on September 22, 2021

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related