The Testing Pyramid: Unit Testing

quality
15 de April de 2024

This is the first of a series of post dedicated to software testing.

In the world of software development, testing plays a crucial role in ensuring the quality of the final product. The testing pyramid, popularized by the ISTQB (International Software Testing Qualifications Board), is a model that organizes different testing approaches based on their granularity level. At the base of this pyramid lies unit testing, an essential technique for any software development project.

testing-pyramid

Unit tests are automated tests that verify the functionality of individual units of code, typically functions or methods, in isolation. They are quick to execute and form the basis of a robust test suite. Their significance lies in their ability to identify and rectify errors in the early stages of development, resulting in more resilient and maintainable code.

Another particularity is that Unit Test are written by developers in the same language as the productive code. You can say that unit testing is a development tool like the compiler or debugger and therefore belongs to the toolbox of every developer.

The concept of unit testing is easy to grasp, yet writing effective tests can be challenging.

Tips for Writing Effective Unit Tests:

  1. Keep Unit Tests Fast: Execution speed is critical for continuous integration (CI) and continuous delivery (CD). Unit tests should run within seconds to provide instant feedback to developers.
  2. Avoid External Dependencies: Eliminate any external dependencies, such as databases or web services, by using mocks or stubs to simulate their behavior. This ensures that unit tests are consistent and not reliant on external factors.
  3. Ensure Tests Are Independent: Each unit test should be independent and not rely on state left behind by other tests. This ensures that failures can be identified and addressed in isolation.
  4. Provide Useful Error Information: Error messages should be clear and concise, indicating the exact cause of the failure and facilitating its correction.
  5. Test Boundary Cases: Ensure to include test cases that evaluate the boundaries of a function’s input and output. This helps identify potential overflow errors, rounding errors, and other issues related to data boundaries.

Incorporating Unit Tests into CI/CD:

Integrating unit tests into CI/CD processes is essential to ensure code quality. For example, in a CI workflow, unit tests are automatically executed whenever a change is made to the code repository. If any test fails, the integration process is halted, preventing the introduction of errors into the main code branch. In a CD workflow, unit tests are also automatically run before deployment to production, ensuring that only changes that pass defined tests are deployed.

Design Considerations for Unit Tests:

When designing a system, it is essential to consider the ability to write effective unit tests. A common practice is to separate classes into components that can be tested in isolation. This can be achieved by using interfaces to define the interaction between components, facilitating the substitution of real implementations with mocks or stubs during testing. This leads to an important point: Unit Tests are hard to introduce afterwards. High coupled components could be almost impossible of isolate.

Limitation of Unit Testing:

Despite their importance, unit tests have limitations. Some include:

  • Cannot Test All Unit Interactions: Unit tests only test the behavior of a unit of code in isolation, without considering how it interacts with other units.
  • As Edsger Dijkstra said: “Program testing can be used to show the presence of bugs, but never to show their absence!”.

Conclusion:

In summary, unit tests are a fundamental part of the software development process, enabling the early identification of errors and ensuring code quality. By following best practices and considering the limitations of unit tests, development teams can build more reliable and robust software. Aditionally, if you’re in a regulated environment (i.e. Healthcare) where software quality gets audited, Unit Testing is a must.

References:

  • Freeman, S., & Pryce, N. (2009). “Growing Object-Oriented Software, Guided by Tests.”
  • Meszaros, G. (2007). “xUnit Test Patterns: Refactoring Test Code.”
  • Hunt, A., & Thomas, D. (2002). “The Pragmatic Programmer: Your Journey to Mastery.”

Tags:
, , ,

Share this Facebook Twitter LinkedIn e-mail