DEV Community

Cover image for The Importance of end-to-end Testing in Web Development: A Comprehensive Guide 🧪💻
Míriam González
Míriam González

Posted on

The Importance of end-to-end Testing in Web Development: A Comprehensive Guide 🧪💻

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');
    });
});
Enter fullscreen mode Exit fullscreen mode
  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.

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, 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, 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! 🍀

Top comments (4)

Collapse
 
alenanik profile image
Alena Nik

Congrats on the article!
Actually, something that I personally looove e2e testing is for automatisation for a11y testing. You can plug-in this lines to your test setup and it's going to check a11y issues too (for cypress-axe)

it('Has no detectable a11y violations on load', () => {
// Test the page at initial load
cy.checkA11y()
})

super cool!

Collapse
 
miriamgonp profile image
Míriam González

Thanks Alena, I'll check it đź’ś

Collapse
 
crisoncode profile image
Cristian Estarlich • Edited

Quite useful, congrats for the post Miriam!

Just somethings to note that I faced working with Cypress.

  • Hard to maintain between some instances like environments for devs, staging and production. (Management of URLs)
  • Cypress can't work with external popups like Paypal login (new window or tab) .
  • We can't test anything on Safari (this is crucial, on our products +50% of the users are visiting our websites from Safari, iOS)
  • For some people the learning curve is hard specially for non JS experienced devs, as you know cypress is always working with promises.

after my words, some questions :D

  • Do you have this tests integrated in a CI/CD pipeline? one thing that I hate about E2E+Cypress is the velocity. In our case we split the tests in "minimal ones" called smoke tests an the full battery of tests are running in a isolated pipeline.

  • How many time are you investing in E2E tests in comparison of pure coding?

Collapse
 
jhoermann profile image
Jochen Hörmann

Thanks for the guide! I think in regards to the tooling there is currently a shift from Cypress to Playwright. Maybe that's something to consider for you, too.