Remember that functional tests are closely linked to “user stories”. If you were using
some sort of project management tool like an issue tracker, you might make it so that
each file matched one issue or ticket, and its filename contained the ticket ID. Or, if you
prefer to think about things in terms of “features”, where one feature may have several
user stories, then you might have one file and class for the feature, and several methods
for each of its user stories.
We’ll also have one base test class which they can all inherit from. Here’s how to get there
step by step.
Skipping a Test
It’s always nice, when doing refactoring, to have a fully passing test suite. We’ve just
written a test with a deliberate failure. Let’s temporarily switch it off, using a decorator
called “skip” from
unittest
:
functional_tests/tests.py (ch10l001-1).
from
unittest
import
skip
[
...
]
@skip
def
test_cannot_add_empty_list_items
(
self
):
This tells the test runner to ignore this test. You can see it works—if we rerun the tests,
it’ll say it passes:
$
python3 manage.py test functional_tests
[...]
Ran 3 tests in 11.577s
OK
Skips are dangerous—you need to remember to remove them be‐
fore you commit your changes back to the repo. This is why line-by-
line reviews of each of your diffs are a good idea!
Don’t Forget the “Refactor” in “Red, Green, Refactor”
A criticism that’s sometimes levelled at TDD is that it leads to badly architected code,
as the developer just focuses on getting tests to pass rather than stopping to think about
how the whole system should be designed. I think it’s slightly unfair.
TDD is no silver bullet
. You still have to spend time thinking about good design. But
what often happens is that people forget the “Refactor” in “Red, Green, Refactor”. The
methodology allows you to throw together any old code to get your tests to pass, but it
also
asks you to then spend some time refactoring it to improve its design.
170
|
Chapter 10: Input Validation and Test Organisation