Test-Driven Development with Python: Obey the Testing Goat: Using Django, Selenium, and JavaScript
Rate it:
9%
Flag icon
.assertTemplateUsed is the test method that the Django TestCase class provides us. It lets us check what template was used to render a response (NB — it will only work for responses that were retrieved by the test client). And that test will still pass:
10%
Flag icon
you can think of the functional test as being a high-level view of the cycle, where “writing the code” to get the functional tests to pass actually involves using another, smaller TDD cycle which uses unit tests.
15%
Flag icon
The -M flag on the git diff is a useful one. It means “detect moves”,
17%
Flag icon
Instead of a long up-front design phase, we try to put a minimum viable application out there early, and let the design evolve gradually based on feedback from real-world usage.
17%
Flag icon
YAGNI! Once you start thinking about design, it can be hard to stop. All sorts of other thoughts are occurring to us — we might want to give each list a name or title, we might want to recognise users using usernames and passwords, we might want to add a longer notes field as well as short descriptions to our list, we might want to store some kind of ordering, and so on. But we obey another tenet of the agile gospel: “YAGNI” (pronounced yag-knee), which stands for “You ain’t gonna need it!” As software developers, we have fun creating things, and sometimes it’s hard to resist the urge to build ...more
17%
Flag icon
I’m using the convention of double-hashes (##) to indicate “meta-comments” — comments about how the test is working and why — so that we can distinguish them from regular comments in FTs which explain the User Story.
20%
Flag icon
You’ll also notice that we can compare list objects with each other directly (saved_list and list_) — behind the scenes, these will compare themselves by checking that their primary key (the .id attribute) is the same.
32%
Flag icon
We’ve just written a test with a deliberate failure. Let’s temporarily switch it off, using a decorator called “skip” from unittest:
32%
Flag icon
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. Otherwise, it’s too easy to allow “technical debt” to build up.
32%
Flag icon
But if you’re halfway through something else, should you stop to refactor the old code? The answer is that it depends. In the case at the beginning of the chapter, we haven’t even started writing our new code. We know we are in a working state, so we can justify putting a skip on our new FT (to get back to fully passing tests) and do a bit of refactoring straight away. Later in the chapter we’ll spot other bits of code we want to alter. In those cases, rather than taking the risk of refactoring an application that’s not in a working state, we’ll make a note of the thing we want to change on ...more
40%
Flag icon
Instead of checking for our custom error message, we check using the CSS pseudoselector :invalid, which the browser applies to any HTML5 input that has invalid input.
41%
Flag icon
If you find yourself looking at complex views, and having to write a lot of tests for them, it’s time to start thinking about whether that logic could be moved elsewhere: possibly to a form, like we’ve done here. Another possible place would be a custom method on the model class. And — once the complexity of the app demands it — out of Django-specific files and into your own classes and functions, that capture your core business logic.
48%
Flag icon
The concept is: just use email to verify someone’s identity. If you’re going to have a “forgot my password” feature, then you’re trusting email anyway, so why not just go the whole hog? Whenever someone wants to log in, we generate a unique URL for them to use, email it to them, and they then click through that to get into the site.
48%
Flag icon
When learning a new tool or exploring a new possible solution, it’s often appropriate to leave the rigorous TDD process to one side, and build a little prototype without tests, or perhaps with very few tests. The goat doesn’t mind looking the other way for a bit. This kind of prototyping activity is often called a “spike”, for reasons best known.
50%
Flag icon
De-spiking means rewriting your prototype code using TDD.
51%
Flag icon
The idea is to throw away the old spike code altogether, and start again from scratch, using TDD once again. De-spiked code can often come out looking quite different from the original spike, and usually much nicer.
54%
Flag icon
1 if = 1 More Test A rule of thumb for these sorts of tests: any if means an extra test, and any try/except means an extra
59%
Flag icon
More and more people are starting to say: don’t use JSON fixtures. They’re a nightmare to maintain when your model changes. Plus it’s difficult for the reader to tell which of the many attribute values specified in the JSON are critical for the behaviour under test, and which are just filler.
64%
Flag icon
Outside-In TDD is sometimes called “programming by wishful thinking”, and you can see why. We start writing code at the higher levels based on what we wish we had at the lower levels, even though it doesn’t exist yet!
68%
Flag icon
When using assert methods on mocks, like assert_called_ once_with, it’s doubly important to make sure you run the test and see it fail. It’s all too easy to make a typo in your assert function name and end up calling a mock method that does nothing (mine was to write asssert_called_once_with with three essses; try it!).
70%
Flag icon
Methodologically, the way to do it is to think about the interaction between your layers in terms of contracts. Whenever we mock out the behaviour of one layer, we have to make a mental note that there is now an implicit contract between the layers, and that a mock on one layer should probably translate into a test at the layer below.
73%
Flag icon
The alternative is to set up a virtual display: we get the server to pretend it has a screen attached to it, so Firefox runs happily. There are a few tools out there to do this; we’ll use one called “Xvfb” (X Virtual Framebuffer)1 because it’s easy to install and use, and because it has a convenient Jenkins plugin