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.
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.
E2E Tests are written in a way that resembles the user's way of operating our application. As such E2E Tests give us 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.
Now to the fun part: Code!
First, we have to install Cypress.
npm install cypress --save-dev
or
yarn add cypress --dev
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"
},
}
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"]
}
After we finish 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");
});
});
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 an integrated step in our CI Pipeline in Jenkins or Azure Pipeline, etc.
To execute Cypress with a UI and controlled Chrome instance, we can add this script to package.json
"cy:open": "node_modules/.bin/cypress open",
Adding this allows us to easily start the cypress UI in the terminal.
npm run cy:open
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"
In addition, we need to install start-server-and-test
for this solution.
npm install --save-dev start-server-and-test
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'
Now when a Jenkins Build is triggered, we will see a new stage in our Pipeline that displays a report of our E2E Tests.
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
This article was first published at: https://dev.to/jochen/react-e2e-testing-made-easy-using-cypress-and-jenkins-42jm.