Stud2design LogoBlog

Understanding Web App Testing

publish date

4 September, 2024

read time

12 mins

coverSource: https://unsplash.com/@kaleidico

Understanding Web App Testing

When many of us started developing applications, we often did so without writing test cases, taking pride in our work and enjoying the process. However, upon joining an organisation or beginning a project, we quickly realised that including test cases is a necessity, and how it speeds up our workflow so we can develop software faster. Understanding why testing is crucial in application development can clarify why companies emphasise writing test cases.


As a developer or maintainer, it's important to understand that testing is not just a bureaucratic requirement; it is a fundamental part of ensuring the reliability and functionality of your application. Without understanding the what, why, and how of testing, one might be tempted to skip it altogether. However, by grasping the reasoning behind testing, we can appreciate its value.

What is testing

Testing is a process where the test program throws an error when the actual result of something does not match the expected output. The goal of any testing is that you try your best to make sure that something unexpected doesn't happen, or at least what the user is expecting works fine for sure.


It is important to know that testing never guarantees that all will be fine, but rather helps you assert that certain elements of your app will be working as expected based on how good your tests are. As a start, you focus on the part which your app can't do without like the “Add to cart” button is clickable and the cart being updated after it's clicked.

Why testing is important

Testing plays a crucial role in maintaining and improving code quality by catching bugs early. Testing enables developers to identify potential issues before they escalate, leading to a more robust and maintainable codebase. As software projects grow, they naturally accumulate complexity, and the ability to refactor code safely is paramount.


The key to productivity in software development lies in reducing cognitive load. When developers have fewer things to worry about, they can focus more on solving the actual problems at hand. Automated tests serve as a form of documentation, ensuring that certain conditions remain true as the code evolves. This provides the developers with the necessary confidence to write code more freely, knowing that their tests will alert them if anything goes wrong.


Testing is essential in software development because it not only ensures that your code functions as expected, but also simplifies the development process. It boosts productivity, facilitates team collaboration, and instils confidence in developers. By making testing an integral part of the development process, teams can ensure that their software is reliable, maintainable, and scalable.

What should you test

It is essential to recognise that testing isn't about covering every line or condition of your code. Instead of merely increasing code coverage, testing should prioritise the outcomes and assess whether the code fulfils its intended purpose, meeting both your expectations and those of the user.


Note ✍🏽Code coverage is a metric that can help you understand how much of your source is tested

When users interact with your app, they engage with the interface, not the underlying code. Therefore, your test cases should focus on verifying that user interactions behave as expected. When crafting test cases, the goal should be to evaluate the product's flow: Does the app function as intended? Are user actions, such as clicks or changes, triggering the correct responses?


Also, when writing test cases, one of the most frustrating aspects is having to update them every time the code changes. This often happens because the test cases are focused on the wrong part of the code—specifically, the implementation details. When tests are too tightly coupled with the underlying implementation, even minor code changes can necessitate extensive updates to the tests.

The more your tests resemble the way your software is used, the more confidence they can give you - Kent C. Dodds

The React Testing Library, created by Kent C. Dodds, was developed with this exact concern in mind. The library emphasizes the importance of testing the app's behaviour from the user's perspective rather than focusing on the internal workings of the code. By following this approach, you can create more resilient tests that remain stable even as the implementation evolves. You can read more about it here.

Levels of Testing

Different levels of testing—Unit Testing, Integration Testing, and End-to-End (E2E) Testing—address different aspects of the application's functionality. Together, they create a robust testing strategy that covers the application from individual components to full workflows.

Unit Testing

Unit testing focuses on testing individual components or “units” of code in isolation. The goal is to verify that each part of the application behaves as expected under various conditions. Unit tests make it easier to refactor code confidently, knowing that any issues in the individual components will be caught.

Integration Testing

Integration testing aims to test how different modules or components of the application work together. It ensures that the interactions between different parts of the application function correctly. It verifies that data is correctly passed between different parts of the application.

E2E Testing

E2E testing simulates real user scenarios and tests the entire application from start to finish. By mimicking user interactions, E2E tests help ensure that the application delivers a smooth and error-free experience to the end user. This type of testing ensures that the application behaves correctly in a real-world environment, covering everything from user input to the final output. By testing the full stack, E2E tests can identify issues that might not be apparent at the unit or integration levels.

Effective Strategy: The Testing Pyramid

A commonly recommended approach is the testing pyramid:


This strategy ensures a balanced trade-off between coverage, speed, and thoroughness, offering an effective and scalable approach to web app testing.


The modern take on the testing pyramid is the testing trophy by Kent C. Dodds.


testing-trophy Source and Credit: Kent C Dodds's Blog

Types of testing

As we learned about different levels of testing, it's important to recognize that these are not the only types of testing. Several other testing methods play a crucial role in ensuring the quality and reliability of a web application. Some of these additional types of testing include:

Functional Testing

Security Testing

Performance Testing

Usability Testing

Compatibility Testing


Testing impact on code

Testing helps us ensure we don't break existing code when making changes. Testing also plays a critical role in helping us structure our code more effectively. By prioritising testability, we naturally improve the separation of concerns, making our code cleaner and more maintainable. However, it is important to remember that tests exist to describe the intention behind the system, not to dictate how the code is written.


Few practices you can follow to make code more testable, avoid doing real work in constructors—use them only to store passed-in dependencies. Control dependencies explicitly by using dependency injection, allowing for easy substitution with mocks during testing. Follow the Law of Demeter by passing only the necessary data to methods, reducing test complexity. Avoid global state to ensure tests are isolated and do not interfere with each other. Keep your code modular and simple, with each component having a single responsibility, and avoid closing over external variables. These practices lead to more reliable, maintainable, and easily testable code.


While these practices encourage writing good testable code, we should be cautious not to let tests influence the code in ways that hinder development. For example, it's essential to avoid tightly coupling the code with the tests, as this can make the system harder to change. Tests should verify the behaviour and outcome of the system without forcing the code into rigid patterns simply to accommodate the test.


By striking this balance, we ensure that testing enhances code quality without impeding progress or innovation in development.

Summary

Testing is a crucial aspect of web application development that ensures reliability, functionality, and user satisfaction. Here are the key takeaways:

In our upcoming post, we'll dive into the nitty-gritty of crafting test cases. We'll explore the essential APIs and best practices for writing effective tests, and discuss strategies for organising your test suite. We'll also peek under the hood of popular testing frameworks, examining their core APIs and fundamental building blocks. This practical guide will equip you with the knowledge to write robust, maintainable test cases for your web applications.