Testing

Last modified by chrisby on 2024/06/20 14:42

Foreword

The chapters presented here are a concise summary of more high-level knowledge about testing. It is recommended that you are familiar with writing very basic tests and mocks before reading on.

Benefits of Testing

  • Quality Assurance
    • Automated Testing: Minimizes the need for human source code checking or manual testing, providing a cost-effective way to ensure continuous quality assurance and the correct functioning of software at all times.
    • Early Feedback: Tests provide immediate bug feedback. This is especially true for detecting accidentally introduced bugs caused by code changes. The earlier bugs are detected, the cheaper they are to fix. This also eliminates the fear of introducing bugs when writing or modifying code.
    • Bug Location Detection: Tests identify bug locations, saving debugging time.
    • For these reasons, development with testing is faster and safer than without, also see Test-Driven Development.
  • Testable Design
    • Writing tests automatically forces developers to apply specific design best practices, resulting in a testable design that improves code and architecture testability, an important quality criterion.
  • Documentation
    • Always Up To Date: Tests serve as the most up-to-date form of code documentation, capturing the expected behavior of the production code in its current state or of a third-party library.
    • Code Is Best Documentation: Good tests are quick and easy to understand because they are written in an expressive language that developers speak fluently. In addition, the actual documentation with its long texts is often skipped anyway.
    • Behavior Is Easier To Understand Than Implementation: Tests are a clearer representation of behavior than the implementation itself. Tests specify the input for a given code and assert the expected output, providing an intuitive understanding that's easier to grasp than the intricacies of production code. Simply put, what code does is easier to understand than how it does it.

What should be tested?

Every functionality you expect the software to provide at any moment. Depending on the overall requirements, you should test:

  • High-level business requirements defined by the customer in project requirements. Tests are essentially requirements translated into code. And customer requirements are typically translated into Acceptance Tests.
  • Lower-level technical requirements derived from high-level business use cases that are not directly visible to end users, but form the backbone of software functionality. This includes the expected behavior of the underlying components, modules and units.
  • Happy Path Requirements: Always test scenarios where a user story works as expected.
  • Unhappy Path Requirements: Test scenarios where things do not go as planned. This includes
    • Edge cases: Test for maximum/minimum values, nulls, invalid input outside the allowed range, zeros, negative numbers, empty lists, and values with special meaning.
    • Error cases: Handle exceptions, dependencies that return errors, file access or existence problems, network problems, and other potential failures.
    • Failure injection (chaos engineering): Perform chaos engineering to test the robustness of the system against unusual conditions. This includes actions such as killing processes, shutting down servers, disconnecting networks, simulating insufficient hardware resources (CPU, memory, disk space), and even simulating entire data center failures due to disasters. Ensure that the system remains functional, available, and able to recover automatically.
    • Security requirements: Simulate potential attack scenarios and verify that the software can withstand them, ensuring robust security measures.
  • Performance requirements: Interactions with software often need to be completed in a certain amount of time.
  • Load requirements: Verify that the software can handle the expected number of requests per second under normal operating conditions.
  • Stress requirements: Run tests with an unusually high number of requests to ensure that the system can handle extreme load conditions without catastrophic failure and to determine its breaking point.

Table of Contents