You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: chapter_02_unittest.asciidoc
+5-2Lines changed: 5 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -108,11 +108,11 @@ I used to virtuously pepper my code with nice descriptive comments.
108
108
My colleagues said to me:
109
109
``Harry, we have a word for comments. We call them lies.''
110
110
I was shocked!
111
-
But I learned in school that comments are good practice?
111
+
I learned in school that comments are good practice?
112
112
113
113
They were exaggerating for effect.
114
114
There is definitely a place for comments that add context and intention.
115
-
But their point was that
115
+
But my colleagues' point was that
116
116
_it's pointless to write a comment that just repeats what you're doing with the code_:
117
117
118
118
[role="skipme"]
@@ -142,6 +142,9 @@ it makes sure we're always testing from the point of view of the user.
142
142
There is more fun to be had in this area, things like
143
143
'Behaviour-Driven Development' (see <<appendix_bdd>>) and testing DSLs, but
144
144
they're topics for other books.
145
+
146
+
For more on comments, I recommend John Ousterhoudt's _A Philosohpy of Software Design_,
147
+
which you can get a taste of by reading the https://web.stanford.edu/~ouster/cgi-bin/cs190-spring16/lecture.php?topic=comments[lecture notes from the chapter on comments.]
@@ -383,11 +383,11 @@ search folders called 'templates' inside any of your apps' directories. Then
383
383
it builds an `HttpResponse` for you, based on the content of the template.
384
384
385
385
386
-
NOTE: Templates are a very powerful feature of Django's, and their main
387
-
strength consists of substituting Python variables into HTML text. We're
388
-
not using this feature yet, but we will in future chapters. That's
389
-
why we use `render` and (later) +render_to​_string+ rather
390
-
than, say, manually reading the file from disk with the built-in `open`.
386
+
NOTE: Templates are a very powerful feature of Django's,
387
+
and their main strength consists of substituting Python variables into HTML text.
388
+
We're not using this feature yet, but we will in future chapters.
389
+
That's why we use `render()` rather than, say,
390
+
manually reading the file from disk with the built-in `open()`.
391
391
392
392
393
393
Let's see if it works:
@@ -547,7 +547,7 @@ used to render the response. Actual template(s) used: home.html
547
547
----
548
548
549
549
That's very helpful! Let's change the assert back to the right thing. While
550
-
we're at it, we can delete our old assertions.
550
+
we're at it, we can delete our old assertions.
551
551
552
552
553
553
[role="sourcecode"]
@@ -597,8 +597,7 @@ notice how that actually would have left space for me to break things: I could
597
597
have defined the template as containing 'any' arbitrary string, instead of
598
598
the string with the right `<html>` and `<title>` tags.
599
599
600
-
TIP: When refactoring, work on either the code or the tests, but not both at
601
-
once.
600
+
TIP: When refactoring, work on either the code or the tests, but not both at once.
602
601
603
602
There's always a tendency to skip ahead a couple of steps, to make a couple of
604
603
tweaks to the behaviour while you're refactoring, but pretty soon you've got
@@ -613,10 +612,10 @@ image::images/twp2_0402.png["An adventurous cat, trying to refactor its way out
613
612
614
613
615
614
NOTE: We'll come across ``Refactoring Cat'' again during this book,
616
-
as an example of what happens when we get carried away and want to change
617
-
too many things at once. Think of it as the little cartoon demon
618
-
counterpart to the Testing Goat, popping up over your other shoulder and
619
-
giving you bad advice...
615
+
as an example of what happens when we get carried away
616
+
and want to change too many things at once.
617
+
Think of it as the little cartoon demon counterpart to the Testing Goat,
618
+
popping up over your other shoulder and giving you bad advice...
620
619
621
620
It's a good idea to do a commit after any refactoring:
622
621
@@ -769,47 +768,62 @@ we've stopped testing constants, and we're now well placed to start processing
769
768
user input.
770
769
771
770
772
-
Recap: The TDD Process
773
-
~~~~~~~~~~~~~~~~~~~~~~
771
+
=== Recap: The TDD Process
774
772
775
773
776
-
((("Test-Driven Development (TDD)", "overall process of", id="TDDprocess04")))We've
777
-
now seen all the main aspects of the TDD process, in practice:
774
+
((("Test-Driven Development (TDD)", "concepts", "Red/Green/Refactor")))
775
+
((("Red/Green/Refactor")))
776
+
((("unit-test/code cycle")))
777
+
((("Test-Driven Development (TDD)", "overall process of", id="TDDprocess04")))
778
+
We've now seen all the main aspects of the TDD process, in practice:
778
779
779
780
* Functional tests
780
781
* Unit tests
781
782
* The unit-test/code cycle
782
783
* Refactoring
783
784
784
-
It's time for a little recap, and perhaps even some flowcharts. Forgive me,
785
-
years misspent as a management consultant have ruined me. On the plus side,
786
-
it will feature recursion.
785
+
It's time for a little recap, and perhaps even some flowcharts.
786
+
Forgive me, years misspent as a management consultant have ruined me.
787
+
On the plus side, it will feature recursion.
787
788
788
-
What is the overall TDD process? See <<simple-TDD-diagram>>.
789
+
What is the overall TDD process?
789
790
790
-
We write a test. We run the test and see it fail. We write some minimal code
791
-
to get it a little further. We rerun the test and repeat until it passes.
792
-
Then, optionally, we might refactor our code, using our tests to make sure we
793
-
don't break anything.
791
+
Well, one very common way to present it is using the three words
792
+
_Red, Green, Refactor_. See <<red-green-refactor>>..
794
793
795
-
[[simple-TDD-diagram]]
794
+
[[red-green-refactor]]
795
+
.Red, Green, Refactor
796
+
image::images/red-green-refactor-excalidraw.png["Red, Green and Refactor as three nodes in a circle, with arrows flowing around."]
797
+
798
+
What if we want to drill down in a bit more detail? Here's what
799
+
we've been doing, including what I call the _unit test/code cycle_:
800
+
801
+
We write a test. We run the test and see it fail.
802
+
We write some minimal code to get it a little further.
803
+
We rerun the test and repeat until it passes.
804
+
Then, we look for opportunities to refactor our code,
805
+
using our tests to make sure we don't break anything. See <<simple-tdd-diagram>>.
806
+
807
+
[[simple-tdd-diagram]]
796
808
.Overall TDD process
797
-
image::images/twp2_0403.png["A flowchart showing tests, coding and refactoring"]
798
-
799
-
But how does this apply when we have functional tests 'and' unit tests? Well,
800
-
you can think of the functional test as being a high-level view of the cycle,
801
-
where "writing the code" to get the functional tests to pass actually involves
802
-
using another, smaller TDD cycle which uses unit tests. See
803
-
<<Double-Loop-TDD-diagram>>.
804
-
805
-
We write a functional test and see it fail. Then, the process of "writing
806
-
code" to get it to pass is a mini-TDD cycle of its own: we write one or more
807
-
unit tests, and go into the unit-test/code cycle until the unit tests pass.
808
-
Then, we go back to our FT to check that it gets a little further, and we
809
-
can write a bit more of our application--using more unit tests, and so on.
810
-
811
-
What about refactoring, in the context of functional tests? Well, that means
812
-
we use the functional test to check that we've preserved the behaviour of
809
+
image::images/tdd-process-unit-tests-only-excalidraw.png["A flowchart with boxes for tests, coding and refactoring, with yes/no labels showing when we move forwards or backwards"]
810
+
811
+
But how does this apply when we have functional tests _and_ unit tests?
812
+
Well, you can think of the functional test as being a high-level view of the cycle,
813
+
where "writing the code" to get the functional tests to pass
814
+
actually involves using another, smaller TDD cycle which uses unit tests.
815
+
See <<double-loop-tdd-diagram>>.
816
+
817
+
We write a functional test and see it fail.
818
+
Then, the process of "writing code" to get it to pass is a mini-TDD cycle of its own:
819
+
we write one or more unit tests, and go into the unit-test/code cycle until the unit tests pass.
820
+
Then, we go back to our FT to check that it gets a little further,
821
+
and we can write a bit more of our application--using more unit tests, and so on.
822
+
823
+
TODO - a little more nuance here
824
+
825
+
What about refactoring, in the context of functional tests?
826
+
Well, that means we use the functional test to check that we've preserved the behaviour of
813
827
our application, but we can change or add and remove unit tests, and use
814
828
a unit test cycle to actually change the implementation.
815
829
@@ -820,13 +834,14 @@ This way of looking at things is sometimes called "Double-Loop TDD". One of my
820
834
eminent tech reviewers, Emily Bache, wrote http://bit.ly/1iXzoLR[a blog post]
821
835
on the topic, which I recommend for a different perspective.
822
836
823
-
[[Double-Loop-TDD-diagram]]
837
+
[[double-loop-tdd-diagram]]
824
838
.The TDD process with functional and unit tests
825
-
image::images/twp2_0404.png["A flowchart showing functional tests as the overall cycle, and unit tests helping to code"]
839
+
image::images/double-loop-tdd-excalidraw.png["A flowchart showing functional tests as the overall cycle, and unit tests helping to code"]
826
840
827
841
828
842
We'll explore all of the different parts of this workflow in more detail
829
-
over the coming chapters.((("", startref="TDDprocess04")))
0 commit comments