Table of contents
What do good assertions look like?
The content here is under the Attribution 4.0 International (CC BY 4.0) license
Test cases are not just a collection of assertions. They should be well-structured, readable, and maintainable. Good assertions are clear, concise, and provide meaningful feedback when they fail.
(Beck, 2002) descrive the qualities of good tests, and by extension, good assertions. Assertions are the heart of test cases, and they should embody the principles of clarity, specificity, and meaningfulness.
In addition to that, later in the timeline of events on TDD, Kent Beck, in test desiderata, uses this term to refer to the qualities that good tests should have. Similarly, we can apply the concept of desiderata to assertions in test cases. Desiderata are essentially a set of criteria or principles that guide the design and evaluation of assertions.
Test Desiderata 1/12 Behavior (Kent Beck & Kelly Sutton)
Kent Beck and Kelly Sutton depicts the concept of “desiderata” in the video Test Desiderata 1/12 Behavior. They describe desiderata as the qualities that good tests should possess, such as clarity, simplicity, and expressiveness. These principles can also be applied to assertions in test cases.
Assertions are a fundamental part of test cases in software development, especially in Test-Driven Development (TDD). They are statements that verify whether a certain condition holds true during the execution of a test. Good assertions are crucial for ensuring that tests are effective and reliable. The term “desiderata” is often used in this context to refer to the qualities or characteristics that good assertions should possess.
1. Clarity
Assertions should be clear and unambiguous. They should express the intent of the test case in a way that is easy to understand. Avoid complex expressions or jargon that might confuse readers.
2. Specificity
Assertions should be specific about what they are checking. Instead of asserting that a value is “true” or “false,” specify the exact condition that should hold true. This helps in diagnosing failures more effectively.
3. Meaningfulness
Assertions should provide meaningful information about the state of the system. They should not just check for arbitrary values but should validate that the system behaves as expected in a given context.
4. Independence
Assertions should be independent of each other. Each assertion should test a specific aspect of the system without relying on the outcome of previous assertions. This ensures that failures can be traced back to a specific condition.
5. Simplicity
Assertions should be simple and straightforward. Avoid complex logic or nested conditions within assertions. If an assertion is too complex, consider breaking it down into smaller, more manageable assertions.
6. Consistency
Assertions should follow a consistent style and format throughout the test suite. This makes it easier for developers to read and understand the tests. Consistency in naming conventions, structure, and formatting helps maintainability.
7. Contextual Relevance
Assertions should be relevant to the context of the test case. They should validate the expected behavior of the system in the specific scenario being tested. Avoid assertions that are not directly related to the functionality being tested.
8. Feedback
When an assertion fails, it should provide clear and actionable feedback. The error message should indicate what was expected versus what was actually received, helping developers quickly identify the issue.
9. Avoiding Side Effects
Assertions should not have side effects that alter the state of the system or the test environment. They should only validate conditions without modifying any data or triggering additional actions.
10. Performance Considerations
Assertions should be efficient and not introduce significant performance overhead. While readability and clarity are important, assertions should also be performant to avoid slowing down the test suite unnecessarily.
11. Test Coverage
Assertions should contribute to comprehensive test coverage. They should cover various scenarios, including edge cases and error conditions, to ensure that the system behaves correctly under different circumstances.
12. Maintainability
Assertions should be easy to maintain. As the system evolves, assertions should be adaptable to changes without requiring significant rewrites. This includes using descriptive names and avoiding hard-coded values that may change over time.
Resources
TDD Anti-Patterns (Emmanuel Valverde Ramos & Matheus Marabesi)
Sometimes going through a video it helps to understand the concepts better. In this case, we presented a video on TDD anti-patterns, which can be useful for understanding what to avoid in test-driven development.
References
- Beck. (2002). Test Driven Development: By Example. Addison-Wesley Longman Publishing Co., Inc.