-
Notifications
You must be signed in to change notification settings - Fork 0
/
TestingSlides.html
299 lines (255 loc) · 6.32 KB
/
TestingSlides.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
<!DOCTYPE html>
<html>
<head>
<title>Title</title>
<meta charset="utf-8">
<style>
@import url(https://fonts.googleapis.com/css?family=Yanone+Kaffeesatz);
@import url(https://fonts.googleapis.com/css?family=Droid+Serif:400,700,400italic);
@import url(https://fonts.googleapis.com/css?family=Ubuntu+Mono:400,700,400italic);
body { font-family: 'Droid Serif'; }
h1, h2, h3 {
font-family: 'Yanone Kaffeesatz';
font-weight: normal;
}
.remark-code, .remark-inline-code { font-family: 'Ubuntu Mono'; }
</style>
</head>
<body>
<textarea id="source">
name: testing
class: middle
layout: true
---
# Perfect Testing and Why nulls Mean You Need To Keep Designing.
by James Tryand
---
# We Don't Want To Test
<!--
.center[![Right-aligned image](https://images-na.ssl-images-amazon.com/images/G/01/img15/pet-products/small-tiles/23695_pets_vertical_store_dogs_small_tile_8._CB312176604_.jpg)]
-->
- Sounds Great but in the real world...
--
- They keep breaking
--
- Waste of time / effort I just wanna code
--
- Don't know where to start
---
# Testing Smells
* Not Inverting the Pyramid
* Coverage via Constructor Test
* Not refactoring
* Brittle Test
---
# The Purpose of Tests
- Confirmation of Spec
???
ensure model find missing edges in code & design
--
- Exploration of code
--
- Exploration of problem space
--
- Confidence in your codebase
--
- Documentation & Examples
---
# Key Cause of Bugs
- Unexpected Code Paths
--
- Unreasoned about code
--
- **why**
--
- *Cognitive Load is Too High
---
class: middle,center
# Key Cause of Bugs
**because it's...**
## "Big and Complicated"
---
# Can we do something different?
--
## Don't Make it Big
--
## Don't Make it Complicated
--
## Simply Avoid The Problem
---
# HOW?
---
# Write "Better" Code
--
# Write "Better" Tests
---
# Write "Better" Code =>
* Code that avoids the problems
# Write "Better" Tests =>
* Tests that prevent and capture possible errors
---
## A short background
"Cognitive Load Is Too High"
---
## So what is cognitive Load?
## Why is it important?
???
Attention and Digit Span
Mental Model Theory
---
**IS IT NOT TRUE THAT? LONDON IS A CITY AND EUROPE IS A COUNTRY**
---
a) London is not a city and Europe is not a continent.
b) London is not a city or Europe is not a continent, or both.
c) If London is not a city, then Europe is not a continent.
d) London is not a city or else Europe is not a continent.
---
## Reasoning Blindspots
???
we are better at reasoning about positives rather than negatives
the number of mental steps indicates difficulty
---
## So how do we avoid them.
---
# Reduce the Cognitive Load
## By Making It Less Complex
## But How?
---
# Avoid the 'Excel Form'
* "It will be easy because it does all this for you"
---
# Geometric Complexity
* the number of discrete tests =
* Multiplying each parameter's possible number of states
ie.
X{3}, Y{5}, Z{3}
3*5*3 = 45
vs. indpendently testing states becomes
3+5+3 = 11
---
# Some Coding Techniques
## Favor Value Oriented Programming Over Place Oriented Programming
---
## Values vs Places
* Facts are not places that you change
* Facts are Values
* Facts do not change
* So use immutable Values
???
---
# Values
* Do Not Change
* can be composed of other values
* aggregate down to values
* can be shared
---
# Values
* Reproducable Tests
* Easy to Fabricate
* Language Independent
---
# Values
* Form our Interfaces
* Reduce Coordination
* Something that happened
---
# Great. So?
---
# Use immutability
* If it's wrong it was only where it was made.
* Can be shared - Concurrency becomes trivial
--
# But We Need State In Our System
---
# Merging Parameters
* By simplifying down input / output parameters to a single input / output state type...
--
# Wat?
---
# Union Types
(types that are a union of other types)
ie. string | int | error
???
* Then where you have that type, you know to handle each possible option.
* By discriminating between them, there's confidence you're not missing any
* Cognitive load is reduced because it's transparent what each one is
---
# Benefits Of Union Types
* explicit description & handling lowers cognitive load
* confidence code paths are not missed.
---
# But I work in the real world...
---
# Enter the NULL
* its an escapes hatch from the typing system
* "My Billion Dollar Mistake"
* So a 'null reference exception' is a missed codepath
???
* Which means a use case you have but did not model for...
* ...so back to the drawing board
---
# BACK TO TEST IMPROVEMENTS
* okay so immutability gives us easier tests
* prior state change -> THE TEST -> expected events
## But where do i start?
---
# SCIENCE
* cannot prove the positive - only disprove something
--
* so disprove the negative
--
* "But Cognitive Load!"
* ahh yes.
---
# Embrace the Failure
* you should know or expect the code to have certain properties
* figuring out what to do if it goes bad...
* if you disprove that - you have a working system
--
* once that is in place reduce the number of ocassions you defer to your error handler.
* use property based testing will help to do this
* This will avoid exceptions as they are a seperate workflow in your system
---
# Anything else
* KISS - don't overengineer during testing, use minimal and then should the need arise use big
* Don't make assumptions about usage behaviour - let it emerge in the refactor
* FLOW & FEEDBACK
* copy test;
* modify test;
* put fixing code in test to pass test;
* refactor by putting it in the right place
* and clean up
* commit
---
# RECAP
## Use Good Coding Techniques To Help Reasonability
* Immutability
* Discriminated Unions
* Small Pieces
---
# RECAP
* Test the expected behaviours
* Start by handling failure in tests and code
* Then reduce the errors by confirming the properties don't fail
* Keep Flow Tight:
---
# References
## Immutability
## Cognitive Science
* https://www.researchgate.net/publication/281258035_The_shallow_processing_of_logical_negation/download
* https://ejop.psychopen.eu/article/view/696/html
## Union Types
## State Modelling
## Property Based Testing
## Values
## Reducing Complexity
???
https://remarkjs.com/remarkise
</textarea>
<script src="https://remarkjs.com/downloads/remark-latest.min.js">
</script>
<script>
var slideshow = remark.create();
</script>
</body>
</html>