Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Review of mocks 2 #349

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading