I understand that unit testing is essential for producing reliable, maintainable, and verifiable code. I recognize that well-written tests not only catch bugs early but also provide confidence that changes do not break existing functionality. This guide ensures that my unit tests meet Fossil Logic standards and contribute to a robust software ecosystem.
1. Purpose of Unit Tests
I write unit tests to verify that individual components behave as intended. I focus on isolated, deterministic, and repeatable tests, ensuring that each test checks a single unit of functionality without depending on external systems or side effects.
2. Testing Frameworks
I use the approved testing frameworks for each language:
- C/C++: Fossil Test (Pizza Test) framework.
- Python:
unittestorpytest. - Other languages: Frameworks approved by project maintainers.
3. Test Structure
I follow a consistent structure for tests:
- Arrange: Set up the conditions and inputs.
- Act: Execute the function or method under test.
- Assert: Verify the results against expected outcomes.
- Teardown: Clean up resources if necessary.
4. Naming and Organization
- I name test functions clearly to describe what they verify, e.g.,
test_add_user_with_valid_data. - I group related tests into logical modules or classes.
- I place test code in dedicated test directories separate from production code.
5. Coverage and Scope
- I strive for comprehensive coverage of critical functionality, including edge cases.
- I avoid testing implementation details; I focus on observable behavior.
- I maintain tests for both success and failure scenarios.
6. Independence and Determinism
- I write tests that are independent of each other; the result of one test must not affect another.
- I avoid reliance on external systems, such as databases or network services, unless using mocks or stubs.
- I ensure tests are repeatable and deterministic across runs.
7. Assertions and Verification
- I use clear, descriptive assertions to verify expected results.
- I include messages in assertions where appropriate to aid debugging.
- I avoid overly complex assertions that are difficult to interpret.
8. Test Maintenance
- I update tests when functionality changes, ensuring they remain accurate and relevant.
- I remove obsolete tests that no longer reflect project requirements.
- I document known limitations or edge cases where tests cannot be fully deterministic.
9. Automation and Continuous Integration
- I integrate unit tests into CI/CD pipelines to ensure automated execution on every commit or pull request.
- I monitor test results and fix failures promptly.
- I avoid committing code that breaks existing tests.
10. Best Practices
- I write tests early, ideally alongside development (Test-Driven Development when feasible).
- I keep tests readable and maintainable, like production code.
- I review and refactor tests regularly to remove duplication and improve clarity.
Why Unit Testing Matters
I recognize that unit testing is a critical tool for quality assurance. It ensures that my work is correct, prevents regressions, supports refactoring, and builds trust with other contributors and users. By following this guide, I contribute to Fossil Logic’s mission of delivering reliable, maintainable, and high-quality software.