1
1
[[cheat-sheet]]
2
2
[appendix]
3
- Cheat Sheet
4
- -----------
3
+ == Cheat Sheet
5
4
6
- By popular demand, this "cheat sheet" is loosely based on the little
7
- recap/summary boxes from the end of each chapter. The idea is to provide a few
8
- reminders, and links to the chapters where you can find out more to jog your
9
- memory. I hope you find it useful!
5
+ By popular demand, this "cheat sheet" is loosely based on the recap/summary boxes
6
+ from the end of each chapter.
7
+ The idea is to provide a few reminders,
8
+ and links to the chapters where you can find out more to jog your memory.
9
+ I hope you find it useful!
10
10
11
11
12
- Initial Project Setup
13
- ~~~~~~~~~~~~~~~~~~~~~
12
+ === Initial Project Setup
14
13
15
- * ((("cheat sheet", "project setup")))((("Django framework", "set up", "project creation"))) Start
16
- with a 'User Story' and map it to a first 'functional test' .
14
+ ((("cheat sheet", "project setup")))
15
+ ((("Django framework", "set up", "project creation")))
16
+ * Start with a _User Story_ and map it to a first _functional test_.
17
17
18
18
* Pick a test framework—`unittest` is fine, and options like `py.test`,
19
19
`nose`, or `Green` can also offer some advantages.
20
20
21
21
* Run the functional test and see your first 'expected failure'.
22
22
23
23
* Pick a web framework such as Django, and find out how to run
24
- 'unit tests' against it.
24
+ _unit tests_ against it.
25
25
26
- * Create your first 'unit test' to address the current FT failure,
26
+ * Create your first _unit test_ to address the current FT failure,
27
27
and see it fail.
28
28
29
- * Do your 'first commit' to a VCS like 'Git' .
29
+ * Do your _first commit_ to a VCS like _Git_ .
30
30
31
- Relevant chapters: <<chapter_01>>, <<chapter_02_unittest>>, <<chapter_03_unit_test_first_view>>
31
+ Relevant chapters:
32
+ <<chapter_01>>,
33
+ <<chapter_02_unittest>>,
34
+ <<chapter_03_unit_test_first_view>>.
32
35
33
36
34
- The Basic TDD Workflow
35
- ~~~~~~~~~~~~~~~~~~~~~~
37
+ === The Basic TDD Workflow: Red/Green/Refactor
36
38
37
- * ((("cheat sheet", "TDD workflow")))((("Test-Driven Development (TDD)", "overall process of"))) Double-loop TDD (<<Double-Loop-TDD-diagram2>>)
39
+ ((("cheat sheet", "TDD workflow")))
40
+ ((("Test-Driven Development (TDD)", "overall process of")))
38
41
39
42
* Red, Green, Refactor
40
43
44
+ * Double-loop TDD (<<Double-Loop-TDD-diagram2>>)
45
+
41
46
* Triangulation
42
47
43
48
* The scratchpad
@@ -54,114 +59,96 @@ The Basic TDD Workflow
54
59
image::images/double-loop-tdd-simpler.png["An inner red/green/refactor loop surrounded by an outer red/green of FTs"]
55
60
56
61
57
- Relevant chapters: <<chapter_04_philosophy_and_refactoring>>, <<chapter_05_post_and_database>>, <<chapter_07_working_incrementally>>
58
-
62
+ Relevant chapters:
63
+ <<chapter_04_philosophy_and_refactoring>>,
64
+ <<chapter_05_post_and_database>>,
65
+ <<chapter_07_working_incrementally>>.
59
66
60
67
61
- Moving Beyond Dev-Only Testing
62
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
63
68
64
- * ((("cheat sheet", "moving beyond dev-only testing"))) Start
65
- system testing early. Ensure your components work together: web server,
66
- static content, database.
69
+ === Moving Beyond Dev-Only Testing
67
70
68
- * Build a staging environment to match your production environment, and run
69
- your FT suite against it.
71
+ ((("cheat sheet", "moving beyond dev-only testing")))
70
72
71
- * Automate your staging and production environments:
73
+ * Start system testing early.
74
+ Ensure your components work together: web server, static content, database.
72
75
76
+ * Build a production environment early, and automate deployment to it.
73
77
- PaaS vs. VPS
74
- - Fabric
75
- - Configuration management (Chef, Puppet, Salt, Ansible)
76
- - Vagrant
78
+ - Docker
79
+ - Ansible vs Terraform
77
80
78
- * Think through deployment pain points: the database, static files,
81
+ * Think through deployment pain points: the database, static files,
79
82
dependencies, how to customise settings, and so on.
80
83
81
84
* Build a CI server as soon as possible, so that you don't have to rely
82
85
on self-discipline to see the tests run.
83
86
84
- Relevant chapters: <<chapter_11_server_prep>>, <<chapter_25_CI>>
87
+ Relevant chapters:
88
+ <<part2>>,
89
+ <<chapter_25_CI>>.
85
90
86
91
87
- General Testing Best Practices
88
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
92
+ === General Testing Best Practices
89
93
90
- * ((("cheat sheet", "testing best practices")))((("testing best practices"))) Each
91
- test should test one thing.
94
+ ((("cheat sheet", "testing best practices")))
95
+ ((("testing best practices")))
92
96
93
- * One test file per application code source file .
97
+ * Each test should test one thing .
94
98
95
- * Consider at least a placeholder test for every function and class,
96
- no matter how simple.
99
+ * Test behaviour rather than implementation.
97
100
98
101
* "Don't test constants".
99
102
100
- * Try to test behaviour rather than implementation.
103
+ * Try to think beyond the charmed path through the code,
104
+ and think through edge cases and error cases.
101
105
102
- * Try to think beyond the charmed path through the code, and think
103
- through edge cases and error cases.
106
+ * Balance the "test desiderata".
104
107
105
108
106
- Relevant chapters: <<chapter_04_philosophy_and_refactoring>>, <<chapter_14_database_layer_validation>>,
107
- <<chapter_15_simple_form>>
109
+ Relevant chapters:
110
+ <<chapter_04_philosophy_and_refactoring>>,
111
+ <<chapter_14_database_layer_validation>>,
112
+ <<chapter_15_simple_form>>,
113
+ <<chapter_27_hot_lava>>.
108
114
109
115
110
- Selenium/Functional Testing Best Practices
111
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
116
+ === Selenium/Functional Testing Best Practices
112
117
113
118
* Use explicit rather than implicit waits, and the interaction/wait pattern.
114
119
115
120
* Avoid duplication of test code--helper methods in a base class and the
116
121
Page pattern are possible solutions.
117
122
118
- * Avoid double-testing functionality. If you have a test that covers a
119
- time-consuming process (e.g., login), consider ways of skipping it in
120
- other tests (but be aware of unexpected interactions between seemingly
121
- unrelated bits of functionality).
123
+ * Avoid double-testing functionality.
124
+ If you have a test that covers a time-consuming process (e.g., login),
125
+ consider ways of skipping it in other tests
126
+ (but be aware of unexpected interactions between seemingly unrelated bits of functionality).
122
127
123
128
* Look into BDD tools as another way of structuring your FTs.
124
129
125
- Relevant chapters: <<chapter_23_debugging_prod>>, <<chapter_25_CI>>,
126
- <<chapter_26_page_pattern>>
127
-
128
- Outside-In, Test Isolation Versus Integrated Tests, and Mocking
129
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
130
-
131
- ((("cheat sheet", "isolated vs. integrated tests"))) Remember
132
- the reasons we write tests in the first place:
130
+ Relevant chapters:
131
+ <<chapter_23_debugging_prod>>,
132
+ <<chapter_25_CI>>,
133
+ <<chapter_26_page_pattern>>.
133
134
134
- * To ensure correctness and prevent regressions
135
- * To help us to write clean, maintainable code
136
- * To enable a fast, productive workflow
137
135
138
- And with those objectives in mind, think of different types of tests,
139
- and the trade-offs between them:
136
+ === Outside-In
140
137
138
+ Default to working outside-in. Use double-loop TDD to drive your development,
139
+ start at the UI/outside layers, and work your way down to the infrastructure layers.
140
+ This helps ensure that you write only the code you need,
141
+ and flushes out integration issues early.
141
142
142
- Functional tests::
143
- * Provide the best guarantee that your application really works correctly, from the point of view of the user
144
- * But: it's a slower feedback cycle
145
- * And they don't necessarily help you write clean code
143
+ Relevant chapter: <<chapter_24_outside_in>>.
146
144
147
- Integrated tests (reliant on, for example, the ORM or the Django Test Client)::
148
- * Are quick to write
149
- * Are easy to understand
150
- * Will warn you of any integration issues
151
- * But: may not always drive good design (that's up to you!)
152
- * And are usually slower than isolated tests
153
145
154
- Isolated ("mocky") tests::
155
- * Involve the most hard work
156
- * Can be harder to read and understand
157
- * But: are the best ones for guiding you towards better design
158
- * And run the fastest
146
+ === The Test Pyramid
159
147
160
- If you do find yourself writing tests with lots of mocks, and they feel
161
- painful, remember & #x201c ; __listen to your tests__ & #x201d ; —ugly, mocky tests may be
162
- trying to tell you that your code could be simplified .
148
+ Be aware that integration tests will get slower and slower over time.
149
+ Find ways to shift the bulk of your testing to unit tests
150
+ as your project grows in size and complexity .
163
151
164
- Relevant chapters: <<chapter_24_outside_in>>,
165
- //<<appendix_purist_unit_tests>>,
152
+ Relevant chapters:
166
153
<<chapter_27_hot_lava>>.
167
154
0 commit comments