Testing Conventions
Note, these are guidelines used by the SCD Cloud Operations Group. They are being presented externally as they may be useful for those developing their own software, they are not being provided with the intention of the Cloud Team reviewing your code - unless you are contributing to one of our repositories.
Code should be well-tested before being contributed. There are a number of ways you can test your code, but we recommend you start with unit tests.
Unit Tests
Unit tests refer to testing individual components or units of code in isolation. We aim to ensure that each unit of code functions properly and that it meets intended behaviours. A unit can a function, method, class or module - depending on granularity of the code being tested.
Guidelines:
When writing unit tests consider the following:
Readability
A unit test should have a singular purpose and the name should reflect what is being tested and the expected behaviour.Independence
A unit test should be independent of all others, and can be executed independent of all others.Maintainability
'The less code to maintain the better' - avoid boilerplate code and testing the same thing twice.
Extract common setup and tear-down code into reusable functions or separate tests.Coverage
Aim for high code coverage by testing each different path and edge case.
We don’t enforce a code coverage targetFail Noisily
Ensure that when tests fail it is clear as to the reason why. Use descriptive assertions and error messages to aid debugging. Avoid overly generic assertions.Performance
Unit test should execute quickly and provide fast feedback
Don’t aim to test expensive I/O operations, network calls or time-consuming operations. Instead use mocksDocumentation
write docstrings for each test to describe what your testing and why - especially when testing obscure edge cases
Python Unit Testing
We can write automated unit tests for Python using a test runner. There are a number of test runners available:
unittest
- comes built-in with the Python standard librarypytest
(recommended) - a third-party testing framework which provides a number of extra features to make it easier to write and run tests.
Guidelines
Here are a set of testing guidelines for python
Use
pytest
parametrization for testing edge-casesUse
pytest
fixtures to reduce setup and tear-down boilerplate in testsMake use of python mocks to remove external dependencies
Test Driven Development (TDD)
Test-driven development is an approach to writing code that encourages you to write test before the actual code. It follows this basic approach
Write a failing test
Implement code to make the test pass
Refactor the code, whilst keeping the test passing
TDD will help you organise your code into smaller modules and prioritise reusability
(because you’ll want to write less tests!)
This will in turn improve your code coverage and overall maintainability of your code.
Higher-level testing procedures
There are a number of other higher level testing procedures you could implement.
Higher-level tests help you to catch bugs from emergent behaviour - like testing if different modules work together as expected.
No Guidelines for higher-level testing yet. Use your best judgement
Integration tests:
Integration tests are tests that verify that each (unit-tested) module of your code interact as expected
useful for testing I/O operations and testing components out of isolation
End-to-End tests
These tests usually replicate user behaviour with the software in an application environment.
We usually run end-to-end tests for software on the Dev Cloud before making changes available on Production Cloud
Note: Testing is an iterative process. If you spot a bug, write tests for that bug, then fix the bug and ensure that the tests pass. That way, future versions will need to maintain that fix as well