-
Notifications
You must be signed in to change notification settings - Fork 3
/
Technique.html
476 lines (389 loc) · 15.1 KB
/
Technique.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
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Concordion - Technique</title>
<link media="all" rel="stylesheet" type="text/css" href="css/default.css"/>
<link media="print" rel="stylesheet" type="text/css" href="css/print.css"/>
<link rel="icon" type="image/vnd.microsoft.icon" href="favicon.ico" />
<style>
#specFixtureSystem {
padding: 20px 20px 20px 64px;
}
.exampleTable table {
border-collapse: collapse;
empty-cells: show;
margin: 8px 0px 8px 0px;
}
.exampleTable th, .exampleTable td {
border: 1px solid #966;
padding: 3px;
background-color: #ffe4e4;
}
</style>
</head>
<body>
<div class="page">
<div class="header">
<div id="google_translate_element" class="language-translation"></div>
<div class="logo"><a href="index.html"> <img src="image/front-page-banner.png" alt="Specification by Example" /> </a></div>
</div><!-- header -->
<div class="menuBar">
<ul class="menu">
<li><a href="/">Home</a></li>
<li><a href="Example.html">Example</a></li>
<li><a href="Tutorial.html">Tutorial</a></li>
<li class="selectedTab"><a href="Technique.html">Hints and Tips</a></li>
<li><a href="ExtensionsAPI.html">Extensions API</a></li>
<li><a href="Extensions.html">Extensions</a></li>
<li><a href="Download.html">Download</a></li>
<li><a href="Questions.html">FAQ</a></li>
</ul>
</div><!-- menuBar -->
<div class="content">
<h1>Technique</h1>
<div class="memo">
<h1>Write specifications, not scripts</h1>
<p class="subtext">
Hide all scripting activity in the Java fixture code.
</p>
<a name="scripts"> </a>
<h2>Scripts over-specify</h2>
<p>
Test scripts are a list of instructions to be followed. For example:
</p>
<blockquote class="badExample">
Clear database
<br/>Load database from "sample-data.sql"
<br/>Start webserver
<br/>Open URL: http://localhost:8080/myapp
<br/>Enter username: admin
<br/>Enter password: admin1
<br/>Click the "Login" button
<br/>Click the "User Administration" link
<br/>Click the "Create User" button:
<br/>Enter name: John Smith
<br/>Enter username: john
<br/>Enter password: john99
<br/>Click the "OK" button
<br/>Click the "Logout" link
<br/>Enter username: john
<br/>Enter password: john99
<br/>Click the "Login" button
<br/>Check page contains text: Hello John!
</blockquote>
<p>
Concealed inside the script is a behaviour that the test is trying to
demonstrate. But because the requirement is not explicit, it's hard to
know what it is (e.g. "Can we change this link to a button,
or is the link part of the requirement?").
</p>
<p>
Scripts also tend to suffer badly from duplication. If we introduce
an extra step into the authentication process then all the scripts that
mention logging-in will need modification. This is exactly the kind of
duplication that programming languages are designed to address and why
plain English is not a good language for scripting.
</p>
<a name="specFreedom"> </a>
<h2>Specifications give you freedom</h2>
<p>
Specifications tell you the requirements explicitly. They are
written at a higher level of abstraction to test scripts.
For example:
</p>
<blockquote class="goodExample">
When John logs in, a greeting "Hello John!" is displayed.
</blockquote>
<p>
This can be implemented in multiple ways. All of the details about
how to test the requirement are hidden inside the fixture code
where they can be refactored as the system evolves.
</p>
<p>
For another example see: <a href="ScriptingMakeover.html">Scripting Makeover</a>
</p>
<br />
<a name="specStable"> </a>
<h1>Specifications should be stable</h1>
<p class="subtext">
The specifications themselves should rarely change. Even on agile projects,
though new behaviour is added frequently, existing behaviour is normally
maintained from iteration to iteration.
</p>
<h2>Decouple using the fixture as a go-between</h2>
<p>
Let the fixture code act as a buffer so that the specifications stay very stable.
Anything implementation-specific should be hidden in the fixture code.
You should find that the majority of specifications
are written once and never changed.
</p>
<img id="specFixtureSystem" src="image/technique/SpecFixtureSystem-Gray.png"/>
<a name="instrumentationStable"> </a>
<h2>Instrumentation should not change either</h2>
<p>
The job of the instrumentation is to translate the examples in the
specification into method calls into the fixture.
The instrumentation should be very simple and should not show any
knowledge of how the behaviour is actually implemented in the
system. Once written, the public interface of the fixture should
not change; the implementation of its methods may change though.
</p>
<a name="keepSpecsSimple"> </a>
<h2>Only reveal data the specification actually needs</h2>
<p>
In general, it's better not to return domain objects directly from
fixture methods, but return strings or small objects containing just
the values needed for the examples in the specification. The interfaces
of domain objects may change and we want to avoid having to make
changes to the instrumentation.
</p>
<p>
For example, don't reference a deep property of a domain object from
the instrumentation:
</p>
<blockquote class="badExample">
<code>order.phoneLine.phoneNumber</code>
<br/><code>order.phoneLine.location.postcode</code>
</blockquote>
<p>
But, instead create a new inner class in the fixture that has the
exact properties needed, and populate it from the domain object.
This decouples the specifications from the domain model and gives
you the flexibility to improve the model.
</p>
<blockquote class="goodExample">
<code>phoneNumber</code>
<br/><code>postcode</code>
</blockquote>
<br />
<a name="evolveDSL"> </a>
<h1>Evolve a domain-specific language</h1>
<p>
As you write the fixture code, and refactor it to remove duplication,
you'll find you gradually build up a scripting API – a domain-specific
language (DSL) – that lets you manipulate the system under test.
Eventually, the fixture code will become very stable too.
</p>
<img id="specFixtureSystem" src="image/technique/SpecFixtureScriptingSystem-Gray.png"/>
<br />
<a name="isolateBehaviours"> </a>
<h1>Isolate behaviours</h1>
<p>
Each active specification should have a narrow focus and cover a single
behaviour as independently as possible from other behaviours.
For example, one specification might describe how text searches
are case-insensitive, another will describe how date searches work,
and another will describe how search results are to be presented (what
data is displayed). The idea is to keep each specification very simple
and to avoid overlaps, so that we can change the specification about
the way search results are presented without having to make changes
to the other specifications.
</p>
<p>
If you want to test a combination of behaviours, write a separate
specification of the behaviour for the combination. But always write
the specifications for the individual behaviours first. When you
combine behaviours there is a penalty in terms of complexity –
of both the specification and the fixture code to support it.
</p>
<br />
<a name="thinkGWT"> </a>
<h1>Think "Given-When-Then"</h1>
<p>
This is an excellent way of structuring the concrete
examples in the specifications, and getting into the mindset of
specifying instead of scripting.
I believe it was <a class="externalLink" href="http://dannorth.net/">Dan North</a> and
<a class="externalLink" href="http://abc.truemesh.com/">Chris Matts</a> who came up with
the template:
</p>
<blockquote>
<b>Given</b> (some context)
<br/><b>When</b> (something happens)
<br/><b>then</b> (some behaviour)
</blockquote>
<p>
Example:
</p>
<blockquote class="goodExample">
Given a user called John;
<br/>When John logs in,
<br/>then a greeting is displayed saying "Hello John!".
</blockquote>
<p>
Once you've written or thought about your behaviour using the Given-When-Then template,
you can reword the sentence to make it less clunky. For example, in this case
we can deduce that John is a user from the phrase "John logs in", so we can drop
the "Given" part and write something more readable like this:
</p>
<blockquote class="goodExample">
When John logs in, a greeting
"Hello John!" is displayed.
</blockquote>
</div>
<br />
<img style="float: right" src="image/technique/SmellyRubbishBin.png"/>
<a name="commonSmells"> </a>
<h1>Common Smells</h1>
<div class="memo">
<a name="specsChange"> </a>
<h1>Existing specifications are often changed</h1>
<h2>You're tied to an implementation</h2>
<p>
If you find you're having to change the contents of specifications /
instrumentation, on a regular basis, this is a strong indicator
that the specifications are too closely coupled to the implementation.
</p>
<h2>So, pretend there are multiple implementations</h2>
<p>
The solution is to describe the underlying behaviour in a more
abstract way. It might help
to imagine that there are several different implementations - a web application,
a Swing application, and a command-line executable, for example. Only
describe behaviour that is <em>required</em> so that you leave as
many options open as possible for alternative implementations.
</p>
<br />
<img style="float: right" src="image/technique/SmellyFish.png"/>
<a name="lotsOfExecutes"> </a>
<h1>Lots of "execute" commands</h1>
<h2>You're writing a script</h2>
<p>
If you have lots of "execute" commands you are probably writing
a script instead of a specification.
</p>
<h2>So, hide the scripting in the fixture</h2>
<p>
Avoid describing the steps of how to test
the behaviour and simply state the context (as a sentence),
and the behaviour you expect to see. Don't explain
how to get into that context, don't explain how to perform the
operation and don't explain how to extract the results. All of these
things are implementation-specific and should be hidden in the
fixture code.
</p>
<br />
<img style="float: right" src="image/technique/SmellyFish.png"/>
<a name="complicatedInstrumentation"> </a>
<h1>Complicated instrumentation</h1>
<h2>You're testing too much in one go</h2>
<p>
As a rule of thumb, well-written fixtures should have no more than
three public methods and no method should have more than one or two
parameters. Complicated instrumentation is usually a sign of
trying to test too many things at once.
</p>
<h2>So, decompose the behaviour</h2>
<p>
Focus on one tiny behaviour at a time. Break the
behaviour into smaller and smaller pieces until you cannot
break it down any further. Then write separate specifications
for each piece.
</p>
<br />
<img style="float: right" src="image/technique/SmellyFish.png"/>
<a name="complicatedFixtures"> </a>
<h1>Complicated fixture code</h1>
<h2>Your fixture code is verbose and hard to follow</h2>
<p>
All the scripting should be done in the fixture code, but this
can make the code seem complicated.
</p>
<h2>So, create classes to help with the scripting</h2>
<p>
Begin to create objects to help with the scripting
activity - push the implementation details into them. Eventually
you'll create a little domain specific language (DSL).
</p>
<br />
<img style="float: right" src="image/technique/SmellyFish.png"/>
<a name="sameStructure"> </a>
<h1>Examples all have the same structure</h1>
<h2>Your examples are too generic</h2>
<p>
If the examples in your specifications look very similar (i.e. they have
the same kind of context set-up, the same kind of checks etc.) this is
a strong sign that the examples are too generic.
</p>
<h2>So, focus the examples more carefully</h2>
<p>
The examples should demonstrate the particular behaviour you are
describing and should not include any irrelevant details. Push
everything you can into the fixture code.
</p>
<blockquote class="badExample">
Given the following orders:
<br/>
<br/>
<table class="exampleTable">
<tr>
<th>Order ID</th>
<th>Status</th>
<th>Requester</th>
<th>Date</th>
<th>Service Level</th>
</tr>
<tr>
<td>1</td>
<td>Active</td>
<td>john.smith</td>
<td>13-Oct-2007</td>
<td>High</td>
</tr>
</table>
<br />When order <b>1</b> is <b>cancelled</b>,
<br />Then the orders become:
<br/>
<br/>
<table class="exampleTable">
<tr>
<th>Order ID</th>
<th>Status</th>
<th>Requester</th>
<th>Date</th>
<th>Service Level</th>
</tr>
<tr>
<td>1</td>
<td>Cancelled</td>
<td>john.smith</td>
<td>13-Oct-2007</td>
<td>High</td>
</tr>
</table>
</blockquote>
<p>
The layout above is "one size fits all". It contains lots of
context that is not relevant to the behaviour we want to show.
</p>
<p>
Focusing the examples improves their clarity and reduces duplication:
</p>
<blockquote class="goodExample">
When an <b>Active</b> order is cancelled,
its status is displayed as <b>Cancelled</b>.
</blockquote>
</div> <!-- memo -->
</div> <!-- content -->
</div> <!-- page -->
<div class="copyright">
<a rel="license" href="http://creativecommons.org/licenses/by/4.0/"><img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by/4.0/88x31.png" /></a><br />This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by/4.0/">Creative Commons Attribution 4.0 International License</a>.
</div> <!-- copyright -->
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-58172036-1', 'auto');
ga('send', 'pageview');
</script>
<script type="text/javascript">
function googleTranslateElementInit() {
new google.translate.TranslateElement({pageLanguage: 'en', layout: google.translate.TranslateElement.InlineLayout.SIMPLE, gaTrack: true, gaId: 'UA-58172036-1'}, 'google_translate_element');
}
</script>
<script type="text/javascript" src="//translate.google.com/translate_a/element.js?cb=googleTranslateElementInit"></script>
</body>
</html>