The Importance of end-to-end Testing in Web Development: A Comprehensive Guide 🧪💻
Tags: testing, webdev, cypress, e2e
Published: 2023-01-23 15:40:07

When developing web applications, an important part is to **verify that everything works correctly for all possible use cases**. This can be done manually for simple applications, but for large applications with a lot of business logic, it is necessary to automate this task. 

That's why **testing is very significant in front-end development**, and there are several types: unit, integration, and **end-to-end (E2E)**.

### **When to Introduce Testing in a Project?**

It's crucial to understand that the **earlier you begin testing**, the better. It should be an integral part of the Front-end team's task definition. 

Implementing techniques such as **TDD (Test Driven Development)** is even better, as defining tests before developing the functionality forces you to anticipate any doubts and makes it easier to find solutions for any issues that may arise.

From my experience, there have been instances where we were **short on time and delivered functionality without testing 💥**. This not only creates uncertainty about whether any modifications might break other parts of the code, but also results in **costly tests done retrospectively**.

### **Benefits of end-to-end Testing**

E2E testing for web applications refers to simulating the behavior of a real user interacting with the application through a web browser. This helps to ensure that the application works as expected from the user's perspective.

The benefits of E2E testing include:

1. 💻 **Complete application overview.** Allows for simulation of a real user's behavior, providing a complete understanding of the application and ensuring that all components are working correctly together and meeting user expectations.
2. 🕵️‍♀️ **User interface error detection.**  Helps to ensure the user interface of the application is functioning correctly and that there are no errors that could negatively impact the user experience.
3. 🔎 **Integration error detection.** It helps confirm that different components of the system are properly integrated and that there are no integration errors that could affect the application's performance.
4. 💰 **Cost-effective in the long term.**  Although it may be more time-consuming to maintain and slower than other types of testing, E2E testing detects errors early in the development process, allowing for efficient and cost-effective corrections.
5. 🚀 **Continuous improvement.** By implementing E2E testing from the beginning, we can ensure that our application is functioning correctly and meeting user expectations, allowing for future improvements and code refactoring.
6. 📝 **Documentation.** End-to-end tests serve as valuable documentation throughout the development process, especially when requirements change or certain behaviors of the application need to be remembered.

**E2E testing** is a crucial tool for ensuring that an application is functioning correctly from the user's perspective and that all components are properly integrated. Despite being slower and more costly to maintain than other types of testing, the benefits outweigh the drawbacks, and it helps prevent **major issues in the future**🛡.

### **How to Begin Creating E2E Tests**

Cypress is a popular framework for conducting E2E testing in JavaScript. It is **easy to install, configure**, and offers an **intuitive interface** with many features. 

Cypress **runs directly in the browser**, eliminating the need for configuring testing environments or running tests on different browsers and platforms.

To start using Cypress, it must first be installed as a **development dependency** in your project. Then, the Cypress interface can be opened with a specific command.

For instance, to install Cypress in a Nuxt project:

1. Install Cypress as a development dependency in your Nuxt project:
    
    ```
    npm install --save-dev cypress
    ```
    
2. Add a Cypress execution script in your package.json file, for example:
    
    ```
    "scripts": {
        "cypress:open": "cypress open"
      }
    ```
    
3. Start your project in development mode using the command `npm run dev` or `yarn dev`.
4. Run the command `npm run cypress:open` to open the Cypress interface.
5. Launching Cypress for the first time, you will be guided through a wizard that will create a `cypress.config.js` for you.
    
    ```
    const { defineConfig } = require('cypress')
    
    module.exports = defineConfig({
      e2e: {
        baseUrl: '<http://localhost:1234>',
      },
    })
    ```
    

### **Structure of an end-to-end test in Cypress**

Once you have installed Cypress as a development dependency in your project, you can create a `cypress` folder at the root, and inside it, an `integration` folder to store your Cypress tests.

Each Cypress test file should have the `.spec.js` extension and can contain multiple test functions. For example:

```
describe('My App', () => {
    it('Visits the app root url', () => {
        cy.visit('/');
        cy.contains('h1', 'Welcome to My App');
    });
});
```

1. **describe():** It's a function that groups multiple `it()` related to each other under the same title or description. In the example above, it's used to describe `My App`.
2. **it():** It's a function that contains a specific use case. In the example above, it's used to visit the root URL of our app.
3. **cy object:** Cypress that provides a variety of commands to interact with the application. In the example above, the visit() command is used to simulate a visit to a specific URL, and `contains()` is used to check if a specific element contains a specific text. In the example above, we check if the page contains a h1 tag with the text `Welcome to My App`.

One of the advantages of Cypress is that it provides us with a lot of functions to interact with the application. You can check all of them in its [official documentation](https://docs.cypress.io/api/commands/and).

It's important to mention that Cypress allows us to create **asynchronous tests** using the `cy.wait()` function. This is useful when we need to give our application time to perform an action before continuing with the flow of the test.

**To run the tests**, you can use the command `npm run cypress:run` in the command line, or you can open the Cypress interface with the command `npm run cypress:open` and run the tests from there.

👉 **Keep in mind that Cypress requires the application to be running on a local server before running the tests**, thus, verify that your project is running before executing Cypress.

### **My Experience in a Real Project 💼**

In [64 Robots](https://www.64robots.com/), we decided to implement E2E testing at the start of a project. It was costly and required a learning and setup process at first, but we were able to deliver the first version of the product with a very low error rate. Being able to detect errors before they reach production is a great way to address them in a timely manner. Additionally, it kept the client satisfied as we delivered a stable and robust product.

Here are some things I've learned during my experience with testing

- 🧪 The **quality of the tests** is crucial in order to maintain trust in their results.
- 📝 Starting with a **user story** can be a helpful approach when writing a test.
- 🛠️ Cypress advises [against the use of conditionals](https://docs.cypress.io/guides/core-concepts/conditional-testing#docusaurus_skipToContent_fallback), if you find yourself needing them, it's worth re-evaluating the test's behavior.
- 💻 Planning the **structure of E2E tests** during the feature development stage is effective as the business logic is still fresh in mind, which will save time in the long run.
- 🔎 Having dedicated **test data** can aid in covering all possible use cases and provide a solid foundation to work with.
- 📚🚀 Starting with E2E testing can be challenging, but with **time and practice**, the quality of your tests will improve.

### **Conclusions**

In conclusion, while E2E testing can be more time-consuming in the short-term, it offers **long-term benefits to your project** that make it worth the time invested. **Cypress is a valuable tool** for E2E testing, with its intuitive interface and ample functionalities, it makes writing simple and complex tests quick and efficient.

I hope this article has helped you understand the importance of including E2E testing in your projects. If you have any questions or need more information, feel free to leave a comment 💬. Good luck with your tests! 🍀