Skip to content

Commit

Permalink
Review of mocks 2
Browse files Browse the repository at this point in the history
  • Loading branch information
seddonym committed Dec 23, 2024
1 parent df7abd8 commit d05fe51
Showing 1 changed file with 20 additions and 5 deletions.
25 changes: 20 additions & 5 deletions chapter_21_mocking_2.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ and we'll also have a discussion about how many tests is "enough".
We got our auth backend ready in the last chapter,
now we need use the backend in our login view.
First we add it to _settings.py_:

// DAVID: Should we do this after writing the failing tests?
// todo renumber listings


Expand Down Expand Up @@ -336,7 +336,8 @@ then we can apply similar reasoning to what we used at the lower level.
However many tests we end up with,
we need 3 of them to be checking on each colour,
and 3 that check that each body type can be painted.

// DAVID: This section could do with a summary sentence before we change subject,
// it feels like a jolt to go back to the tests without knowing what we're meant to take from it.

=== Using Mocks to Test Parts of Our System in Isolation

Expand Down Expand Up @@ -603,6 +604,9 @@ So in our test, we could have done this instead:
But you can see how using the `call` helper is nicer.
// DAVID: Might be worth moving the magic assert_called... methods sidebar
// to here.
*******************************************************************************


Expand Down Expand Up @@ -1168,6 +1172,9 @@ the "right" way, ie by calling into Dango's `auth.authenticate()` function
(instead of, eg, instantiating and calling our auth backend ourselves,
or even just implementing authentication inline in the view).

// DAVID: Another approach for all this would be to swap in stub authentication
// backends using Django's override_settings helper. Might be worth mentioning.

TIP: "Test behaviour, not implementation" is a GREAT rule of thumb for tests.
But sometimes, the fact that you're using one implementation rather than another
really is important. In these cases, a mocky test can be useful.
Expand Down Expand Up @@ -1211,6 +1218,9 @@ We're just about ready to try our functional test!
Let's just make sure our base template shows a different nav bar for logged-in
and non–logged-in users (which our FT relies on):

// DAVID: I originally misunderstood that this code snippet was meant to be
// copy-pasted in. Suggest being more explicit.

[role="sourcecode small-code"]
.src/lists/templates/base.html (ch20l022)
====
Expand Down Expand Up @@ -1292,6 +1302,8 @@ It's because of two things:

* Firstly, we need to re-add the email configuration to _settings.py_.

// DAVID: Shouldn't we write a failing test first? If not, why not?

[role="sourcecode"]
.src/superlists/settings.py (ch20l023)
====
Expand Down Expand Up @@ -1391,7 +1403,7 @@ $ *git commit -m "Custom passwordless auth backend + custom user model"*


((("mocks", "logout link")))
The last thing we need to do before we call it a day is to test the logout button
The last thing we need to do before we call it a day is to test the logout button.
We extend the FT with a couple more steps:

[role="sourcecode"]
Expand Down Expand Up @@ -1509,6 +1521,7 @@ Ran 57 tests in 78.124s
OK
----
//54
// DAVID: Should we get them to `cd ..` back out of src?

WARNING: We're nowhere near a truly secure or acceptable login system here.
Since this is just an example app for a book, we'll leave it at that,
Expand All @@ -1533,7 +1546,8 @@ Using mock.return_value::
this usually happens in the "Assert" or "Then" part of your test.
It can also be assigned to in the "Arrange" or "Given" part of your test,
as a way to say
"we want this mocked-out function to return a particular value"
"we want this mocked-out function to return a particular value".
// DAVID: Could this point be expressed more clearly?
Mocks can ensure test isolation and reduce duplication::
You can use mocks to isolate different parts of your code from each other,
Expand All @@ -1556,14 +1570,15 @@ Mocks can allow you to verify implementation details::
There are alternatives to mocks, but they require rethinking how your code is structured::
In a way, mocks make it "too easy".
In other programming languages
that lack Python's dynamic ability to monkepatch things at runtime,
that lack Python's dynamic ability to monkeypatch things at runtime,
developers have had to work on alternative ways to test code with dependencies.
While these techniques can be more complex,
they do force you to think about how your code is structured,
to cleanly identify your dependencies,
and to build clean abstractions and interfaces around them.
Further discussion is beyond the scope of this book,
but check out http://cosmicpython.com[Cosmic Python].
// DAVID: Suggest removing the word "other".
There's a longer worked example of mocks and using them
to improve the structure of code in <<appendix_purist_unit_tests>>.
Expand Down

0 comments on commit d05fe51

Please sign in to comment.