Shared base fixture
Q: How do you know you can trust your test set-up?
A: You reuse a well-known test set up in every test.
Example code
def test_simple():
req = set_up_working_request()
resp = invoke(req)
assert resp.status == OK
def test_invalid_page_size():
req = set_up_working_request()
req.page_size = -5
resp = invoke(req)
assert resp.status == INVALID_ARGUMENT
In the test,
- We call
set_up_working_request()
and we know this results in “working” behavior. Then we purposefully inject a defective negative page size into the working request. - We exercise the system under test in the same way.
- We expect a different result.
Because the only difference in set up between test_simple
and
test_invalid_page_size
was in the differing page size, we can easily
reason that the different response status is resulting from just that.
Related techniques
This works well together with these techniques:
- Structure your test methods with separate set up, exercise and verify phases.1
- Use explicit helper functions for set up and possibly name them according to expected behavior such as “working” in the example above.
- Keep the shared set up code in test methods as short as possible, so that it’s easy to spot the equal parts.
- 1:N: Use one base scenario (e.g. “working”) and use its set up as a base for multiple derived scenarios.
-
This is called the “Four-Phase test” in the xUnit test pattern book. (Meszaros07, p358) ↩︎