You are on page 1of 832

xUnit

title.indd 1

08.09.2008 10:39:10

xUnit
Test Patterns
Refactoring
Test Code

Gerard Meszaros

ADDISONWESLEY
Upper Saddle River, NJ Boston Indianapolis San Francisco
New York Toronto Montreal London Munich Paris Madrid
Capetown Sydney Tokio Singapore Mexico City

title.indd 2

08.09.2008 10:39:10


xUnit


2009

title.indd 3

08.09.2008 10:39:11

32.973.26018.2.75
53
681.3.07

..
. ..
..
:
info@williamspublishing.com, http://www.williamspublishing.com
, .
53 xUnit: . : . .  . :
.. , 2009.  832 . : .  . . .
ISBN 9785845914484 (.)
,
, , , 
, . I

( ). II III
,
. , III

, 
, .
, 
.
xUnit, 
.
32.973.26 018.2.75

.

, , 
,
AddisonWesley Publishing Company, Inc.
Authorized translation from the English language edition published by AddisonWesley, Copyright 2007.
All rights reserved. No part of this book may be reproduced or transmitted in any form or by any means, elec
tronic or mechanical, including photocopying, recording or by any information storage retrieval system, without
permission from the publisher.
Russian language edition is published by Williams Publishing House according to the Agreement with R&I
Enterprises International, Copyright 2009.
ISBN 9785845914484 (.)
ISBN 9780131495050 (.)

. 4

, 2009
Pearson Education, Inc., 2007

. 5

19
21
23
29
31
43

I.

59

1.
2.
3.
4.
5.
6.
7. xUnit
8.
9.
10.
11.
12.
13.
14.

61
67
75
85
93
103
127
137
147
159
175
201
213
221

II.

227

15.
16.
17.

229
263
295

. 6

III.

309

18.
19. xUnit
20.
21.
22.
23.
24.
25.
26.
27.

311
377
433
483
517
537
603
657
683
717

IV.

735

.
. xUnit
. xUnit
.
.
. ,
. ,

737
743
749
755
759
763
767

784
813
827

. 7

19

21

23
23
24
26
26
27
27

29


xUnit

31
31
31
32
32
34
34
34
35
35
36
38
38
39
39
40
40
41
41
42
42

43
43
43

. 8

44
44
47
51
54
55
56

I.

59

1.

61

61
61
62
62
63
64
65
65

2.

67

67
67
67
68
68
69
69
70
73
74

3.

75








( )




75
75
76
77
77
78
79
80
82
84
84

. 9

4.

85

85
85
86
86
86
87
88
89

5.

93

: (Write the Tests First)


: (Design for Testability)
: (Use the Front Door First)
: (Communicate Intent)
: (Dont Modify the SUT)
: (Keep Tests Independent)
: (Isolate the SUT)
: (Minimize Test Overlap)
: (Minimize Untestable Code)
:
(Keep Test Logic Out of Production Code)
: (Verify One Condition per Test)
: R (Test Concerns Separately)
:
(Ensure Commensurate Effort and Responsibility)

93
93
94
94
94
95
95
96
97
98
98

90
90
90
91

99
99
101
101
101

6.

103








xUnit
xUnit

103
103
104
104
106
107
108
109
110
111
111

10

. 10






, ,

,



112
114
115
116
118
118
118
118
119
120
123
125

7. xUnit

127


xUnit







xUnit


xUnit

127
127
128
128
128
130
130
131
131
133
134
134
134
135

8.

137

137
137
137
139
139
140
140
141
143
145
145
146

9.

147

147
147
148

. 11

11

148
149
152
153
154
154
156
157

10.

159



: ?


R










if






159
159
160
161
162
163
163
164
164
165
166
166
168
168
169
170
171
172
172
172
173
173
174

11.

175

175
175
176
176
178
179
183
183
189
190
192

12

. 12

197
197
198
198
198
198
199

12.

201


xUnit
















201
201
202
203
203
203
205
205
206
206
208
208
209
210
211
211
211
212
212

13.

213




,





(!)

213
213
214
214
215
217
217
218
219
219
219

14.

221

221
221
222
223

. 13

13
223
224
225
225
226

II.

227

15.

229

(Obscure Test)
(Conditional Test Logic)
(HardRtoRTest Code)
(Test Code Duplication)
(Test Logic in Production)

230
243
251
254
257

16.

263

(Assertion Roulette)
(Erratic Test)
(Fragile Test)
(Frequent Debuggin)
(Manual Intervention)
(Slow Tests)

264
267
277
285
287
289

17.

295

(Buggy Test)
(Developers Not Writing Tests)
(High Test Maintenance Cost)
(Production Bugs)

296
298
300
303

III.

309

18.

311

(Recorded Test)
(Scripted Test)
(DataRDriven Test)
(Test Automation Framework)
(Minimal Fixture)
(Standard Fixture)
(Fresh Fixture)
(Shared Fixture)
(Back Door Manipulation)
(Layer Test)

312
319
322
332
336
338
344
350
359
368

19. xUnit

377

(Test Method)
(FourRPhase Test)
(Assertion Method)

378
387
390

14

. 14

(Assertion Message)
(Testcase Class)
(Test Runner)
(Testcase Object)
(Test Suite Object)
(Test Discovery)
(Test Enumeration)
(Test Selection)

398
401
405
410
414
420
425
429

20.

433

(InRline Setup)
(Delegated Setup)
(Creation Method)
(Implicit Setup)
(Prebuilt Fixture)
(Lazy Setup)
(Suite Fixture Setup)
(Setup Decorator)
(Chained Tests)

434
437
441
449
454
460
465
471
477

21.

483

(State Verification)
(Behavior Verification)
(Custom Assertion)
R (Delta Assertion)
(Guard Assertion)
(Unfinished Test Assertion)

484
489
495
505
510
514

22.

517

(GarbageRCollected Teardown)
(Automated Teardown)
(InRline Teardown)
(Implicit Teardown)

518
521
527
533

23.

537

(Test Double)
(Test Stub)
(Test Spy)
(Mock Object)
(Fake Object)
(Configurable Test Double)
(HardRCoded Test Double)
(TestRSpecific Subclass)

538
544
552
558
565
571
581
591

24.

603

(Named Test Suite)


(Test Utility Method)

604
610

. 15

15

(Parameterized Test)
(Testcase Class per Class)
(Testcase Class per Feature)
(Testcase Class per Fixture)
(Testcase Superclass)
(Test Helper)

618
627
633
639
646
651

25.

657

(Database Sandbox)
(Stored Procedure Test)
(Table Truncation Teardown)
(Transaction Rollback Teardown)

658
662
668
675

26.

683

(Dependency Injection)
(Dependency Lookup)
(Humble Object)
(Test Hook)

684
692
700
713

27.

717

(Literal Value)
(Derived Value)
(Generated Value)
R (Dummy Object)

718
722
726
730

IV.

735

.
. xUnit
. xUnit
.
.
. ,
. ,

737
743
749
755
759
763
767

784
813
827

. 16

,
Nortel 1995 ClearStream Consulting , ,
, . ,
27 2006 , .

. 17

. 18


C hapter Name

Sub/Category

Pattern 11

P attern

V
ariation of

P attern
Variation
described

separately

. 19

Pattern 22

C hapter N ame

A lternativ e P attern

from
O ther C hapter
Sub/Category

v ariation of

use d w ith

e ach
othe r

Pattern

Smell

Cause

of Smell

le ads to

Al ternativ e

P
attern 1
Al ternativ e

Pa
ttern 2

Sm
ell

Sm
ell

20

xUnit

Fresh Fixture Setup

. 20


junit.org, : 

. JUnit , 
. , 
. JUnit 
: 
. ,
JUnit .
, JUnit. 
. xUnit,
Java. (, Java:
Smalltalk .)
xUnit, , 
:
, 
.
.
, xUnit .
xUnit 
.  
, 
.
.

.
. .
, ,
. ,
(eXtreme Programming), , 
xUnit . ,
.
, . ( 
,
.) ,
, . ,

. 21

22


, .
Design Patterns ( $ $
, , 2005 .)  
.
xUnit.
,
,
, ThoughtWorks

. 22



4 [Ref] .
, $
, . $
, $$$$ ,
. $
( ).
, ( ).
. $
$$$$ . ,
,
. .
.
.
1996 ,
, 
,
( , Observer).
,
. , 

, .
, .
.
, 
. (Dictionary),

. 
, 
. , .
, ,
.

. 
. ,

. 23

24

. ,
(Mock Object, . 558)
(Test Automation Framework, . 332).


1999 OOPSLA, 
[XPE].
 
, 
. 
PLoP (Pattern Languages of Programs) 1994 .

ClearStream Consulting. OOPSLA

, ,
.
.

, , ,
. ,
, 
.
: 
.

, , 
.
. ,
. 
. , , 90%
, 
.

, 
. . , 

.
, ,
.
,
.
, ; 
.
,
.

. 24

25


(Test Utility Method, . 610).
.

, 
, .
(Creation Method, . 441).

.
$
(Parameterized Creation Method).


, , 
. (Paramete
rized Creation Method) $
(Test Helper, . 651), 
,
(One Bad Attribute).

,
1.
,  
,
. (Anonymous
Creation Method, . 443), .
, (Fragile
Test, . 277), .
. 

. ,
. 
. , ( 
; )
, . 
, 
.
,
. .
,
. 
.

.
XP2001.
,
1

, 
.

. 25

26

.
( ).
(test smell) .
, 
[Ref]2.

. #
. #
xUnit
.
, #
, # #
.
ClearStream Consulting
. #
, . #
, . #
, .
,
. , #
,
#### #
.
, ,
, . ,
?
, #
. #
( ) . #
, , , #
.



(, ), #
, , ,
#
. #
, xUnit. , #
,
2

[Ref] #
. #### . .

. 26

27

xUnit . #
Fit [FitB] .
, , #
, . #

. , #
.
( ) ,
.
I, #
, , , II, . , #
18, , , #
, #
. 3,
.


.
, : #
?
. #
, Galloping Gertie ( #
) Iron Workers Memorial Bridge ( #
, ).
,
, ,
. New River Gorge #
. 1980# . #
:
. #
, , .
: ,
.

!
, , .
, , #
. .
.
.
, , ,
, .

. 27

28

, ,
. #
.
:
info@williamspublishing.com
E#mail:
http://www.williamspublishing.com
WWW:
:
:
:

. 28

127055, . , . , . 43, . 1
03150, , / 152


,
. , .
, , , 
. ( 
) , , 
. 
, .
, , .
(Heather Armitage),
. 
, ,
. , (Alf
Skrastins), .
 , 
,
: (Grania Devine) Selkirk Lodge,
(Tannis Dakin) Sorcerer Lodge, (Dave Flear)
(Aaron Cooperman) Sol Mountain Touring. 
!
, , 
. (Robert C. Uncle Bob Martin)
.
(Lisa Crispin) (Rick Mugridge). (Jeremy Miller),
(Alistair Duguid), (Michael Hedgpeth)
(Andrew Stopford) .
PLoP,
:
(Michael Stahl), (Danny Dig) (Joe Yoder). 
.
 PLoP 2004,
(Eugene Wallingford), (Ralph Johnson) 
(Joseph Bergin). (Brian Foote) SAG 
MP3 .
.

, http://xunitpatterns.com. 
, 

. 29

30

.
(Javid Jamae), (Philip Nelson), (Tomasz Ga
jewski), (John Hurst), (Sven Gorts), (Bradley T.
Landis), (Cdric Beust), (Joseph Pelrine),
(Sebastian Bergmann), (Kevin Rutherford),
(Scott W. Ambler), (J. B. Rainsberger), (Oli Bye),
(Dale Emery), (David Nunn), (Alex Chaffee), 
(Burkhardt Hufnagel), (Johannes Brodwall),
(Bret Pettichord), (Clint Shank), (Sunil Jo
glekar), (Rachel Davies), (Nat Pryce), (Paul
Hodgetts), (Owen Rogers), (Amir Kolsky), 
(Kevin Lawrence), (Alistair Cockburn), (Michael
Feathers) (Joe Schmetzer).
(Neal Norwitz), (Markus Gaelli), (Stephane Du
casse) (Stefan Reichhart).
 
xUnit.
. 
. , 
. .
, 
ClearStream Consulting. 

. , 
.
(Jennitta Andrea), (Ralph Bohnet), (Dave Braat),
(Russel Bryant), (Greg Cook), (Geoff Hardy), (Shaun
Smith) (Thomas Tannahill).
. ,
25, CVS 
. ClearStream Consulting


. ,
(Denis Clelland) (Luke McFarlane)!
,
. .
(Joshua Kerievsky) .
(Shaun Smith)
. 
, CSS, Ruby, 
Wiki , 

. , , 
.

. 30


,  
.
, 
. .
, , 
.


. 
,
. , , 
.

( xUnit), 
.


. 
, . 
, . 
.
, , . , 
( ), 
.

. .

, . 
, 
.

.
, !

. 31

32

, , ,
.
. 
, . 
.
, .
,
, ,
. : 
?


, .
,  . (,
?)
.
. 
, , 
. .
,
. 
, .
( 
, , 
.)


.
1980 Bell
Northern Researsh, Nortel, 

.
, 
. 
,
. , 

,  
.

,
. . 

. , 

. 32

33

.
, .




. , ,
. ,
 , 
, .


(, 
), 
(
, , 
).
. 

. ,
, .


 
. 
, . 

.
,
. 
. 
Web 
, ,
HTML, .


, /
(test fixture). (test context)
. 
, . ,
. 
.

. 33

34



. (
, ), (,
/ ).
.



. , 
, . 
xUnit
.



. 
, .


(test driven development  TDD),
, , ,
, 
. ,
.
: , 
, .

? , , . 


. , ; 
!
. .
( 
) . 

. , 
 , 
.

, . 
. 

. 34

35

.

, , .
: 
, 
.


,
.
, . 
, (refactoring) ,

.

, 
, . ,
,

. 
. 
.
1. (Fully Automated Tests,
. 81), .
2. .


xUnit. ,
.
, , 

.

. , 
, 
. .
,
. 
. , ,
.
. ( )
. 

. 35

36

, 
.
,
.

,
.
. 
, .

. , .
(Shared Fixture, . 350)
(Fresh Fixture, . 344)
.
6, .

. 
. . 
(Mock
Object, . 558).
.

. .
.
(block closure) Smalltalk
(Expected Exception
Test) $
(Mock Object) Java. ,
(Simple Success Test), ,
.

.

.
, , 
.
, . 
, 
. 
.
, 
. ,
. 
3, ,
5, .
[AP]. (test
smells) . 
. (code smells)

. 36

37

[Ref],
xUnit XP2001 [RTC].
, 
, ( ),
(
). , 
II, .


.
,
. 
, 
.
.
, .
, .


, ,
. , 
,
.
, . 
,
. : ...? , 
,  ,
. 
. 
, 
.
.
.
, , 
.
.
, . 
, , 
. , 
, .
, .

. 
.

. 37

38

.
.
: ( ) .

:
( ).
,
. +
. ,
,
.
, +
. +
(.. +
),
.
, .


+
, .
. +
. +
.
, .. +
, . ( 
, : ,
? , ! ++++ .
, .) , +
, , +
.
(Mystery Guest).


, +
. ,
, .
.
.
, .
, ( , Mystery
Guest) (Obscure Test) ,
(Obscure Test), 
(Irrelevant Information,) , +
.

. 38

39


. ,

. ,
,
.

. ,
[Ref]. , 
, . .
[RtP].
,
! 
, 
? , ,
? 
. ,
( 6,
), .
, .
, .
,
, ,
. 
() .
, , .

,
(  ). 

. ,
, (
, ).
. 
. 
. . 
. 
.
, , , ,
, . ,
.

. 39

40

: 
.
. ,
. , 
.


(system un
der test  SUT) . , 
.
(). , 
, ( ).
,
, , 
,
. (depended
on component  DOC). , 
(. 1).

Unit1
Test

Unit1
SUT

Unit2
Test

Comp1
Test

Comp2
Test

App1
Test

Unit2
SUT

Comp1
SUT
Comp2
SUT

App1
SUT

. 1. . .
,
.

. 40

41

xUnit

xUnit, JUnit,
.
JUnit ( 
).
. , xUnit,
xUnit.
Java ,
JUnit 
xUnit. , 
assertTrue (JUnit) , NUnit
Assert.IsTrue, SUnit  should:, VbUnit  verify. 
SUnit, VbUnit, Test::Unit 
. JUnit
.


.
, 
. , .
, 
, ,
.

, , ( ) 
, .
Ruby XML,
. Java C# ,
ClearStream .

xUnit. 
. ,
xUnit. 

xUnit. , Java C#,

.
, 
65 . 
. ,

. , 
, ,  !

. 41

42


, .
.
UML (Unified Modeling Language), 
. ,
() () UML,
, 
. 19,
xUnit.  .
, ,
. . 
. UML, .
(assertion)  
(test failure). 
. . 
. ,
, , .

,
. , 
.
. !
, , 
.
, . , 
.

. 42



.
, 
. !
.
, . ,
, .
, .


, .
public void testAddItemQuantity_severalQuantity_v1(){
Address billingAddress = null;
Address shippingAddress = null;
Customer customer = null;
Product product = null;
Invoice invoice = null;
try {
//
billingAddress = new Address("1222 1st St SW",
"Calgary", "Alberta", "T2N 2V2","Canada");
shippingAddress = new Address("1333 1st St SW",
"Calgary", "Alberta", "T2N 2V2", "Canada");
customer = new Customer(99, "John", "Doe",
new BigDecimal("30"),
billingAddress,
shippingAddress);
product = new Product(88, "SomeWidget",
new BigDecimal("19.99"));
invoice = new Invoice(customer);
//
invoice.addItemQuantity(product, 5);
//
List lineItems = invoice.getLineItems();
if (lineItems.size() == 1) {
LineItem actItem = (LineItem) lineItems.get(0);
assertEquals("inv", invoice, actItem.getInv());

. 43

44

assertEquals("prod", product, actItem.getProd());


assertEquals("quant", 5, actItem.getQuantity());
assertEquals("discount", new BigDecimal("30"),
actItem.getPercentDiscount());
assertEquals("unit price",new BigDecimal("19.99"),
actItem.getUnitPrice());
assertEquals("extended", new BigDecimal("69.96"),
actItem.getExtendedPrice());
} else {
assertTrue("Invoice should have 1 item", false);
}
} finally {
//
deleteObject(invoice);
deleteObject(product);
deleteObject(customer);
deleteObject(billingAddress);
deleteObject(shippingAddress);
}
}

1, , .
(Obscure Test, . 230) , 
. , ,
.


. 
, .
List lineItems = invoice.getLineItems();
if (lineItems.size() == 1) {
LineItem actItem = (LineItem) lineItems.get(0);
assertEquals("inv", invoice, actItem.getInv());
assertEquals("prod", product, actItem.getProd());
assertEquals("quant", 5, actItem.getQuantity());
assertEquals("discount", new BigDecimal("30"),
actItem.getPercentDiscount());
assertEquals("unit price",new BigDecimal("19.99"),
actItem.getUnitPrice());
assertEquals("extended", new BigDecimal("69.96"),
actItem.getExtendedPrice());
} else {

65 ,
, . 25 , 
, 6 , 4 2 . 
37 .

. 44

45

assertTrue("Invoice should have 1 item", false);


}

.
assertTrue false 
. ? fail.
List lineItems = invoice.getLineItems();
if (lineItems.size() == 1) {
LineItem actItem = (LineItem) lineItems.get(0);
assertEquals("inv", invoice, actItem.getInv());
assertEquals("prod", product, actItem.getProd());
assertEquals("quant", 5, actItem.getQuantity());
assertEquals("discount", new BigDecimal("30"),
actItem.getPercentDiscount());
assertEquals("unit price",new BigDecimal("19.99"),
actItem.getUnitPrice());
assertEquals("extended", new BigDecimal("69.96"),
actItem.getExtendedPrice());
} else {
fail("Invoice should have exactly one line item");
}

(Extract Method),
(Stated Outcome Asser
tion; . , Assertion Method, . 390) 
$
(Single Outcome Assertion; . , Assertion Method).
, . ,
? , , 
LineItem, .
,
.
 $
(Expected Object; . , State Verification, . 484)
. , 
, . 
LineItem, ,
unitPrice extendedPrice, product.
List lineItems = invoice.getLineItems();
if (lineItems.size() == 1) {
LineItem expected =
new LineItem(invoice, product, 5,
new BigDecimal("30"),
new BigDecimal("69.96"));
LineItem actItem = (LineItem) lineItems.get(0);
assertEquals("invoice", expected.getInv(),
actItem.getInv());
assertEquals("product", expected.getProd(),
actItem.getProd());
assertEquals("quantity",expected.getQuantity(),
actItem.getQuantity());

. 45

46

assertEquals("discount",
expected.getPercentDiscount(),
actItem.getPercentDiscount());
assertEquals("unit pr", new BigDecimal("19.99"),
actItem.getUnitPrice());
assertEquals("extend pr",new BigDecimal("69.96"),
actItem.getExtendedPrice());
} else {
fail("Invoice should have exactly one line item");
}

(Expected Object)
assertEquals.
List lineItems = invoice.getLineItems();
if (lineItems.size() == 1) {
LineItem expected =
new LineItem(invoice, product,5,
new BigDecimal("30"),
new BigDecimal("69.96"));
LineItem actItem = (LineItem) lineItems.get(0);
assertEquals("invoice", expected, actItem);
} else {
fail("Invoice should have exactly one line item");
}

, (Preserve Whole Object)


. ! 
if ? , , 
?
(Conditional Test Logic, . 243). ,
(Guard Assertion, . 510) .
(Replace Conditional with
Guard Clause) if... else fail()...
. (Guard Assertion) 
,
(Conditional Test Logic).
List lineItems = invoice.getLineItems();
assertEquals("number of items", 1,lineItems.size());
LineItem expected =
new LineItem(invoice, product, 5,
new BigDecimal("30"),
new BigDecimal("69.96"));
LineItem actItem = (LineItem) lineItems.get(0);
assertEquals("invoice", expected, actItem);

11 4 , 
2.  .
? ?

, !
.

. 46

47

,
, expectedLineItem. ,
(Extract Method)
(Custom Assertion, . 495).
LineItem expected =
new LineItem(invoice, product, 5,
new BigDecimal("30"
new BigDecimal("69.96"
assertContainsExactlyOneLineItem(invoice, expected);

! , ,
.
public void testAddItemQuantity_severalQuantity_v6(){
Address billingAddress = null;
Address shippingAddress = null;
Customer customer = null;
Product product = null;
Invoice invoice = null;
try {
//

billingAddress = new Address("1222 1st St SW",
"Calgary", "Alberta", "T2N 2V2", "Canada");
shippingAddress = new Address("1333 1st St SW",
"Calgary", "Alberta", "T2N 2V2", "Canada");
customer = new Customer(99, "John", "Doe",
new BigDecimal("30"),
billingAddress,
shippingAddress);
product = new Product(88, "SomeWidget",
new BigDecimal("19.99"));
invoice = new Invoice(customer);
//
invoice.addItemQuantity(product, 5);
//
LineItem expected =
new LineItem(invoice, product, 5,
new BigDecimal("30"
new BigDecimal("69.96"));
assertContainsExactlyOneLineItem(invoice, expected);
} finally {
//
deleteObject(invoice);
deleteObject(product);
deleteObject(customer);
deleteObject(billingAddress);
deleteObject(shippingAddress);
}
}


, ,
finally . ?

. 47

48

} finally {
//
deleteObject(invoice);
deleteObject(product);
deleteObject(customer);
deleteObject(billingAddress);
deleteObject(shippingAddress);
}

,
try/finally.
. (Test Method, . 378)
finally 
. ,

(Test Automation Framework, . 332). finally
. 
.
finally deleteObject
. , .
, !
. ,
deleteObject ?
deleteObject . 
try/finally,
deleteObject. ?
try/finally 
. .
.
} finally {
//

try {
deleteObject(invoice);
} finally {
try {
deleteObject(product);
} finally {
try {
deleteObject(customer);
} finally {
try {
deleteObject(billingAddress);
} finally {
deleteObject(shippingAddress);
}
}
}
}

. 48

49

(Complex Teardown; .
, Obscure Test). ? 
? , .
, tearDown. $
(Test Method). , tearDown
finally, try/finally . ,
: 
.
,
(Shared Fixture, . 350), 
. , 
, (Unrepeatable Test; . $
, Erratic Test) (Interacting Tests), 
(Shared Fixture).
(Shared Fixture) $
(Mystery Guest; . , Obscure Test)3.
(Fresh Fix
ture, . 344), . 
, 
. ,
(, 
). ,
, ,
.
(Test
Automation Framework) . 
,
.
.
//

billingAddress = new Address("1222 1st St SW", "Calgary",
"Alberta", "T2N 2V2", "Canada");
registerTestObject(billingAddress);
shippingAddress = new Address("1333 1st St SW", "Calgary",
"Alberta","T2N 2V2", "Canada");
registerTestObject(shippingAddress);
customer = new Customer(99, "John", "Doe",
new BigDecimal("30"),
billingAddress,
shippingAddress);
registerTestObject(shippingAddress);
product = new Product(88, "SomeWidget",
new BigDecimal("19.99"));
registerTestObject(shippingAddress);
invoice = new Invoice(customer);
registerTestObject(shippingAddress);

. 49

, .

50

.
List testObjects;
protected void setUp() throws Exception {
super.setUp();
testObjects = new ArrayList();
}
protected void registerTestObject(Object testObject) {
testObjects.add(testObject);
}

testObject
.
public void tearDown() {
Iterator i = testObjects.iterator();
while (i.hasNext()) {
try {
deleteObject(i.next());
} catch (RuntimeException e) {
// .
// .
}
}
}

.
public void testAddItemQuantity_severalQuantity_v8(){
Address billingAddress = null;
Address shippingAddress = null;
Customer customer = null;
Product product = null;
Invoice invoice = null;
//

billingAddress = new Address("1222 1st St SW", "Calgary",
"Alberta", "T2N 2V2", "Canada");
registerTestObject(billingAddress);
shippingAddress = new Address("1333 1st St SW", "Calgary",
"Alberta","T2N 2V2", "Canada");
registerTestObject(shippingAddress);
customer = new Customer(99, "John", "Doe",
new BigDecimal("30"),
billingAddress,
shippingAddress);
registerTestObject(shippingAddress);
product = new Product(88, "SomeWidget",
new BigDecimal("19.99"));
registerTestObject(shippingAddress);
invoice = new Invoice(customer);
registerTestObject(shippingAddress);
//
invoice.addItemQuantity(product, 5);
//
LineItem expected =
new LineItem(invoice, product, 5,
new BigDecimal("30"),

. 50

51

new BigDecimal("69.96"));
assertContainsExactlyOneLineItem(invoice, expected);
}

try/finally, , registerTestObject, . . 
, null,
? 
, finally. , 
, .
public void testAddItemQuantity_severalQuantity_v9(){
//

Address billingAddress = new Address("1222 1st St SW",
"Calgary", "Alberta", "T2N 2V2", "Canada");
registerTestObject(billingAddress);
Address shippingAddress = new Address("1333 1st St SW",
"Calgary", "Alberta", "T2N 2V2", "Canada");
registerTestObject(shippingAddress);
Customer customer = new Customer(99, "John", "Doe",
new BigDecimal("30"),
billingAddress,
shippingAddress);
registerTestObject(shippingAddress);
Product product = new Product(88, "SomeWidget",
new BigDecimal("19.99"));
registerTestObject(shippingAddress);
Invoice invoice = new Invoice(customer);
registerTestObject(shippingAddress);
//
invoice.addItemQuantity(product, 5);
//
LineItem expected =
new LineItem(invoice, product, 5,
new BigDecimal("30"),
new BigDecimal("69.95"));
assertContainsExactlyOneLineItem(invoice, expected);
}


,
. 
(Extract Method) 
registerTestObject (Creation Method, . 441).
. (Creation Method)
:

( ,
).

. 51

52

public void testAddItemQuantity_severalQuantity_v10(){


//

Address billingAddress =
createAddress( "1222 1st St SW", "Calgary", "Alberta",
"T2N 2V2", "Canada");
Address shippingAddress =
createAddress( "1333 1st St SW", "Calgary", "Alberta",
"T2N 2V2", "Canada"
Customer customer =
createCustomer( 99, "John", "Doe", new BigDecimal("30"),
billingAddress, shippingAddress);
Product product =
createProduct( 88, "SomeWidget",new BigDecimal("19.99"
Invoice invoice = createInvoice(customer);
//
invoice.addItemQuantity(product, 5);
//
LineItem expected =
new LineItem(invoice, product,5, new BigDecimal("30"),
new BigDecimal("69.96"));
assertContainsExactlyOneLineItem(invoice, expected);
}

.

. ? 
? ?
(HardCoded
Test Data; . , Obscure Test). , 
,
(HardCoded Test Data)
(Unrepeatable Test), (Interacting Tests)
(Test Run War; . , Erratic Test),
, .

.
.
(Creation Method),
. $
(Creation Method), . 
(Extract Method), 
(Creation Method) .
public void testAddItemQuantity_severalQuantity_v11(){
final int QUANTITY = 5;
//

Address billingAddress = createAnAddress();
Address shippingAddress = createAnAddress();
Customer customer = createACustomer(new BigDecimal("30"),
billingAddress, shippingAddress);
Product product = createAProduct(new BigDecimal("19.99"));
Invoice invoice = createInvoice(customer);
//

. 52

53

invoice.addItemQuantity(product, QUANTITY);
//
LineItem expected =
new LineItem(invoice, product, 5, new BigDecimal("30"),
new BigDecimal("69.96"));
assertContainsExactlyOneLineItem(invoice, expected);
}
private Product createAProduct(BigDecimal unitPrice) {
BigDecimal uniqueId = getUniqueNumber();
String uniqueString = uniqueId.toString();
return new Product(uniqueId.toBigInteger().intValue(),
uniqueString, unitPrice);
}

(Anonymous Creation Method; .


, Creation Method), , 
.
,
.
, .
? ,
(Extract Method) 
!  createACustomer, .
public void testAddItemQuantity_severalQuantity_v12(){
//

Customer cust = createACustomer(new BigDecimal("30"));
Product prod = createAProduct(new BigDecimal("19.99"));
Invoice invoice = createInvoice(cust);
//
invoice.addItemQuantity(prod, 5);
//
LineItem expected = new LineItem(invoice, prod, 5,
new BigDecimal("30"), new BigDecimal("69.96"));
assertContainsExactlyOneLineItem(invoice, expected);
}

, ,
, .
,
.
. , 
(HardCoded Test Data) , 
. $
(Replace Magic Number with Symbolic Con
stant). , LineItem
, LineItem 
extendCost .
(Foreign Method), .
Customer Product: 
LineItem 

. 53

54

(Parameterized Creation Method; . $


, Creation Method).
public void testAddItemQuantity_severalQuantity_v13(){
final int QUANTITY = 5;
final BigDecimal UNIT_PRICE = new BigDecimal("19.99");
final BigDecimal CUST_DISCOUNT_PC = new BigDecimal("30");
//

Customer customer = createACustomer(CUST_DISCOUNT_PC);
Product product = createAProduct( UNIT_PRICE);
Invoice invoice = createInvoice(customer);
//
invoice.addItemQuantity(product, QUANTITY);
//
final BigDecimal EXTENDED_PRICE = new BigDecimal("69.96");
LineItem expected =
new LineItem(invoice, product, QUANTITY,
CUST_DISCOUNT_PC, EXTENDED_PRICE);
assertContainsExactlyOneLineItem(invoice, expected);
}

: 69.96?
, .
,
.


.
public void testAddItemQuantity_severalQuantity_v14(){
final int QUANTITY = 5;
final BigDecimal UNIT_PRICE = new BigDecimal("19.99");
final BigDecimal CUST_DISCOUNT_PC = new BigDecimal("30");
//
Customer customer = createACustomer(CUST_DISCOUNT_PC);
Product product = createAProduct( UNIT_PRICE);
Invoice invoice = createInvoice(customer);
//
invoice.addItemQuantity(product, QUANTITY);
//
final BigDecimal BASE_PRICE =
UNIT_PRICE.multiply(new BigDecimal(QUANTITY));
final BigDecimal EXTENDED_PRICE =
BASE_PRICE.subtract(BASE_PRICE.multiply(
CUST_DISCOUNT_PC.movePointLeft(2)));
LineItem expected =
createLineItem(QUANTITY, CUST_DISCOUNT_PC,
EXTENDED_PRICE, product, invoice);
assertContainsExactlyOneLineItem(invoice, expected);
}

BASE_PRICE ()
EXTENDED_PRICE ( ) $

. 54

55

(Introduce Explaining Variable). 


, .
(Tests as Documentation, . 79). 
? , 
,
.


,
. ?
, !
(Test Utility Method, . 610),
. (HigherLevel
Language, . 95).
. , ,
LineItem, 
(Test Utility Method).
public void testAddLineItem_quantityOne(){
final BigDecimal BASE_PRICE = UNIT_PRICE;
final BigDecimal EXTENDED_PRICE = BASE_PRICE;
//

Customer customer = createACustomer(NO_CUST_DISCOUNT);
Invoice invoice = createInvoice(customer);
//

invoice.addItemQuantity(PRODUCT, QUAN_ONE);
//
LineItem expected =
createLineItem( QUAN_ONE, NO_CUST_DISCOUNT,
EXTENDED_PRICE, PRODUCT, invoice);
assertContainsExactlyOneLineItem( invoice, expected );
}
public void testChangeQuantity_severalQuantity(){
final int ORIGINAL_QUANTITY = 3;
final int NEW_QUANTITY = 5;
final BigDecimal BASE_PRICE =
UNIT_PRICE.multiply(
new BigDecimal(NEW_QUANTITY));
final BigDecimal EXTENDED_PRICE =
BASE_PRICE.subtract(BASE_PRICE.multiply(
CUST_DISCOUNT_PC.movePointLeft(2)));
//

Customer customer = createACustomer(CUST_DISCOUNT_PC);
Invoice invoice = createInvoice(customer);
Product product = createAProduct( UNIT_PRICE);
invoice.addItemQuantity(product, ORIGINAL_QUANTITY);
//
invoice.changeQuantityForProduct(product, NEW_QUANTITY);
//
LineItem expected = createLineItem( NEW_QUANTITY,
CUST_DISCOUNT_PC, EXTENDED_PRICE, PRODUCT, invoice);
assertContainsExactlyOneLineItem( invoice, expected );
}

. 55

56


(Test Utility Method).
,
. , 
. , 
. 
.


,
(Test Code Duplication, . 254). ,
Customer Invoice. ? 
QUANTITY CUSTOMER_DISCOUNT_PC.
, . Product 
.
? ! 
(Extract Method) .
(Creation Method).
public void testAddItemQuantity_severalQuantity_v15(){
//

Invoice invoice = createCustomerInvoice(CUST_DISCOUNT_PC);
//
invoice.addItemQuantity(PRODUCT, SEVERAL);
//
final BigDecimal BASE_PRICE =
UNIT_PRICE.multiply(new BigDecimal(SEVERAL));
final BigDecimal EXTENDED_PRICE =
BASE_PRICE.subtract(BASE_PRICE.multiply(
CUST_DISCOUNT_PC.movePointLeft(2)));
LineItem expected = createLineItem( SEVERAL,
CUST_DISCOUNT_PC, EXTENDED_PRICE, PRODUCT, invoice);
assertContainsExactlyOneLineItem(invoice, expected);
}
public void testAddLineItem_quantityOne_v2(){
final BigDecimal BASE_PRICE = UNIT_PRICE;
final BigDecimal EXTENDED_PRICE = BASE_PRICE;
//

Invoice invoice = createCustomerInvoice(NO_CUST_DISCOUNT);
//

invoice.addItemQuantity(PRODUCT, QUAN_ONE);
//
LineItem expected = createLineItem( SEVERAL,
CUST_DISCOUNT_PC, EXTENDED_PRICE, PRODUCT, invoice);
assertContainsExactlyOneLineItem( invoice, expected );
}
public void testChangeQuantity_severalQuantity_V2(){
final int NEW_QUANTITY = SEVERAL + 2;
final BigDecimal BASE_PRICE =
UNIT_PRICE.multiply(
new BigDecimal(NEW_QUANTITY));
final BigDecimal EXTENDED_PRICE =

. 56

57

BASE_PRICE.subtract(BASE_PRICE.multiply(
CUST_DISCOUNT_PC.movePointLeft(2)));
//

Invoice invoice = createCustomerInvoice(CUST_DISCOUNT_PC);
invoice.addItemQuantity(PRODUCT, SEVERAL);
//
invoice.changeQuantityForProduct(PRODUCT, NEW_QUANTITY);
//
LineItem expected = createLineItem( NEW_QUANTITY,
CUST_DISCOUNT_PC, EXTENDED_PRICE, PRODUCT, invoice);
assertContainsExactlyOneLineItem( invoice, expected );
}

4 35 6.
!
setUp,
,
Customer/Discount/Invoce. (Test
Utility Method) (Testcase Class,
. 401), (Extract Superclass)
(Testcase Superclass, . 646), 
(Pull Up Method) $
(Test Utility Method).

, 6 , 
.

. 57

. 58

. 59

. 60



, . 
, .
? ?
, ! .
, 
.


,
. 
. , 
. ,
, .
,
, 
.
.

. 61

. 
.

.
.

. 
.

. , , 
.

. (Test Method, . 378)


(Testcase Class, . 401).

62


: ?
. , , 
1.
, /
(storytestdriven development), /
(customer tests), 
. 
(unit tests),
, .
.
2.

(test suites) 
. 
.
(Smoke Tests), 
(Integration Build).

,
( 
). 
.

. , 
. . 
/ (business logic), 
,
. , ,
,  
.


. 
 , 
. , .
, . 
(Scripted Test, . 319)
, (DataDriven Test, . 322). ,
1

, 
!
2 $
(Missing Unit Test; . , Production Bugs, . 303), 
.
.

. 62

63

.
(Recorded Test, . 312) 

. , ,
, 
(Fragile Test, . 277).
, 
. ,
, (Obscure
Test, c. 230) (Defect
Localization, . 78), .
, (Tests as
Documentation, . 79) .

(Subcutaneuos Test; . , Layer
Test, . 368) (Service Facade)
[CJ2EEP].  ,
.
.
, 
, . (Fresh Fixture,
. 344) (Interacting Tests; .
, Erratic Test, . 267), ,
.
(Shared Fixture, . 350) ,
(Immutable Shard Fixture).
(Erratic Test).
,

(Test Double, . 538),
, . 
 
, $
(Fake Objects, . 565)
. $
(Chained Tests, . 477)  $
(Interacting Tests).


$
(Fully Automated Test, . 81).
.
(Defect Localization), (Single Condition Test,
. 99), . ,
,

. 63

64

(FourPhase Test, . 387) .


(Tests as Documentation).

(Interacting Tests)
(fixture teardown). (Testcase Class)
(. , Testcase Class per Class,
. 627). (Test Method)
. (Test Method) 
(Delegated Setup, . 437) 
(Minimal Fixture, . 336). 
(Creation
Method, . 441) .
(SelfChecking Test, . 81) 
(Expected Objects; .
, State Verification, . 484) ,
(system under test  SUT). 
(Equality Assertions; . 
, Assertion Method, . 390) (Custom Assertion, . 495), 
(testspecific equality).
, 
(Verification Method; . 
, Custom Assertion), .
(Untested Code; . 
, Production Bugs, . 303)  ,
(Test Stub, . 544)
(indirect inputs) . 
(Untested Requirements; . , Production Bugs)  
,
(Mock Object, . 558)
(indirect outputs) .


, 
. 
,
(Subcutaneous Test) (Service Layer Test;
. , Layer Test).
(Database Sandbox, . 658) ( )
, . 
(GarbageCollected
Teardown, . 518),
(
(Resource Leakage). , 
(Slow Tests, . 289)
( ).

. 64

65


. (Humble
Dialog; . , Humble Object, . 700), 
,
(, / )
, .

, ,
(component tests), 
. , ,
, (Test Double).

(Dependency Injection, . 684), (Dependency Lookup, . 692)
(Subclassed Singleton; .
, TestSpecific Subclass, . 591).


(Testcase Class)
(Test Method),
. $
(Testcase Class per Feature, . 633) $
(Testcase Class per Fixture, . 639) . $

setUp. (Implicit Setup,
. 449). (Test Suite Object, . 414)
(Test Suite Object).
(Suite of Suites), (Testcase Class).
, (Test Suite Object) 
.
, 
, .


, ,
. 214 
.
,
II III.
, 
.  2, , 
, .

. 65

. 66



1, , ,
.
, . 
,  : , 
, 
.


:

. , 
 .
3, ,
. : , !
: ,
? .
, ,
. , , 
.
[RTC] XP2001 .
, .
, 
.
(test smells).
.


.
, . 

. 67

68

. 
. , 
(.. ).
, 
. , (..
, , 
). ,
( ).

. 
, 
. , ,
.


, :
(code smells), ,
(behavior smell), .
. ,
, ..
.
. 
.
, (Scripted Test, . 319)
(Recorded Test, . 312). , 
. ,
(Obscure Test, . 230),
, .
, , 
( )
, ; 
, . ,
.
,
. 
 ,
. (project smell)
.


,
.
. ,
.

. 68

69


. ;
. , 
, .
, , 

.
, 
, . ,
. 
, ,
, . :
. : 
, 
.
. 
,  . ,
, , .
, .
 
1.
, 
. .
, .


, ,
, . 
II.


. 
.
,
, .
, ,
. , ,
. 
, , , 
, , 
.
(Production Bugs, . 303) , , 
1

. 69

70

: 
?

, 
. 
,
( ). (root
cause analysis) ,
, $
(Buggy Test, . 296). , !
, (production code).
(Buggy Test)
(High Test Maintenance Cost, . 300),
.
(..
)  ,


. ,
. ( 
.  ,
 . ,
:

.)
, ,
(Production Bugs) , (Developers
Not Writing Tests, . 298).
.
, ,
, , 
.
, , ,
(Fragile Test, . 277). ,
(Lost Test) 
, (AllTests Suite; .
, Named Test Suite, . 604), 

.


. ,
,
.
(Fragile Test).
,  ,

. 70

71

. 
. 
,
. .
,
.

.

(Interface Sensitivity) ,
 ,
.

.
, 
.

(Behavior Sensitivity) , 
 . ,
, . ,
. 
, 
.

(Data Sensitivity) ,
, .
, 
. 
, .

(Context Sensitivity) , 
 .
,
(,
).


(Fragile Test),
(Fragile Fixture).
.
$
(Standard Fixture, . 338) , ,
.
, 
, .
/
(continuous integration), : 

. (Assertion Roulette, . 264) 
,

. 71

72

. 
.
,
.

, .. , 
, . 
.
(Erratic Test, . 267)
,
. .

(Interacting Tests) ,
(Shared Fixture, . 350).

(Suite of Suites). 
,
(Standard Fixture) , 
.

(Test Run War) , $


(Test Runner, . 405)
(Shared Fixture). 
, 
.

(Unrepeatable Test) 
. $
(Manual Intervention, . 287).

(Frequent Debugging, . 285) , 


.
, 
. $
(Frequent Debugging) , 
.
(Fully Automated Test,
. 81) .
.
, , 
, .
(Manual Intervention) , .
, 
.

(Slow Tests, . 289). 30 , 
.
, , 
. 

. 72

73

.
; $
(Shared Fixture) 
.


,
[Ref]. , , 
. .
, 
.
( ) $
(Obscure Test). ,
: , ,
(Communicate Intent, . 95).
(Buggy Test),
(test maintainer) .
(Conditional Test
Logic, . 243). , 
. , , 
.
(HardCoded Test Data)
. , : 
, ,
. , ,
. (HardCoded Test Data) 
(Erratic Test), 
, (Fragile Fix
ture), .
(HardtoTest Code, . 251) 
, .
, 
, .
(
), . 
(Obscure Test),
.
(Test Code Duplication, . 254)
, . 
,
(Obscure Test). , 

2. 
2

, , 
.

. 73

74

$
(Test Utility Method, . 610),
(Test Method, . 378)3.
.
(Test Logic in Production, . 257) 
, 4. ,
. , 

.


, 
. 3, , , 
.
.
, .

(Test Method) , 
(Flexible Test; . , Conditional Test Logic).
4 Ariane . 257 .

. 74



2, , , 
.
, 
. 
, 
, ,
. ,
. , 
; ,
.



. 
, . 
(.. ),
,
. 
, 
.
, ,
. 
,
. ,  
.
. , ,
.
( ) ( 
). 
.

. 75

76


,
. 
, ,
. , , 
1.
,
.
,
,
. . 3.1 ,
.


( )

. 3.1. ,


.
, ( ) 
.
,
( )
, . 3.2.
, . 3.2
. 3.1 . ,
. 
, 
.

. 76

77


( )

. 3.2.
.



, . ,
.

( )

.
.
( ) . 
,
.


(quality as
surance  QA). ? ? 
:
? 
?

: (Tests as Specification)


.

. 77

:

(Executable Specification)

78

( 
).
.
,
, .

, 
. , ,
.

: (Bug Repellent)
, , .
. 
,
.
. (
, ?)

: (Defect Localization)
! , ,
. , 
. (
),
.
. 
, ; 
: ? $
(Defect Localization). , 
 , (Missing Unit Test; .
, Production Bugs, . 303).
,
. 
, . ,
.
,
( )
(Test Utility Method, . 610), .



 . , 
, . (black box)
.

. 78

79

: (Tests as Documentation)

: , ...? 
(Tests as Documentation).
(, , Self
Checking Test, 
). ,  , , 
, . 
.

( )
,

. .
,

.
(Fully Automated Tests).

: (Tests as Safety Net)



:
. (Safety Net)

. , ,
. , ! 
, .
,
. . , ? 
? ! ! 
, 
2.

.
CVS, Subversion SourceSafe 
, ,
.

: (Do No Harm)

: 
. ,

:

(No Test Risk)

, 
. .

. 79

80


.
 . , 
, 
. 
.
, 
, , , .
, (Test Double,
. 538) . 
: . 
, 
(. 3.3).

Unit1
Test

Unit1
SUT

Unit2
Test

Comp1
Test

Comp2
Test

App1
Test

Unit2
SUT

Comp1
SUT
Comp2
SUT

App1
SUT

. 3.3. . . ,

. Unit1 (
) Unit2 Comp1


.
. ,
3 , 
, .
3

. 80

 .

81

?
.

(Fully Automated Tests) 


.

(SelfChecking Test), ..
.

(Repeatable Tests)
.

(Independent Tests)
.


( ). .

: (Fully Automated Tests)


(Manual Intervention, . 287),
.
. , 
,
. main(),
print , . 

, : (Self
Checking Test) (Repeatable Test).

: (Self/Checking Test)
, 
. :
, . , (Test Runner,
. 405) , .
.
xUnit $
(Graphical Test Runner), (green bar)
. (red bar) , 
.

: (Repeatable Tests)

. $
(Unrepeatable Test; . , Erratic Test, . 267)
. ,
(
).
(Unrepeatable Test) $

. 81

82

(Manual Intervention).
(Nondeterministic Test; . , Erratic Test),
;
. 
, . 
,
, . , , 
, ,
, . 
, .

, . $
(Unrepeatable Test) $
(Shared Fixture, . 350) 
. 
, .
, 
(Automated Teardown, . 521).
, 
(Erratic Test), .


,
.
, . ,
 .
, 
.
, .

( ) . 

, , .
,
. $
(Minimize Test Overlap),
.
, , ,
.
:

. 82


(, Java) ( ) 
, .

83

: (Simple Tests)
, , 
.
, , 
, ,
. 
, (Verify One Condition per Test),
(Test Method, . 378) 
.
(Test Method) 4.
(Test Method) 
, 
. 
. 
, (Test Method)
.

: (Expressive Tests)

(Test Utility Method),
. 
. 
(HigherLevel Language)
(Creation Method, . 441) (Custom Assertion, . 495).
. 
, . 
.
(Communicate Intent), $
(Test Method), . 
$
(Test Utility Method). ,
.

: (Separation of Concerns)
.


(Keep Test Logic Out of Production Code).


(Test Concerns Separately), 
(Obscure Test, . 230).

$
(Test Method). : /
(boundary value) (equivalence class).

. 83

84

, , 
, 
. (, 
), . 
.
. 
11, .



. 
, . ,
.
, . 
50 . 
? , .

. 
, 30 ! ?

: (Robust Test)

.  ,
. 
. ,
; .
(Robust Test).

(Verify One Condition per Test). 
: ,
. $
(Test Utility Method), 
, .



, $
(Fully Automated Tests). 5,
, 4, 
, ,
.

. 84


3, , 
.
, , 
. 
, , 
( ),
,
.


? ! 
( ) .
( 
)
xUnit. , 
, (Mock Object, . 558).

.

( ) .
,
. 
.

. 85

86

( 
)





. ,
. ,
. 
? , (Fully
Automated Tests, . 81) , ,
.
, , ,
. (design for testability) 

. ,
.
.
, ,
. 
; .
,
( ).

, . 
,
(Sensitive Equality; . , Fragile Test, . 277), 
,
. ,
. (Test Double,
. 538) , /
(substitutable dependency) .



,
. :
?

. 86

87

(exampledriven development). ,
, . , 
,
, .
, ,
.
RSpec Ruby
JBehave Java.
xUnit, 
(Executable Specification; . $
, . 77).
 
Fit. 
 . 
!


, 
 
. , 
. 
. , , 
(incremental development).
? , ! 
, ,
. , ,
, .
,
, .
, . 
, ,

. $
(Defect Localization; . , . 77), 
( )
.
,
()
. 
(task)  , (Test
Method, . 378), (Test Method) .
, (Test Method),
, .
,
. 
. 

. 87

88

( 
) ,
.


, 
( 
) , 
.
.
,
. , 
. ,
. 
, 
. 
. ,
. .

. , 
. 
. 4.1.
. 
;
(Test Stub, . 544) (Mock Object)
. , (Test Stub) ,
,
.
(Saboteur; . , Test Stub).

SUT

SUT

SUT

. 4.1. .
,

. 88

89


. 
.
(Test Stub).
. , (Test Stub)
( ,
) 
.
. 4.2 .
, (Test Double).

SUT

SUT

SUT

. 4.2. ,
(Test Double). ,
(Test Double),


. (Defect Localization),
.



, . ,
,
, . 

, .
, . 
(indirect output) 
, ,
, .
(behavior
driven development). $
(Mock Object) (Test Spy, . 552). 

. 89

90


, 
. [MAS].



, 
, .

.
xUnit,
(Standard Fixture, . 338),
(Test Method)
(Testcase Class, . 401).
(Fresh Fixture, . 344) (Test Method) $
(Delegated Setup, . 437) setUp
(Implicit Setup, . 449). , $
(Shared Fixture, . 350),
. 
$
(Test Method).
$
(Minimal Fixture, . 336) (Test Method).

(Fresh Fixture) .


, . 
,
. , (,
, , , 
).
. .

. 90

, 
, .

,
.

91

(State Verification, . 484), 



(Behavior Verification, . 489).

! , .


, 
, . 5, 
, , , 
3, . 
.

. 91

. 92


3, , , ,
. 4,
, 
.
, 
. : 
, , ,
. 
, .
.


(TAM),
. , 
, , 
. ,
. 
.
, ,
. .
, . 
.

. $
(Verify One Condition per Test),
, .

. 93

94

,
.

: (Write the Tests First)


:

(Test-Driven Development),
(Test-First Development)


. , 
, 
, 
.
.

1. (
).
2.
.
. ,
.

: (Design for Testability)


.
, (Write the Tests
First), (Design for Testability)
, , , 
.
, 
. 
[WEwLC].

: (Use the Front Door First)


. 
, 
. , 
.
, 
.
. 
(Back Door Manipulation, . 359) 

(Overcoupled Test; . , Fragile
Test, . 277), .
(Behavior Verification, . 489) (Mock Object, . 558)
(Overspecified Software; .
, Fragile Test) ,
.
:

(Front Door First)

. 94

95

, , 
.
(State Verification, . 484), 
. ,
(LayerCrossing Test) (Behavior
Verification) /
(dependedon components). 
(Test Double, . 538),
(Fake Object, . 565),
(
, , Fake Object).

: (Communicate Intent)
(Fully Automated
:
(HigherTests), (Scripted Test,
Level Language),
. 319), . 
(Single-Glance

Readable)
. 

. 
, , 
: (test maintainer).
( ) (Conditional Test
Logic, . 243) (Obscure Test, . 230).
,
. , 
(Tests as Documentation). , 
.

. (Test Utility Method, . 610)
[SBPP] 
. (Test Method, . 378)
, , ..
.
(Test Utility Method) 
, .

: (Dont Modify the SUT)



(Test Double)
(TestSpecific Subclass, . 591). 
$
(Behavior Verification), .
,
.

. 95

96


(Test Hook, . 713),
(TestSpecific Subclass) 
(Test Double). ,
, .
,
. 

, . 
, . ,
X, Y Z, X Y, 
, , Z. X
Y Z (Test Double). Y Z
(Test Double) . Z 
(Test Double) , 
!
.
(TestSpecific Subclass) 
,
,
.
(TestSpecific Subclass), , 
, , .
:
. X Y Z

X, Y Z .
X, Y Z. ,
, 

.
(, ). ,
.

: (Keep Tests Independent)



,

.
,
. 
, . 
. , 
 , 
, ,
( ) .
:

(Independent Test)

. 96

97

, , , 
, .
(Interacting Tests; . , Erratic Test, . 267)
. , , 
, . 
, , 
, , . 
. , ,
(Interacting Tests).
(Independent Tests) .
(Fresh Fixture, . 344), 
.
(Fresh Fixture) ,
(Shared Fixture, . 350). 
(Erratic
Test), (Lonely Test), (Interacting Tests)
(Test Run War).
(Defect Localization)
.

: (Isolate the SUT)


(
) . 
. 
, ,
, ,
.
(Context Sensitivity; . , Fragile Test)
(Fragile Test).
,
,
. , $
(Untested Code; . , Production Bugs, . 303) $
(Untested Requirement; . , Production Bugs). 
,
.
, , 
. 
(Test Concerns Separately) $
(Keep Tests Independent). , $
(Context Sensitivity),
.

(Test
Double) (Dependency Injection, . 684)
(Dependency Lookup, . 692). 

. 97

98

(TestSpecific Subclass), 
. 
.

: (Minimize Test Overlap)


.

. ,
.
,
. 
,
. ,
. ,
. 
, 
, .
. 
, , . ,
, , 
.

: (Minimize Untestable Code)


$
(Fully Automated Tests).
,
(Test Method). :
.

(Fully Automated Tests), ,
.
.
, 
. 
, .

(Humble Executable; . , Humble Object, . 700). 
(Humble Dialog; .
, Humble Object). (Test Method)
(Test Utility
Method), .
(Minimize Untestable Code),
. , 
. .

. 98

99

:
(Keep Test Logic Out of Production Code)
,
:

(No Test Logic in
.
Production Code)
if testing then... 
, .
. 
, ,
? , 
!
if testing then.
. ( 
) . 
,
. ,  
, 
.

: (Verify One Condition per Test)


, 
:
(Single 
Condition Test)
,
.

,
(Test Method). , 
, .
(Defect Localization).
,

. 

, 
1. ,
. , 
. , 
(
).
(Scripted Test) 
. , , 
.
1


, .

. 99

100

! 
, (Test Method)
(Testcase Class per Fixture, . 639),
(Implicit Setup, . 449).
, (Test Utility Method)
(Delegated Setup, . 437).
(. $
; FourPhase Test, . 387), :
(fixture setup), (exercise SUT),
(result verification) (fixture teardown).

( 
), 
, 
(, , Test Double).


, . 
. 
, (Single Condition Test).

.
, .


. 
(, , , ),
, $
(Test Method).

(Verify One Condition per Test) . 
(assertion) .
(Test Method) 
(Testcase Class per Fixture) 
, AwaitingApprovalFlight.validApproverRequestShouldBeApproved. 
,

. ,
(Custom Assertion, . 495)
(Verification Method; . , Custom Assertion), 
.
. 
.

. 100

101

: / (Test Concerns Separately)



. . 

.
(Test
Method) .
, .
(Manual Debugging; . , Fre
quent Debugging, . 285)  (Defect Localization).
, ,
. 
. 
,
.
 
,
.

. ,
(Testcase Class, . 401), .
.

:
(Ensure Commensurate Effort and Responsibility)

.
,
. , 
,
, . 

(DataDriven Test, . 322).


(
) .
, . 6,
, , 
, .

. 101

. 102



. 5, , ,
. 
,  
. 
, .
xUnit,
7, xUnit, 8,
.


, ,

. , 
.
, 
. , 
. .

, . 
, , 
.
? .
, (
,
), .. , ,
.

. 103

104

,
, 
.

(Test
Automation Framework, . 332). xUnit,
xUnit .
:
(Test Automation Framework)
.


, :

,
;

,
, .

. 6.1 . 
.



.
 (, ) 
(, 
). /
(use cases), (feature), (user
stories) .

( ) 
, .


. 
,

. 104

105

. ,

, .

Au
tomated

Au tomated
xUnit

( )


( )


( )

Au
tomated

xUnit

Manual

Manual


,
?

Tool
/ Base d

. 6.1. .
,
; .
, ;
. ,


, 
, .
, , 
. . 
, , .


, 
. 
 . 
,
, 
.

. 105

106



. . 

. .
,
, .



(
) . 
. 
. :

.

(
),
. 
xUnit,
.

 
.
.


, 
. 
,
.
.


.
, , , 
. 
, 
.

. 106

107


,
. ,
. 
: 
.
(. 6.2).
(Recorded Test, . 312) 
,
.
( ) 
. (Recorded Test) 
. 
, (Fragile Test, . 277).
(Hand
Scripted Test; . , Scripted Test, . 319)
() . $
(Test Automation Framework)
xUnit, , , 
. 
(Scripted Test) Watir
( Ruby, Internet Explorer), Canoo WebTest
( XML, WebTest) Fit (
Wiki FitNesse). 
, (Scripted Test)
(Recorded Test).


unit

component

system


. 6.2. .
.
.

. 107

108


.
. [ARTRP]. 
.


. 6.3 
. 223 ,
;
.

/
t

+

/ ?
/
+
/

+
+

/
xUnit

/
+

/
/
/
+
+

/ ,

/
/
+

/

. 6.3. . ,
. 6.2. (+) ($$)

: xUnit
xUnit. 
xUnit ,
(, , ) 
. ,
JUnit NUnit.

:

xUnit. Http
Unit, JFCUnit, Watir .

(Recorded Test), QTP.
. 
( 

. 108

109

), ,
.

: /
,
. 
. , 
, , 
, , 
.

:
$
(Recorded Test) ,
. 
(
) .

.
1.
(Recorded Test) .

xUnit
xUnit , 
. .

.
xUnit .


. xUnit
.
.


. xUnit (Suite of
Suites; . , Test Suite Object, . 414)
.

,
. $

,
() 
.
(serviceoriented architecture  SOA).

. 109

110

(SelfChecking Test, . 81)


2.
xUnit . ,
, JUnit
3. , xUnit
, 
. ,
( ) 
, xUnit
( , ) 
. .

, 
. ,
. ,
.

xUnit
.
.

xUnit ,
.

, Fit
. xUnit,
, .
Java TestNG, 
(Chained Tests, . 477).
, 
( 
). , 
Fit . , 
(Chained Tests),
, 
Fit, xUnit. xUnit 
, , 
(Obscure Test, . 230)
(High Test Maintenance Cost, . 300).

xUnit
xUnit , 
.
2

: , 
( ).
3 SUnit, 
JUnit Test Infected [TI].

. 110

111

.
$
(Fresh Fixture, . 344)
(Minimal Fixture, . 336) .

, 
.
, .
xUnit 
(HigherLevel Language, . 95), 
. 
. 
(DataDriven Test, . 322),
xUnit Fit.
, 
Fit,
xUnit. ,
,
. 
, ,
. 

(Test Method, . 378), (Test Utility Method,
. 610) .



.
,
(Slow Tests, . 289); 
(High Test Maintenance Cost).

(,  
).


,
(FourPhase Test, . 387). ,
. ,
. xUnit 
(test fixture). 
, , /
(fixture setup).

. 111

112

, (fixture)
.

xUnit (fixture)
(Testcase Class, . 401), .
JUnit .

xUnit (Testcase Class)


(fixture). NUnit.


. , RSpec
, (Test Method) 
NUnit, .

(fixture)
. , Fit
(Interpretator)
(DataDriven Test),
(HigherLevel Language).


(Testcase Class per Fixture, . 639).
,
(Testcase Class per Class, . 627)
(Testcase Class per Feature, . 633),
.
,
(Testcase Class) , (Test
Method) , .


, .
,
(Back Door Setup; . , Back Door Manipu
lation, . 359) 
, . $
(Back Door Setup)
(Mock Object, . 558)
(Test Double, . 538). 13,
, 11, 
.


, .

, .

. 112

113

, .. (Test Method), $
(Test Utility Method), ,
setUp, (Testcase Class).
(Transient Fresh
Fixture; . , Fresh Fixture). 
.
(Fresh
Fixture), ,
(Test Method). $
(Shared Fixture, . 350)
(Persistent Fresh Fixture) , 
.
.

. (Shared
Fixture) , $
(Persistent Fresh Fixture), 
.
. , 
( ), 
(Erratic Test, . 267)
(High Test Maintenance Cost).
. 6.1
.

6.1. /


(Transient Fresh
Fixture)


(Persistent Fresh
Fixture)


(Shared Fixture)

: (Shared Fixture) ,
, 
(Prebuilt Fixture, . 454)

. 6.4 , 
.

. 113

114

. 6.4. .
(Fresh Fixture) , .
(Shared Fixture) .
(Immutable Shared Fixture; . , Shared
Fixture) .
(Shared Fixture)
(Fresh Fixture)


. (Fresh Fixture) 
. (Shared
Fixture)  
. , 
.



(Fresh Fixture) . 
( , Test Method).
, 
(
, ).
(Fresh Fixture), 
.
(Prebuilt Fixture)
.
, .

. 114

115

(Fresh
Fixture) ,
. , ,
(Shared Fixture), 
(Persistent Fresh Fixture).


, ? ,
, 
. ? 
, .

, .
,
(substitutable dependency) .

(legacy software), 
(Fresh Fixture). 
(Persistent Fresh Fix
ture). $
(Transient Fresh Fixture) ,
. 
, 
, (Persistent Fresh Fixture)
(Slow Test).
(Slow Test)
.
1. (Minimal Fixture),
.
2. (Test
Double).
3. ,
, .

(Immutable Shared Fixture).
, , ,
50 ( 2% 
), (Dependency Injection, . 684) $
(Dependency Lookup, . 692)
(Fake Database; . , Fake Object, . 565), ,
.

.

. 115

116

.
(Minimal Fixture)
 
. ,
(Tests as Documentation, . 79). 
(Entity Chain Snipping; .
, Test Stub, . 544) , 
.
.


( ) $
(Fresh Fixture). 
.
(Shared Fixture)
. 
, (Stale Fixture), 
, : $
(Interacting Tests; . , Erratic Test).
,

(Fresh Fixture). (Standard Fixture, . 338)
, 
.
(Shared Fixture) ,
? 
( , 
). , 
, .
, ... , , .
, , $
(Shared Fixture),
, ? (. 6.5).

(,
(Testcase Class), , )?

, ,
 
. , 
. , $
(Prebuilt Fixture) ,
. 
, (Unrepeatable Test),
.
(Database Sandbox, . 658), 

. 116

117

. (Shared
Fixture) (Test Runner, . 405),
(Test Run War; . , Erratic Test),

.

. 6.5. .
.

(Unrepeatable Test) (Test


Run War) .
xUnit ,
(Lazy Setup, . 460), (Suite
Fixture Setup, . 465) (Setup Decorator, . 471).

. 
. 
.
setUp tearDown. (Lazy Setup) 
.
(Chained Tests) $
(Shared Fixture) 

. , 
, ,
. $
(Guard Assertion, . 510),
4.
, (Immutable
Shared Fixture) ,
4

, , 
. ,
.

. 117

118

(Fresh Fixture). ,

(Shared Fixture) 
.




. 
. 
,
. .

, ,
, 
, ! 
, . 

, .

, 

.

////
, ,

. .
,
.
.

,
, ,
;
.
,
. 
, .
(TestDriven Development)

.

. 118

119


5 
(interaction points). 
, (. 6.6).

( )

(
)

( )

/
(
)

B
A

( )


( )
/
(
)

( )

. 6.6. .
.
;
(Back Door
Manipulation). ,
. ,

.

, . 
.
, 
, .

.

. , 
, .
(Back
Door Verification; . , Back Door Manipulation).

,
.

. 119

120

,
. 
. 
. (Back Door Ma
nipulation). ,
( , ). 
, .
6. ,
,
7.



.

, .. (. 6.7). ,
.
.

.
(LayerCrossing Test)
(. 6.8), ,
(Test Double)
, (Test Spy, . 552) (Mock Ob
ject, . 558). 
. , 
(Overspecified Software; .
, Fragile Test), 
.
. 6.8
(Mock Object) . 
(Test Stub), . 
, ,
, (Layer Test, . 368)
(. 6.9). 
(Component Test; . , Layer Test)
.

6
7

. 120

.
.

121

__

_c_
testMethod_1

testMethod_1

testMethod_2

testMethod_2

. 6.7.
. (Fake Object)

__

__

testMethod_1

testMethod_1

testMethod_2

testMethod_2

. 6.8. (Layer$Crossing Test)


.
(Test Stub).
(Mock Object)

. 121

122

6
_1

_n

testMethod_1

testMethod_1

testMethod_2

testMethod_2

. 6.9. (Layer Test) .



.


, 
, .
(Dependency Injection; . 6.10)
(Dependency Lookup),
(Object Factory) (Service Locator). 
, /
(inversion control  IOC), 
. $
(TestSpecific Subclass, . 591) .

,
, .
(Test Hook, . 713)8.
,
(Safety Net, . 79) 
.
, (Test Hook)
(Test Logic in Production, . 257).
8

. 122

if (testing) then ... else ... endif.

123

. 6.10. (Test Double).


(Test Double)
(Dependency Injection).

(asynchronous
test), . 
, 
, wait. ,
, , 
. 
.
, (Humble Executable; . $
, Humble Object, . 700) 
(. 6.11).
, .
 
. (Indirect Testing; . ,
Obscure Test) , 
, . 
(
),
.
, .
, ,
, , , .


(HardtoTest Code, . 251)
,
, .

. 123

124

. 6.11. (Humble Executable),


. ,

,
(Subcutaneous Test; . , Layer Test).
, , 
(Service Facade) [CJ2EPP], 
.
, 
. , 
. 
(Service Facade) (Test Double),
, 9.
10
(Humble Dialog; . , Humble
Object) 
( ) ,
(. 6.12).
(  ) 
.

(Test Double) , 
. ,

, , .
10 , ,
/ ,
.

. 124

Humble Dialog
Abc
def
ghi

OK

Cancel

125

. 6.12. (Humble Dialog)


. ,
, .

(Humble Dialog),


,
. ,
.



. , , 
xUnit 
. 

(Fresh Fixture), (Shared Fix
ture). 8, , 
 (Transient
Fresh Fixture). 9, 
, .
7, xUnit, xUnit, 
.

. 125

. 126

xUnit

6, ,
, 
. . ,
xUnit , . ,
xUnit
. $
(Test Automation Framework, . 332),
xUnit. 
, xUnit.

xUnit
xUnit $
(Test Automation Framework), $
(HandScripted Test; . ,
Scripted Test, . 319) . 

xUnit. ,
. ,
, 
. 
,
(Fully Automated Tests, . 81)1.

. JUnit . 664,
, 
.

. 127

128


, xUnit 
, .
, .
xUnit , 
:

(Test Method, . 378);

$
(Assertion Method, . 390);

, ;

xUnit $
(Test Method Discovery; . , Test Discovery, . 420),
(Test Enumeration, . 425) 
(Test Method) .
(Test Selection, . 429), 
,  .


xUnit (. 7.1) 
.

(Test Method)
(Testcase Class, . 401)?

(Suite of Suites; .
, Test Suite Object, . 414)2?


(Test Method), $
(FourPhase Test, . 387) 
.

(Inline
Setup, . 433), (Delegated Setup, . 437) $
(Implicit Setup, . 449).

xUnit, Suite,
(Test Suite Object) .

. 128

xUnit

129

(Assertion
Method).

(Garbage
Collected Teardown, . 518), (Inline Teardown, . 527),
(Implicit Teardown, . 533) (Automated Tear
down, . 521).

testMethod_1

testMethod_1

Testcase

testMethod_n

testMethod_n

. 7.1. .
.
(Test Method)
(Testcase Class). (Test Suite Factory;
. , Test Enumeration) .
( )


(Simple Success Test; . , Test Method),
,
(Expected Exception Test; . , Test Method),
. 
(Constructor Test; . , Test Method)
. 
, .
(Test Method), , 
, (Testcase Class)3.
(Testcase Class)  /, 
3

xUnit . ,
, $
(Testcase Class per Fixture, . 639).

. 129

130

,  (Test Runner, . 405).


(, )
, .


(test fixture) 
.
, . , 
, . , 
xUnit (Testcase
Class)  , (Test Method)
(Testcase Class) 
. , 
. (Testcase Class) 
. 

xUnit.


(Test Runner)
, (Test Method)
(Testcase Class). .
. 
, .
xUnit
(Testcase Class Discovery), (Test
Runner) 
.
, 
(Test Suite Enumeration; . , Test Enumeration),

. 
(Test Suite Factory), suite 
(Test Suite Object), 
(Test Method) (Test Suite Object).
(Suite of Suites),

, , , . 

,
. , 

[SCMP].

. 130

xUnit

131


(Test Runner).
xUnit .
(Graphical Test Runner; .
, Test Runner) 
, . 

(Test Suite Factory), (Test
Tree Explorer; . , Test Runner),
(Test Method) . 
, 
Run as Test .
(CommandLine Test Runner; .
, Test Runner) 
, . 7.2. $
(Test Suite Factory), ,
. $
(Test Runner) [SCMP]
.
>ruby testrunner.rb c:/examples/tests/SmellHandlerTest.rb
Loaded suite SmellHandlerTest
Started
.....
Finished in 0.016 seconds.
5 tests, 6 assertions, 0 failures, 0 errors
>Exit code: 0
. 7.2.
(Command$Line Test Runner)



. , 
. xUnit (
, ). , 
. . ,
, 
.
,
. , 
. xUnit 
$
(SelfChecking Test, . 81).
, (assertion). 
, (Assertion Method),
. (Assertion

. 131

132

Method) ( ).
(Test Automation Framework) 

. 
.
. $
(Keep Tests Independent, . 96).
, ,
.
, 
. ,
(Test Automation Framework)

, .
xUnit
, . 
(Test Method) (Testcase Class), 
( ).
(Graphical Test
Runner)
, .

, 
.
. , ,
:
. 
, 
. (Guard Asser
tion, . 510) (Test Method),
(Test Method)4.
,
.

, , 
, assertNotNull
, .

. 132

xUnit

133

xUnit
(Test Method) $
(Testcase Class) . 

, xUnit.
xUnit 
(Test Automation Framework). 

. ,  ,
xUnit (Test Method). 
xUnit (Test Method) $
(Testcase Object, . 410), , 
(. 7.3)5. (Testcase Object) 
(Test Suite Object),
.

testMethod_ 1

testMethod_1

testMethod_ n

testMethod_n

. 7.3.
(Test Automation Framework).
(Test Runner) (Testcase Class)
(Test Suite Factory) (Testcase Object)
(Test Method).
(Test Suite Object). (Test Runner)
( Composite [GOF]) .
(Testcase Object) (Test Method)

5 NUnit.
. 411.

. 133

134


(Test Runner) , $
(Test Method) . 
xUnit (Test Method)
 Command [GOF], run.
(Testcase Object), (Test Runner) suite
(Testcase Class) (Test Suite Object).
run (Testcase Object)
(Test Method), ,
. run (Test Suite
Object)
.


(Test Suite Object) Composite
, (Testcase Object). 
( ,
) run. , run
, , . (Testcase Object)
(Test Method).
(Test Suite Object) run
(Testcase Object). Composite Command 
.
, (Test Suite Object) 
. ?
(Testcase Class) (Test Suite Factory).
(Test Suite Factory) (class method),
(Test Suite Object),
(Testcase Object) (Test Method). 
xUnit
(Test Method Discovery) 
(Test Suite Object). 
suite . (Test
Enumeration)
(Lost Test; . , Production Bugs, . 303).

xUnit
(Test Automation Framework)

. xUnit 
 , 
(Testcase Object). 
, (Self

. 134

xUnit

135

Checking Test) ,
(Test Runner) .
(Test Method)
( ) .
(
). (procedure
variable), (function pointer),
(Test Suite Procedure; . , Test Suite
Object), (Test Method), 
, . (Test Method)
(Test Enumeration), 
.
(Test Method) ,
(Test Suite
Procedure), (Test Method) /
. main
.

(DataDriven
Test, . 322).
(DataDriven Test).

.
(
).


xUnit, 
. 
8,
.

. 135

. 136




6, ,
, . 
,
. 7, xUnit,
xUnit , .

.
(Fresh Fixture,
. 344),
, (Tests as
Documentation, . 79). (Persistent Fresh Fixture)
, (Transient Fresh Fixture),
(. 8.1).
(Shared Fixture, . 350) .
(Persistent Fresh Fixture) $
(Shared Fixture) 9.


, .


, $
(FourPhase Test, . 387).
, .
, . xUnit 
(test fixture).

. 137

138

. 8.1. (Transient Fresh Fixture).


(Fresh Fixture) $$$$ (transient)
(persistent). .


, .. 
. 

.
, (Back Door Setup;
. , Back Door Manipulation, . 359), 
,
. (Back Door
Setup)
(Mock Object, . 558) (Test Double, . 538). 
13, ,
11, .
,
. xUnit
Microsoft (Testcase Class, . 401).
xUnit (Testcase Class)
( ), , . 
Fit [FitB]
(DataDriven Test, . 322), 
(HigherLevel Language, . 95).


. 138

139

, , 
. , (Test Method, . 378), 
(Testcase Class).


(Fresh Fixture)
(. 8.2), ..
(Testcase Object, . 410) 
.
. ,
(Interacting Tests; . ,
Erratic Test, . 267).

. 8.2. (Fresh Fixture) .


(Fresh Fixture) ,



1, 
(Garbage
Collected Teardown, . 518). 
. , 
(Fresh Fixture). ,
. 
1

. 139

. . 411.

140

.
, .
(Fresh Fixture)
, .
(Persistent Fresh Fixture) 
9.


(Transient Fresh Fixture) $
(Persistent Fresh Fixture) .

2,
, 
. $
(Fresh Fixture) (Inline Setup, . 434),
(Test Method).

(Delegated Setup, . 437), (Test Utility
Method, . 610). , (Implicit Setup, . 449),
(Test Automation Framework, . 332) 
setUp (Testcase Class). ,
. .


(Inline Setup) 
(Test Method). ,
, 
. (Test
Method). (Inline Setup) 
.
public void testStatus_initial() {
// (In-line Setup)
Airport departureAirport = new Airport("Calgary", "YYC");
Airport destinationAirport = new Airport("Toronto", "YYZ");
Flight flight = new Flight( flightNumber,
departureAirport,
destinationAirport);
//
assertEquals(FlightState.PROPOSED, flight.getStatus());
//
//

}

, ,
.

. 140

141

(Inline Setup)
(Test Code Duplication, . 254), $
(Test Method)
. $
(Test Code Duplication) $
(High Test Maintenance Cost, . 300) (Fragile
Test, . 277). ,
(Obscure Test, . 230). 
(HardCoded Test Data; .
, Obscure Test) (Test Method),

.

(Test Method).
.


(Test Code Duplication) 
(Obscure Test)
(Test Method) (Delega
ted Setup). $
(Test Method) (Test Utility Method) 
(Extract Method) [Ref]. $
(Test Utility Method)
(Test Method). , 
.
, , $
(Creation Method, . 441)3.
,
(Test Code Duplication). ,
, , ,
. (Creation Method) 
.
public void testGetStatus_inital() {
//
Flight flight = createAnonymousFlight();
//
assertEquals(FlightState.PROPOSED, flight.getStatus());
//
//

}

(Creation Method)
.
3

(Test Helper, . 651)


(Object Mother).

. 141

142

(Fragile Test), 
. , 
(Anonymous Creation Method; . $
, Creation Method).
.
(Distinct Generated Value; . , Generated Value, . 726)
, 
. $
(Erratic Test), (Unrepeatable Test), $
(Interacting Tests) (Test Run War),
, $
(Shared Fixture).
, $
(Parameterized Anonymous Creation Method; . $
, Creation Method). 
, .
.
$ , , $
!
(Delegated Setup)
( ,
). 
, . 
(Inline Setup) . 
(Test Code
Duplication) (One Bad
Attribute; . , Derived Value, . 722); $
(Creation Method) , 
, .
$
(Named State Reaching Method; . , Creation Method).

(Reuse tests for fixture setup; . , Creation Method)
(Chained Tests, . 477).

. ,
, . ,
, .
(Tests as Documentation)
(Creation Method), 
. , 
.
(Creation Method)
(Testcase Class), (Testcase Superclass, . 646) 
(Test Helper, . 651).

. 142

143

(Object Mother; . $
, Test Helper). 
(Creation Method) 
(Test Helper). , $
(Automated Teardown, . 522).


xUnit , 
(Test Method).
(, setUp). 
(, @before JUnit)
(, [Setup] NUnit).
, setUp
, $
(Test Automation Framework). setUp 
,
(Testcase Class).
(Implicit Setup)
setUp. 
(Test Method) (Testcase Class)
,
(Test Method) .
(Test Code Duplication), 
. , ?
Airport departureAirport;
Airport destinationAirport;
Flight flight;
public void testGetStatus_inital() {
// (Implicit Setup)
//
assertEquals(FlightState.PROPOSED, flight.getStatus());
}

,
( )
(Test Method).
setUp.
public void setUp() throws Exception{
super.setUp();
departureAirport = new Airport("Calgary", "YYC");
destinationAirport = new Airport("Toronto", "YYZ");
BigDecimal flightNumber = new BigDecimal("999");
flight = new Flight(flightNumber, departureAirport,
destinationAirport);
}

. 143

144

(Testcase Class) 
setUp . ,
, (Test Method) 
,  $
(Testcase Class per Fixture, . 639). ,
xUnit (, VbUnit NUnit)
, (Testcase Class).
, ,
(Testcase Class per Fixture).
(Implicit Setup) 

. , 
setUp 
, .

. , 
,
(Testcase Class). xUnit
, (Test Method),
, , NUnit .
. 411. 
,
setUp .

setUp
, !
, setUp .
setUp , .
. 
 , 

. , , 
, .
setUp xUnit.

setUp (General Fixture; .
, Obscure Test), , 
(Test Method).
(Persistent Fresh Fixture), (Slow
Tests, . 289). ,  
, 
(Obscure Test).
(Test Method)
(Testcase Class) 
, setUp,

. 144

145

. , setUp 
, .

(Test Method), , setUp 
(General Fixture)
(Minimal Fixture, . 336).
(General Fixture) (Slow Test),

. , (Obscure Test),
(Test Method) 
.
(General Fixture) (Fragile Fixture; .
, Fragile Test), 
.
.
, ,
, . $
(Lazy Setup, . 460)
, 
, , , , 
.



. 
. (Creation Method) 
(Test Method),
. setUp ,
(Creation Method) 
. , (Creation Method) 
 
setUp. 
, (Testcase Class), , ,
(Test Helper).


(Transient
Fresh Fixture) . xUnit 
, (garbage collection). 
,
(GarbageCollected Teardown)
.
. 411 , NUnit.

. 145

146

xUnit , $
(Fresh Fixture) .


$
(Fresh Fixture).
, .
(Fresh Fixture) , 
. 9, 
, 
, (Persistent Fresh Fix
ture) (Shared Fixture).

. 146




8, , 
(Fresh Fixture, . 344).
, , 
. 
, 
, (Persistent Fresh Fixture;
. , Fresh Fixture) (Shared
Fixture, . 350).


(Persistent Fresh Fixture)
, . 
(Fresh Fixture) ,
(Test Method, . 378)
. : 
! ,  
(. 9.1).
(Persistent Fresh Fixture) ,
(Transient Fresh Fixture). 
, (Unre
peatable Test; . , Erratic Test, . 267), 
,
(Slow Tests, . 289), $
(Shared Fixture, . 350).

. 147

148

. 9.1. (Fresh Fixture)


. (Fresh Fixture)
,


( )
.
( , ). ,

. 
(Testcase Class, . 401).
(Transient Fresh Fixture)
,
(Test Method).
xUnit
.
( ) .

( ,
).


,
(Test Method) ,
. 

. 148

149

.
,
.
(Unrepeatable Test) ,
.
(Distinct Generated Value; . , Generated Value, . 726)
, .


, 
, 
. ,
. ,
.
, , (Garbage
Collected Teardown, . 518). , 
.

,

(Test Method). ,
. .
public void testGetFlightsByOriginAirport_NoFlights()
throws Exception {
//
BigDecimal outboundAirport = createTestAirport("1OF");
//
List flightsAtDestination1 =
facade.getFlightsByOriginAirport(outboundAirport);
//
assertEquals(0,flightsAtDestination1.size());
facade.removeAirport(outboundAirport);
}

(Naive Inline Teardown; . , In


line Teardown, . 527) 
, .
, (Assertion Method, . 390) 
. , .
(Inline
Teardown) (Test
Method) try/catch.
.
public void testGetFlightsByOriginAirport_NoFlights_td()
throws Exception {
//
BigDecimal outboundAirport = createTestAirport("1OF");

. 149

150

try {
//
List flightsAtDestination1 =
facade.getFlightsByOriginAirport(outboundAirport);
//
assertEquals(0,flightsAtDestination1.size());
} finally {
facade.removeAirport(outboundAirport);
}
}

,
(Test Method). , 
: ,
.
(Extract Method) [Ref],
(Test Utility Method, . 610),
. (Delegated Teardown; .
, Inline Teardown) , 
.
xUnit
(Implicit Teardown, . 533). (Test Automation
Framework, . 332) tearDown 
(Test Method) .

(Test Method), . ,
tearDown, , 
( ), 
. , tearDown
(Test Method)
. (
(Testcase Class per Fixture, . 639),
.
(Testcase Class),
(Teardown Guard Clause; . , Inline Teardown) tearDown, .)

(Inline Setup, . 433);

(Delegated Setup, . 437);

(Implicit Setup, . 449).

. 150

(Inline Teardown);

(Delegated Teardown);

(Implicit Teardown).

151

.
,
.
(. 9.1). , (Implicit Tear
down) (Inline Setup) $
(Delegated Setup). , (In
line Teardown) (Inline
Setup), .

9.1.


(Inline Teardown)
(Delegated Teardown)


(Implicit
Teardown)


(Inline Setup)


(Delegated Setup)


(Implicit Setup)


: 
. 
, (Erratic Test),
(Resource Leakage),
, .
$
(Transient Fresh Fixture) . 
,
(Testcase Object, . 410), 
.
, .
.
, , 
. ,
, (
, ). 
(Automated Teardown, . 521) 
(Test Method)
(Testcase Class). .
1.
.

. 151

152

2. ,
. Command
[GOF], ,
delete
switch, .
3. (
) .
(Automated Teardown)
(Creation Method, . 441)
tearDown.
(Testcase Superclass, . 646), (Testcase Class).
,
.
(Object Factory; . , Dependency Lookup, . 692) 
(Testcase Superclass) 
(Observer) [GOF] .


(Fresh Fixture)
, 
. (Table Truncation Teardown,
. 668) ,
. , ,
(Test Runner, . 405) (Database Sandbox,
. 658). $
(Transaction Rollback Teardown, . 675), ,
.
(Humble Transaction Controller; .
, Humble Object, . 700), 
. 
(Implicit Teardown),
(Test Method).


. ,
.


.
1. .
2.
.

. 152

153

3.
(Fresh Fixture) .
: 
. ,
,
.
, $ (Delta Assertion,
. 505) . $ (Delta Assertion) 

.

. , 
, .. , ..
,

.
(Test Runner),
.
(Distinct Generated Value) 
: (Database Parti
tioning Scheme; . , Database Sandbox),
.


, ,
(Fresh Fixture).
? : ! :
(Fresh Fixture) . 
, (Test
Double, 538), . 
(Fake Database; . , Fake Ob
ject, . 565). , :
.



(Persistent Fresh Fixture) , , .
.
,
. ,
, 
. (Fresh Fixture)
,
. 

. 153

154

50 100 ( !) , , 
.
,
(Persistent Fresh Fixture),

. , 

, , 
(Shared Fixture) 
( 
). ,
: .
, (Interacting Tests; . $
, Erratic Test), (Lonely Test; . , Erratic
Test) (Unrepeatable Test).
(Slow Test)!

. $
(InMemory Database; . , Fake Object)
(Fake Database). ,
. , , 
, .
, $
(Slow Test).
. 351 .



(Persistent Fresh Fixture), 

(. 9.2). , 
. ,
. ,
.


(Shared Fixture)
. 
. 
( 
), , 
.
(HardCoded Value; . , Literal Value, . 718)
. 

. 154

155

, 
, (. ,
Obscure Test, . 230). , 
(Finder Method; . 
, Test Utility Method, . 610) .
(Finder Method) (Creation
Method), 
, .

. 9.2. (Shared Fixture)


(Test Method). (Shared Fixture)
,
.

, 
. 
(Testcase Class), 
. ,
.
(Finder Method).

(Testcase Class), . , 
,
. , 
. 
,  (Test Fixture
Registry; . , Test Helper, . 651).
.
(Finder
Method). (Test Fixture Registry) 
(Finder Method), , , ,
(Test Helper).

. 155

156



(Test Method). 
,
(. 9.3). 
(Shared Fixture).

. 9.3. (Shared Fixture).


(Shared Fixture) ;
,
,


, (Lazy Setup, . 460) setUp 
(Testcase Class), 
. 
.
( (Suite of Suites); . ,
Test Suite Object, . 414), , 
. (Unrepeatable Test),

( ).
,
(Fixture Setup Testcase).
(Chained Tests), 
, (Lazy Setup): , 
. 
(Test Enumeration, . 425).

, ,
. xUnit setUp,
(Testcase
Class). (Suite Fixture Setup,
. 465) tearDown,

. 156

157

(Test Method) ( 
, Testcase Class). 
, 
. ,
(Unrepeatable Test); $
(Interacting Tests).
xUnit.

(Testcase Class), (Setup Decora
tor, . 471), setUp
tearDown. (Setup Decorator) 
.
(Lonely Test).

, .. (Prebuilt Fixture,
. 454).
, xUnit.
, ,
, 
.
(Prebuilt Fixture) (Manual Intervention, . 287),
(Unrepeatable Test). $
(Prebuilt Fixture) 
(Fresh Fixture)
(Immutable Shared Fixture).


,

(Assertion Method). 
10, .

. 157

. 158

10

10



8, , 9,
, 
.

, 
.


xUnit 
(SelfChecking Test; . $
, . 77).
, .
xUnit (Assertion Method,
. 390) . ,
, $
(Assertion Method). 
(Test Code Duplication, . 254).

, . 
;
,
(Assertion Method). ,
, . 
, .
( ) (Test Method,
. 378) . 
, 
.
(Obscure Test, . 229), 

. 159

160

10

(Test Utility Method, . 611)1.


.
11,
. (Assertion Method) $
(Test Utility Method) .
( )
(Assertion Method) tearDown,
(Implicit Teardown, . 534). 
( setUp ), 
. ,
(Implicit Setup, . 450) .
, . 
tearDown (Implicit Teardown) 

 . 507.

: ?
, 
. .
.
, 
.
.
1. , ,

.
2.
, .
( )
.
(State Verification, . 485) 
. (Behavior Verification, . 490)
, .

1 (Shared Fix
ture, . 350); (Guard
Assertion, . 510) 
. $
(Finder Method; . , Test Utility Method), 
(Shared Fixture, . 350).

. 160

161


$
(State Verification, . 484). ,
. ,
, 
. , :

. , 

.

(
)

B
A

. 10.1. (State Verification). ,



.

(State Verification) 
. (Procedural State Verification; .
, State Verification) 
,
. (Expected Object; . , State
Verification) , 
(Assertion Method). 
(Test Code Duplication)
( ). 
, (Custom Assertion, . 495).

. 161

162

10



, ! 
.

. xUnit $
(Assertion Method), .

(Stated Outcome Assertion; . $


, Assertion Method), assertTrue(aBooleanExpression).

(Equality Assertion), assertEquals


(expected, actual).

(Fuzzy Equality Assertion), assertEquals(expected, actual, tolerance),


.

, , , 
. JUnit, SUnit, CppUnit, NUnit CsUnit $
(Equality Assertion) Object.

. 
, C, ,
.
,
(Assertion Method). , 
. ,
(Safety Net, . 79) .
. , 
S1 X, 
R S2. S1 
. X 
. R S2
. , 
R S2.
, ,
. , 
2. , 
(Assertion Message, . 398)
message ( 
xUnit).
(Assertion Roulette, . 264), 
.
2

[TDDAPG] , Eclipse Debugger,


, .
!

. 162

163

. , 
, , ,
, .
(Stated Outcome Asser
tion), assertTrue JUnit, 
(, Assertion failed).
, (ArgumentDescribing
Message; . , Assertion Message),
. 
(Assertion Message) .

/
(Shared Fixture, . 350) 
(Interacting Tests; . , Erratic
Test, . 267), /
, 
. , $$
(Delta Assertion, . 505) .

/. /, 
(Expected Object). 
,
(Custom Assertion) /
(Verification Method; . , Custom Assertion).
(Test
Method) setUp,
(Test Method), (Implicit
Setup), (Shared Fixture)
(Prebuilt Fixture, . 454).


. 
, ,
.
(Custom Assertion), 
.
, (
), $
(Fuzzy Equality Assertion).

,
.
(Mystery Guest; . , Obscure Test), ,
. ,
, 

. 163

164

10

. ,
( , Minimal
Fixture, . 336).


, ,  .
, 
(. 10.2).
: (Procedural Behavior Verifi
cation) (Expected Behavior). 
( ). 
(Test Double, . 538) 
11, .

(
)
)

. 10.2. (Behavior Verification).


( )
. ,



. 
( ) 
. ,
( ) .

. 164

165

public void testRemoveFlightLogging_recordingTestStub()


throws Exception {
//
FlightDto expectedFlightDto = createAnUnregFlight();
FlightManagementFacade facade =
new FlightManagementFacadeImpl();
//
(Test Double)
AuditLogSpy logSpy = new AuditLogSpy();
facade.setAuditLog(logSpy);
//
facade.removeFlight(expectedFlightDto.getFlightNumber());
//
assertEquals("number of calls", 1,
logSpy.getNumberOfCalls());
assertEquals("action code",
Helper.REMOVE_FLIGHT_ACTION_CODE,
logSpy.getActionCode());
assertEquals("date", helper.getTodaysDateWithoutTime(),
logSpy.getDate());
assertEquals("user", Helper.TEST_USER_NAME,
logSpy.getUser());
assertEquals("detail",
expectedFlightDto.getFlightNumber(),
logSpy.getDetail());
}


. 
(Test Spy, . 552)
(Self Shunt; . , HardCoded Test
Double, . 581)3 . 
.


(Expected Object)
, , ,
 ? , . $
(Expected Behavior)
(LayerCrossing Test) .
(Mock Object, . 558),
.
public void testRemoveFlight_JMock() throws Exception {
//
FlightDto expectedFlightDto = createAnonRegFlight();
FlightManagementFacade facade =
new FlightManagementFacadeImpl();
//
Mock mockLog = mock(AuditLog.class);
mockLog.expects(once()).method("logMessage")
.with(eq(helper.getTodaysDateWithoutTime()),
3

. 165

(Test Spy), (Testcase Class, . 401).

166

10

eq(Helper.TEST_USER_NAME),
eq(Helper.REMOVE_FLIGHT_ACTION_CODE),
eq(expectedFlightDto.getFlightNumber()));
//
facade.setAuditLog((AuditLog) mockLog.proxy());
//
facade.removeFlight(expectedFlightDto.getFlightNumber());
//
// JMock verify()
}



(Test Code Duplication). 
,
. , , 
. (Test Code Duplication) ,
, (Fragile Test, . 277),
(Fragile Fixture, . 284) $
(High Test Maintenance Cost, . 300),  
, (Standard Fixture,
. 338) . ,
(Test Code Duplication) 
 (, $
, Obscure Test).
(Test Code Duplication)
. ,
:

(Expected Object);

(Custom Assertion);

(Verification Method).



. (
),
(Test Code Duplication). (Test Method),
. ,
.
public void testInvoice_addLineItem7() {
LineItem expItem = new LineItem(inv, product, QUANTITY);
//
inv.addItemQuantity(product, QUANTITY);
//
List lineItems = inv.getLineItems();

. 166

167

LineItem actual = (LineItem)lineItems.get(0);


assertEquals(expItem.getInv(), actual.getInv());
assertEquals(expItem.getProd(), actual.getProd());
assertEquals(expItem.getQuantity(), actual.getQuantity());
}


(Equality Assertion) 
.
, ,
.
(Expected Object)
equals, .
public void testInvoice_addLineItem8() {
LineItem expItem = new LineItem(inv, product, QUANTITY);
//
inv.addItemQuantity(product, QUANTITY);
//
List lineItems = inv.getLineItems();
LineItem actual = (LineItem)lineItems.get(0);
assertEquals("Item", expItem, actual);
}

equals
, ?
(testspecific equality)?
(Expected Object)  ? $
(Custom Assertion), 
, equals $
(Expected Object), (Assertion
Method). . ,
equals, 
. , (data
transfer object) [CJ2EEP] (TestSpecific Subclass, . 591)
equals.
equals,
, 
, ( 
). 
. equals
, . 
, (Custom Assertion)
(Expected Object). , :
, equals ? ,
,
( Java), (Custom
Assertion),
. 
equals .

. 167

168

10


(Custom Assertion) 
. 
,
. ,
(Obscure Test), . 
(Custom Assertion) 
. 
(Untestable Test Code; .
, HardtoTest Code, . 251)!
static void assertLineItemsEqual(
String msg, LineItem exp, LineItem act) {
assertEquals (msg+" Inv", exp.getInv(), act.getInv());
assertEquals (msg+" Prod", exp.getProd(), act.getProd());
assertEquals (msg+" Quan", exp.getQuantity(), act.getQuantity());
}

(Custom Assertion).
1.
(Test Code Duplication).
2. (Assertion
Method) .

(Custom Assertion).

, .
(Custom Assertion)
(HigherLevel Language, . 95) .
(Extract
Method) [Ref] . 
. ,
(Assertion Message), 

(Assertion Method).



(Verification Method). , 
, ,
. 
(Extract Method) ,
, 
!

. 168

169

void assertInvoiceContainsOnlyThisLineItem(
Invoice inv,
LineItem expItem) {
List lineItems = inv.getLineItems();
assertEquals("number of items", lineItems.size(), 1);
LineItem actual = (LineItem)lineItems.get(0);
assertLineItemsEqual("",expItem, actual);
}

(Verification Method) 
(Custom Assertion)
( ).
(Equality Assertion)
(Custom Assertion): assertSomething(message, expected, actual). 
, (Verification Method) 
, . 
  (Custom
Assertion) (Parameterized Test, . 618).


. 
, ,
,
(Parameterized Test). $
(Test Automation Framework, . 332) 
, .
(Test Method), , , $
(Parameterized Test) , 
. , 
.
generateAndVerifyHtml (Parameterized Test).
def test_extref
sourceXml = "<extref id='abc' />"
expectedHtml = "<a href='abc.html'>abc</a>"
generateAndVerifyHtml(sourceXml,expectedHtml,"<extref>")
end
def test_testterm_normal
sourceXml = "<testterm id='abc'/>"
expectedHtml = "<a href='abc.html'>abc</a>"
generateAndVerifyHtml(sourceXml,expectedHtml,"<testterm>")
end
def test_testterm_plural
sourceXml = "<testterms id='abc'/>"
expectedHtml = "<a href='abc.html'>abcs</a>"
generateAndVerifyHtml(sourceXml,expectedHtml,"<plural>")
end

(DataDriven Test, . 322)


.
. (DataDriven Test) 

. 169

170

10

(Parameterized Test).
(Test Method) (Parameterized Test).
(DataDriven Test) (Test Method)
.
(HigherLevel Language) .
(DataDriven Test) . 
Fit, xUnit. $
(DataDriven Test) Ruby.
def test_crossref
executeDataDrivenTest "CrossrefHandlerTest.txt"
end
def executeDataDrivenTest filename
dataFile = File.open(filename)
dataFile.each_line do | line |
desc, action, part2 = line.split(",")
sourceXml, expectedHtml, leftOver = part2.split(",")
if "crossref"==action.strip
generateAndVerifyHtml sourceXml, expectedHtml, desc
else # new "verbs" go before here as elsif's
report_error("unknown action" + action.strip)
end
end
end

, 
(DataDriven Test).
ID,
Action,
SourceXml,
ExpectedHtml
Extref,crossref,<extref id='abc'/>,<a href='abc.html'>abc</a>
TTerm,crossref,<testterm id='abc'/>,<a href='abc.html'>abc</a>
TTerms,crossref,<testterms id='abc'/>,<a href='abc.html'>abcs</a>


, , . $
(Conditional Test Logic, . 243) 
. , 
. ?
(Test Method)
. (Test Method)
,
. . 
, :

. 170

, 
, ( 
);

171

(Test Method)
( $
, Test Method).

(Conditional Test Logic) 



(Flexible Test; . ,
Conditional Test Logic). , 
. 
, $
(Test Method). (.
). .
!
,
(Conditional Test Logic) .

if
, , 
, ?
if, 
. ,
(Conditional Test Logic), , 
.
List lineItems = invoice.getLineItems();
if (lineItems.size() == 1) {
LineItem expected =
new LineItem(invoice, product,5,
new BigDecimal("30"),
new BigDecimal("69.96"));
LineItem actItem = (LineItem) lineItems.get(0);
assertEquals("invoice", expected, actItem);
} else {
fail(" ");
}

$
(Guard Assertion, . 510), .
List lineItems = invoice.getLineItems();
assertEquals("number of items", lineItems.size(), 1);
LineItem expected =
new LineItem(invoice, product, 5,
new BigDecimal("30"),
new BigDecimal("69.96"));
LineItem actItem = (LineItem) lineItems.get(0);
assertEquals("invoice", expected, actItem);

(Guard Assertion)
, ,
(Conditional Test Logic).

. 171

172

10

. 

!


(Conditional Test Logic) , 
, . 
(Test Method) .

(Untestable Test Code),


.

(Obscure Test), 
.


(Developers Not Writing Tests, . 298),
(Self
Checking Test).


(Test Utility Method) . 
.



.


.
: , . 
.
. 
( ). 
( ).
, 
. 
. , 
.
, . 

. , 
invoice1 invoice2.

. 172

173

( , )
. (Test Method)

. 
. 
(Test Utility Method), 
(Test Method) 
. , 
. ,
. ,

. ( 
fail, 
.) , 
.
(Test Utility Method).



(Test Method)
(Test Utility Method).
,
(Test Utility Test; . , Test Utility Method).
, 
.
(,
, ),
, (Test Method)
(, , , 
). 
(Test Utility Method),
. , 
, (Guard As
sertion) (Custom Assertion),
.


, (Extract
Method) (Custom Assertion)
(Verification Method) .
? 
(Testcase Class, . 401). 
, (PullUp
Method) [Ref] (Testcase Superclass, . 646).

. 173

174

10

, (Move Method) [Ref] 


(Test Helper, . 651). 
12, .



xUnit. 11, 
, , 
(Test Double).

. 174

11

11



(Test Automation Framework, . 332)
xUnit. ,

. ,
.
, :
, , 
. 
, .



.
, ,
. 
, ,
(, ). 

. ?

. 
( ), 
.
, 
(Test Double, . 538). $
(Test Double) .
.

. 175

176

11


, 
. 

. , 
(Untested Code; . , Production Bugs, . 303).
,

.
,
. ? ,
. 
,
. 
(indirect input test condi
tion) (. 11.1). (control point).

. 11.1.
. .

,


.
,  
. ,
.

. 176

177

,
. ,
. 
.
.
, . 

, .
.
, , ,
. , 
, (indirect output test condition)
(. 11.2). , $
(Untested Requirement; . , Production Bugs).
(observation point).

. 11.2. .
.

,
, 
. .

. (Untested Requirement).

. 177

178

11


, 
,
. .

,
. .
:

/;


. , 
, (Back Door Setup; . $
, Back Door Manipulation, . 359) 
,
(, , , 
).
(. 11.3).

Setup

Ex
ercise

SUT

Data
Data
Fixture

Ve r ify

Te
ardo wn

. 11.3. (Back Door Manipulation)


.
,
" "

.

.

. 178


. 
.

179

,
.

,
.

, 
, .
, 
. (Test
Stub, . 544) 
. (Test Stub) 
(. 11.4). 
.

. 11.4. (Test Stub)


.
(Test Stub) .
(Test Stub)
.



. 

(. 11.5). , 
, (
).

. 179

180

11

(
)
)

. 11.5. (Behavior Verification)


.
, ,
(Behavior Verification),


, .

, 
. ,
.

,
,
.


.

(Back Door Verification; .


, Back Door Manipulation, . 359). 
,
.

. 180


.

181

, , 
. 
, 
. ,
.

( ) .

,
.

, 
.

,
.
. $
(Procedural Behavior Verification; . , Behavior Verifi
cation) ( ) 
,
. (substitutable
dependency) (Test Spy, . 552).
.
(Test Method, . 378) (Test Spy) 
(Assertion Method, . 390) 
(. 11.6).
(Expected Behavior; . , Behavior Verification)

.
(Mock Object, . 558) 
. (. 11.7).
(Mock Object) 
( 
). (Mock Object)
, . 

, (Assertion Method) $
(Mock Object), , , .
, , (Test Method)
.
(Test Spy) (Mock Object)
.

. 181

182

11

. 11.6. (Test Spy)


.
(Behavior Verification) (Test Spy)
.
(Test Spy)

. 11.7. (Mock Object)


.
(Behavior Verification) (Mock Object)
.
, (Mock Object)

. 182

183


: 
, 
?
,
,
(, ).

. (Test Double) 
.


(Test Double)  , 
. 
(Test Double)
(. 11.8).

$ (Dummy Object, . 730)


( ), 
.

(Test Stub) ,
, . 

, . (Test
Spy), (Test Stub), 
,
.

(Mock Object) , 
. .

(Fake Object, . 565)


.

/
$ (Dummy Object)
(Test Double). 
, .. $ (Dummy Object) .
null ( nil, nothing).
, 
.
. 
$ (Dummy Object) 
, .

. 183

184

11

. 11.8. (Test Double). $


(Dummy Object) .
(Test Stub) . (Test Spy)
(Mock Object) .
(Fake Object) ,

DummyCustomer Invoice
. DummyCustomer
.
public void testInvoice_addLineItem_DO() {
final int QUANTITY = 1;
Product product = new Product("Dummy Product Name",
getUniqueNumber());
Invoice inv = new Invoice( new DummyCustomer() );
LineItem expItem = new LineItem(inv, product, QUANTITY);
//
inv.addItemQuantity(product, QUANTITY);
//
List lineItems = inv.getLineItems();
assertEquals("number of items", lineItems.size(), 1);
LineItem actual = (LineItem)lineItems.get(0);
assertLineItemsEqual("", expItem, actual);
}

, $ (Dummy Object) Null Object [PLoPD3] 


. $ (Dummy Object) 
, , . , Null Object 
, , 
. , !
$ (Dummy Object) (Test
Double), ,
(Literal Value, . 718), (Generated Value, . 726) $

. 184

185

(Derived Value, . 722). ,


. 
$ (Dummy Object),
.


(Test Stub) ,
.
. (Test Stub) 
, . $
(Responder; . , Test Stub) 
, 
.
(Saboteur; . , Test Stub)

.
, $
(Procedural Test Stub; . , Test Stub).
Java $
(Saboteur) getTime
. .
public void testDisplayCurrentTime_exception()
throws Exception {
//
//

TimeProvider testStub = new TimeProvider()
{ //
public Calendar getTime() throws TimeProviderEx {
throw new TimeProviderEx("Sample");
}
};
//

TimeDisplay sut = new TimeDisplay();
sut.setTimeProvider(testStub);
//
String result = sut.getCurrentTimeAsHtmlFragment();
//
String expectedTimeString =
"<span class=\"error\">Invalid Time</span>";
assertEquals("Exception", expectedTimeString, result);
}

(Procedural
Test Stub) :

. 185

,
.

186

11

(Procedural Test Stub)


, .
 
. (Test Logic in
Production, . 257),
(Test Hook, . 713) if testing then... else 
. .
public Calendar getTime() throws TimeProviderEx {
Calendar theTime = new GregorianCalendar();
if (TESTING) {
theTime.set(Calendar.HOUR_OF_DAY, 0);
theTime.set(Calendar.MINUTE, 0);}
else {
//
}
return theTime;
};


(procedural variables)1. 
, .


(Test Spy) , 
. 
(Test Stub)
, .
(Procedural Behavior Verification),
.
, 
logMessage , (Retrieval
Interface; . , Test Spy).
public void testRemoveFlightLogging_recordingTestStub()
throws Exception {
//
FlightDto expectedFlightDto = createAnUnregFlight();
FlightManagementFacade facade =
new FlightManagementFacadeImpl();
//

AuditLogSpy logSpy = new AuditLogSpy();
facade.setAuditLog(logSpy);
//
facade.removeFlight(expectedFlightDto.getFlightNumber());
//
assertFalse(" ",
facade.flightExists(expectedFlightDto.
getFlightNumber()));
//
1

. 186

(function pointers).

187

//
assertEquals("number of calls", 1,
logSpy.getNumberOfCalls());
assertEquals("action code",
Helper.REMOVE_FLIGHT_ACTION_CODE,
logSpy.getActionCode());
assertEquals("date", helper.getTodaysDateWithoutTime(),
logSpy.getDate());
assertEquals("user", Helper.TEST_USER_NAME,
logSpy.getUser());
assertEquals("detail",
expectedFlightDto.getFlightNumber(),
logSpy.getDetail());
}


(Mock Object) 
. (Test Stub),
. ,
(Mock Object) .

(Test
Method).
, $
(Mock Object). .

(Mock Object) , 
, 
.

(Mock Object) 
. 
. , 
.

(Mock Object)
logMessage. ( removeFlight) logMessage, (Mock Object) 
. 
, .
public void testRemoveFlight_Mock() throws Exception {
//
FlightDto expectedFlightDto = createAnonRegFlight();
//
ConfigurableMockAuditLog mockLog =
new ConfigurableMockAuditLog();
mockLog.setExpectedLogMessage(
helper.getTodaysDateWithoutTime(),
Helper.TEST_USER_NAME,
Helper.REMOVE_FLIGHT_ACTION_CODE,
expectedFlightDto.getFlightNumber());
mockLog.setExpectedNumberCalls(1);

. 187

188

11

//
FlightManagementFacade facade =
new FlightManagementFacadeImpl();
facade.setAuditLog(mockLog);
//
facade.removeFlight(expectedFlightDto.getFlightNumber());
//
assertFalse(" ",
facade.flightExists(expectedFlightDto.
getFlightNumber()));
mockLog.verify();
}

(Test Stub), (Mock Object)


,
, .


(Fake Object) (Test Stub) $
(Mock Object),
. (Fake Object) 
,
. (Fake Object)

, . 
(Fake Object) 
, .
. 351 

, 
. 
. (Fake Database; .
, Fake Object), , .
public class InMemoryDatabase implements FlightDao{
private List airports = new Vector();
public Airport createAirport(String airportCode,
String name, String nearbyCity)
throws DataException, InvalidArgumentException {
assertParamtersAreValid(airportCode, name, nearbyCity);
assertAirportDoesntExist(airportCode);
Airport result = new Airport(getNextAirportId(),
airportCode, name, createCity(nearbyCity));
airports.add(result);
return result;
}
public Airport getAirportByPrimaryKey(BigDecimal airportId)
throws DataException, InvalidArgumentException {
assertAirportNotNull(airportId);
Airport result = null;
Iterator i = airports.iterator();
while (i.hasNext()) {
Airport airport = (Airport) i.next();

. 188

189

if (airport.getId().equals(airportId)) {
return airport;
}
}
throw new DataException("Airport not found:"+airportId);
}


: $
(HandBuilt Test Double; . , Configur
able Test Double, . 571) (Dynamically Gen
erated Test Double), 
2.
(Test Double) $
(Configurable Test Double).
. , (HandBuilt
Test Double) (Hard
Coded Test Double, . 581), 
.
(Inner Test Double), Java.
public void testDisplayCurrentTime_AtMidnight_PS()
throws Exception {
//
//
TimeProvider testStub = new PseudoTimeProvider()
{ //
public Calendar getTime(String timeZone) {
Calendar myTime = new GregorianCalendar();
myTime.set(Calendar.MINUTE, 0);
myTime.set(Calendar.HOUR_OF_DAY, 0);
return myTime;
}
};
//

TimeDisplay sut = new TimeDisplay();
//
sut.setTimeProvider(testStub);
//
String result = sut.getCurrentTimeAsHtmlFragment();
//
String expectedTimeString =
"<span class=\"tinyBoldText\">Midnight</span>";
assertEquals("Midnight", expectedTimeString, result);
}

JMock
. , EasyMock, 
(Statically Generated Test Double).
, ,
.

. 189

190

11

(HandBuilt Test Double) 


(Java C#) , 
, (PseudoObject; .
, HardCoded Test Double) 
. (PseudoObject)
(Test Stub), (Test Spy)
(Mock Object) , . 
(Inner Test Double)
(Self Shunt; . , HardCoded Test
Double). (PseudoObject)
.
/**
*
*
*
*/
public class PseudoTimeProvider implements ComplexTimeProvider {
public Calendar getTime() throws TimeProviderEx {
throw new PseudoClassException();
}
public Calendar getTimeDifference(Calendar baseTime,
Calendar otherTime)
throws TimeProviderEx {
throw new PseudoClassException();
}
public Calendar getTime(String timeZone)
throws TimeProviderEx {
throw new PseudoClassException();
}
}


(Test Double) ( , Test Stub,
, Mock Object) 
. (HardCoded Test Double) 
.
(Configurable Test Double) 
(. 11.9). (Test Stub) (Test Spy) 
, , 
. , (Mock Ob
ject) ,
. , 
(Test Double). , 

(Test Double).
(Fake Object) ,
.
. $

. 190

191

(Dummy Object) , 3. $
(Procedural Test Stub)
(HardCoded Test Double), .. 
; ,
(Test Double).
,

. 11.9. (Test Double) .


(Configurable Test Double),

(Hard$Coded Test Double)

(Configurable Test Double) $


(Configuration Interface; . ,
Configurable Test Double) (Configuration Mode), 
.
(Configurable Test Double) 
. , 
, (Test Double)
. (Mystery
Guest; . , Obscure Test, . 230).
? $
(Test Double) , 
. , (Inline
Setup, . 434), (Implicit Setup, . 449)
(Delegated Setup, . 437).

$ (Dummy Object) ,
, . $ (Dummy
Object) , .

. 191

192

11


$
(Test Double), . 
(Test Double).

(Test Double), (Configurable
Test Double) .
(Test Double).
, , 
.
, .

(Dependency Injection, . 684), , 
, (Dependency Lookup, . 692),

, (Test Hook), 
.

(inversion of control), 
. $
(Dependency Injection) (Dependency Lookup).


(Dependency Injection)
, 
(. 11.10). $
(Dependency Injection) , 
. 
,
,
.
(Dependency Injection).

. 192

(Setter Injection; . , Dependency


Injection).
( ). 
,
(Test Double). 
( 
).

(Constructor Injection; . , Depend


ency Injection).
. (Test Double)
, 
, . , 
. 

193

,
.

. 11.10. (Test Double) .


.
(Dependency Injection)

(Parameter Injection; . , Dependency Injec


tion). 
. (Test Double), 
4. ,
.
(Mock Object) ,

,
.


$
(Dependency Injection) , (Dependency Look
up) .
,

(. 11.11). 
. 
 ,
(Dependency Lookup).

(Mock Object) [ET]. $


(Mock Object), ,
(Smart Handlers).

. 193

194

11

. 11.11. (Service Locator)


(Test Double) .
(Test Double) .
(Dependency Lookup)
.
(Service Locator),
(Test Double)

(Object Factory; . , Dependency Lookup).


, / (Factory
Method) [GOF] .
(Object Factory) (Test Double)
.

(Service Locator; . , Dependency Lookup). 


,
(Registry) [PEAA].
(Service Locator) (Test Double)
.

, 
, (Service Locator),
(Lazy Initialization). , $
(Object Factory)? ? ,
 (Dependency Lookup).


, 

(TestSpecific Subclass).
Singleton [GOF] $
(Object Factory) (Service Locator). Singleton
, $

. 194

195

(Substitutable Singleton; . , TestSpecific Subclass,


. 591),
(Test Double). $
(Singleton),
(Dependency Injection). 
,
, (Test Double)
. ,
(Singleton), , 
. .
(TestSpecific Subclass)
(Dependency Injection) 
(. 11.12).
, .

(Test Double) . ,
, ,
(Test Stub). , 
(Subclassed Test Double; .
, TestSpecific Subclass).
.

. 11.12. (Test$Specific Subclass).


,


(TestSpecific Subclass) 
,
. , 

. 195

196

11

!
, .

, (Subclassed Test
Double) (. 11.13). , 
, 
. ,
(TestSpecific Subclass) .
, 
( , Sin
gleton). Singleton
soleInstance , soleInstance (Test Double) Sin
gleton soleInstance
(Test Double). Singleton,
(Subclassed Test Double).
(Service
Locator), (Subclassed Test Double)
(Service Locator).

. 11.13. (Test Double),


.
,


,
. .

. 196

197

(Test Hook)  ,


, (Test
Logic in Production). , 

.
, (Scripted Test, . 319)
(Recorded Test, . 312) (Safety Net,
. 79) .

(Test Hook).
[WEwLC] 
. ,
, .
, . 
,
. 

.
(Test Double)
. 
,
. 
, .
,
.


. 
(Test Double).


c (endoscopic
testing) [ET] (Mock Object).

(Mock Object) . 
,
.
,
. 
, 
.
. 
, 
.

. 197

198

11


c
[MRNO], 
.

$
(Mock Object).
, 
.

( ) 
,
.


(Fresh Fixture, . 344)
(Test Double).
(  
), $
(Test Double). 
, (Entity Chain Snipping; .
, Test Stub).


(Test Double) 
. , $
(Fake Object) 
! (Fake Database)

 .

. 351.


$
(Test Double), 
? , 
( , 
,
). 
(Constructor Test; . $
, Test Method), , 
. 

. 198

199

, 
(Test Double). 
.
, 5.
(Test Double),
(Mock Object) (Test Stub), $
(Overspecified Software; . , Fragile Test, . 277), 
. (Test
Double) ,
.



. , $
(Test Double) . 12,
, $
(Test Method) (Test Utility Method, . 610),
(Testcase Class, . 401)
(Test Helper, . 651).

. 199

, .

. 200

12

12




. 
.
(Test
Method, . 378).
. 
, . 

.
. 
(Testcase Class, . 401), $
(Test Method). , 
, .
(Testcase Class)
. 
.

xUnit
xUnit .
? ,
(Test Method) (Testcase Class).
(Test Suite Object, . 414), (Testcase
Class), (Test Discovery, . 420) $
(Test Enumeration, . 425). (Test Runner, . 405)
(Test Suite Object)
(Test Method).

. 201

202

12


(test condition) 
. ,
, 
. (Test Method)
,
(. 12.1). (Test Method)?

testMethod_1

testMethod_1

Testcase

testMethod_n

testMethod_n

. 12.1. . (Test Method)


(Four$Phase Test, . 388),
.


(Verify One Condition per Test, . 99), $
(Defect Localization, . 78). , ,
,
. ,
, 
. 
xUnit 
( 8, 
),
. , , 
(Eager Test; . , Assertion Roulette, . 264)
.

.
(Repeatable Test, . 81). ,
.  
? $

. 202

203

(Isolate the SUT, . 97) 


. 
. ,
, 
, 1.
(Minimize Test
Overlap, . 98), , 
.
,

. ,
.
.


(Test Method) (Testcase Class).
(Testcase Class) 
(Test Method)? , 
 , 
.


(Test Method) .
(Test Method) 
(Testcase Class),
(Testcase Class). (Test Method)
(. 12.2). (Testcase Class) 
. 
.


(. 12.3) (Testcase
Class) (Test Method), 
( 
, ).
. (
.)

(Testcase Class).
1

(Conditional Test Logic, . 243) (Test Method)


,

(Test Method).

. 203

204

12

testMethod_A_1
testMethod_A_2

feature_1

feature_2

testMethod_B_1

testMethod_B_2

. 12.2. (Testcase Class).


(Test Method)
(Testcase Class).
,
(Creation Method, . 441)
Feature1

testMethod_A
testMethod_B

Feature2

feature_ 1

feature_2

testMethod_A
testMethod_B

. 12.3. (Testcase Class) .


(Testcase Class)
.
(Test Method)

. 204

205


(. 12.4)
(Test Method), ( ),
(Testcase Class per Fixture, . 639).
setUp
( , Implicit Setup, . 449),
(Testcase Class).
FixtureA
setUp

testMethod_1
testMethod_2

FixtureB

feature_ 1

feature_ 2

setUp
testMethod_ 1
testMethod_2

. 12.4. (Testcase Class) .



. (Test Method)
,


, ,
. .
(Testcase Class per Fixture) 
,
. (Testcase
Class per Feature, . 633)
(Service Facade) [CJ2EEP].
. ,
(Prebuilt Fixture, . 454),
.
, 

. 205

206

12

(Testcase Class per Feature) $


(Delegated Setup, . 437) .



. ,
(Test Method)
. 
, (Testcase Class) (Test
Method) :

, 
;

. , 
, , 
, . 
, . 
. 12.5.
. 12.5
:

() ;

(Test Method) 
should. ,
, (Test Method). ( 
xUnit test , 
(Test Suite Object). 

(method attribute) (annotation).)


(Testcase Class) (Test Suite Fac
tory; . , Test Enumeration), (Test
Suite Object) (Testcase Object, . 410). 
(Test Method) (. 12.6). 
, xUnit. $
(Test Runner)
(Test Suite Factory) Factory Method [GOF],
suite.

. 206

207

. 12.5. .
,



testMethod_1

testMethod_n

. 12.6. (Testcase Class) (Test Suite


Factory). (Testcase Class)
(Test Suite Factory) (Test Suite Object),
(Test Runner). ,
, (Test Suite Factory),
(Test Suite Object)

. 207

208

12


( ),
. 
(Test Suite Factory) AllTests
. : $
(Named Test Suite, . 604) ,
.
(Subset Suite; . , Named Test Suite),
, , ( 
!) .
(Subset Suite)  (
). xUnit $
(Test Selection, . 429), $
(Subset Suite).

, . , $
(Subset Suite), , ,
, .
(Subset Suite) ,
. , $
(Suite of Suites) AllTests, $
(Subset Suite). , $
(Subset Suite), AllTests.


, (Test Method) 
. ,
. Go 
, 
. $
(Test Method), . 
, (Test Discovery)
. xUnit, ,
Ignore. 
(Lost Test; . , Production Bugs,
. 303), Ignore
. xUnit, (Test Tree Ex
plorer; . , Test Runner),
(. 12.7).
,
(Test Suite Factory). :

(Testcase Class)? , , , 
. (Single Test Suite; .
, Named Test Suite), MyTest, 

. 208

209

.
(Testcase Class),
(Test Method).

. 12.7. (Test Tree Explorer),


.


(Test Code Duplication, . 254) 
. ,
. ,
(Tests as Documentation,
. 79). (Test Method)
(, ),
(Flexible Test; . ,
Conditional Test Logic, . 243), .
$
(Implicit Setup) (Test Utility Method,
. 610).
(Test Double, . 538) .
(Test
Helper, . 651).

. 209

210

12

xUnit (Testcase
Superclass, . 646), TestCase. ( 
) (Testcase Class)
(. 12.8). (Testcase Class) 
, ,
c (Testcase Superclass), 
.
, ,
,  (Testcase Superclass) 
, 
. (Testcase Superclass) 
, . 
(Test Helper)

(Test Helper) . ,
(Testcase Class) (Testcase Superclass)
(Test Helper).

testMethod_1
testMethod_n

. 12.8. (Test Utility Method).



(Test Method)



(Testcase Superclass) (Test Utility
Method).

. 210

211

. ,
Template Method [GOF]. 
, 
, . 
, . 
[FaT].


:
(Testcase Class)? ,
.
. 
 , 
.
(Keep Test Logic Out of Production Code, . 99).

.



. .
(Keep
Test Logic Out of Production Code, . 99),
. 
, .

. , SAP ABAP Unit For Testing, .


(Testcase Class) ,
. , 
, .
, ,
.
Java, ,
2.
, , 
2

Java :
Security Manager, 
, .
, Java. 
( !) .

. 211

212

12

.

(test stripper), .



(Test Dependency in Pro
duction; . , Test Logic in Production, . 257),
, .
.
, (Test Logic in Production),
,
. 6, 
.


, 
. 13,
.

. 212

13

13



12, ,
. , , 
.
.
, .
, , 
.
(Slow Tests, . 289),
. 
.

. 9, 
.
.


:
, $
!
, .

. , , ,
.

. 213

214

13



. .
, (Database Sandbox, . 658) 
( ) 
(. 13.1).

. 13.1. (Database Sandbox) .


$$$$ ,
( ,
)

,
, 
.
. 9,
, .



. , 
, .
, , 
. (Slow Test), 
.
(Erratic Test, . 267)
(Obscure Test, . 230). ,
, , , 

. 214

215

.
(Unrepeatable Test; . , Erratic Test)
(Interacting Tests; . , Erratic Test) 

.



 .
(Lonely Test; . $
, Erratic Test), 
, .. (Chained Tests, . 477). 
(Database Sand
box), (Test Run War, . 274;
. , Erratic Test). , $
(Test Runner, . 405)
.

.

.


, : 
(General Fixture; . $
, Obscure Test), . 
$
(Prebuilt Fixture, . 454),
.
(Standard Fixture, . 338) $
(Fresh Fixture, . 344). 
. , (Mystery
Guest; . , Obscure Test) .


[DDD, PEAA,
WWW]  
. 
. (Layer Test, . 368)
(data access layer) (Test Double, . 538) (. 13.2).
,
(Layer Test),
(Fake Database; . , Fake Object,
. 565) (InMemory Database; . , Fake Ob

. 215

216

13

ject). (InMemory Database) ,


, , ,
. (Fake Database)
; , . 
, (Fake Database)
,
(Transient Fresh
Fixture; . , Fresh Fixture).
, 
(Slow Test). 
,
.
_1

_n

testMethod_1

testMethod_1

testMethod_2

testMethod_2

. 13.2. (Layer Test),


. (Layer Test)
. ,
(Test Double), (Context
Sensitivity; . , Fragile Test, . 277)

(Test Double) , 
. , 
, , 
. 
,
. 
. 
,
.
,

. 216

217

;
(Test Stub, . 544).
,
.
(Test Double) ,
. 
Strategy [GOF], 
null [PLoPD3].
null ; Strategy 
.
, 
( , 
).
( )
, 
. : $
(Dependency Injection, . 684)  $
(Dependency Lookup, . 692) .


, 
. ? 
? , ! ,
, .
, . 
, 
, .
? 
, . 
, . 
,
.


.
(Remoted Stored Procedure Test; . , Stored
Procedure Test, . 662) ,
.
, ( Remote Proxy, Fa
cade Command [GOF]). ,
(InDatabase Stored Procedure Test) ,
. (. 13.3). 
xUnit .
utPLSQL.

. 217

218

13

testMethod_1
testMethod_2


testMethod_1
testMethod_2

. 13.3.
(Self$Checking Test, . 81).
,


.
.
, , , .
xUnit (
, DbUnit Java).
( Read) (
Create/Update/Delete).

(Transaction Rollback
Teardown, . 675). DFT $
(Humble Transaction Controller; . , Humble Object, . 700).
,
.
, 
, $
(Table Truncation Teardown, . 668).

(Database Sandbox) 
.

. 218

219



.
(Database Sandbox). 
. 
1.
,
. 
, 
.
, $
(DBSchema per TestRunner) (Database
Partitioning Scheme).

(!)
,
. 
? : ,
!
, , 
, .
 ( 
).
(Subcutaneous Test; . , Layer Test) 
.


.

. ( [RDb].) 14, 
,
.

. 219

, .

. 220

14

14




13, ,
, , 
. , 6, 
, 9, 
, 11, .
, 
!
: 
 . ,
, 
. 
,
Capability Maturity Model (CMM).


, . 

. 
.
1. (entity objects; Domain Model [PEAA]).
 .
 .
2. .
.
 (Layer Test, . 368).

. 221

222

14

3. .
(Service Facade) [CJ2EEP]
(Subcutaneous Test; . , Layer Test).
.
4. .
,
(Humble Dialog; . , Humble Object, . 700).
.
.
5.  (
).
6.  .

. , 
, . , 
,
. , 
, , 
. ,
,
: , , ; 
, [WEwLC],
.


, , , 
. 
.
[HoN]:
.
1. .
.
.
2. .
(Assertion Method, . 390) 
.
(Assertion Method)
.
3. .

. 222

223

.
.
$
(Test Stub, . 544).
4. .
(Mock Object, . 558)
(Test Spy, . 552) .
5. .
.
, .
.
.
1.
, 
.
.


(Simple Success Test;
. , Test Method, . 378),
.
, , , 
,
.
, .
, 
.
.



(SelfChecking Test, . 81).
(Assertion Method), 
. 
, . ,

; 
(Assertion Method).

, 
.

. 223

224

14


.
(Untested Code; . ,
Production Bugs, . 303), , 
( , 
, ). 
: ? 
:

, ;

, 
.

, , 
, .
.
. 
.



, 
. (Test Stub), 
, 
.
, . 
(Test Stub): (HardCoded Test
Stub), , ,
(Configurable Test Stub), 
.
(Test Stub) .

. (Simple Success Test)
(Test Stub),
(Responder). ,
, (Expected Exception Test)
(Saboteur).


(Test Stub)
: . 
(Test Stub), 
. 
(Isolate the SUT, . 97).

. 224

225

(State Verification, . 484).


, .
(Untested Requirement; . ,
Production Bugs),
(Behavior Verification, . 489).

(Test Stub),
. (Test Spy) , ,

(Assertion Method) .
(Mock Object) %
.
.


.
.

(Slow Tests, . 289).

(Test Code Duplication, . 254),


.

(Obscure Test, . 230).

(Buggy Test,
. 296),
(Test Utility Method, . 610) (Conditional Test
Logic, . 243).


(Slow Test) %
. %
, ,
(Shared Fixture, . 350). ,
. ,
(Fake Object, . 565)
. (Fake Object)
.

. 225

226

14


(Obscure Test) . $
(Test Code Duplication) $
(Test Method) (Test Utility Method), 
. (Creation Method, . 441),
(Custom Assertion, . 495), (Finder Method; . $
, Test Utility Method) (Parameterized Test,
. 618) .
(Testcase Class, . 401) , 
, 
. ,
(Testcase Class) (Test Method), 
.


, (Buggy Test)
(Production Bugs), 
(, , )
. (Test
Utility Method) . $
(Test Utility Method) $
(Test Utility Test; . , Test
Utility Method).


I, . 114 
, , , ,
. II, , III, , 
, I.

. 226

II

. 227

. 228

15

15


:
(Obscure Test)................................................................ 230
(Conditional Test Logic) ........................................ 243
(HardtoTest Code).................................. 251
(Test Code Duplication)............................. 254
(Test Logic in Production)................................... 257

. 229

230

15

(Obscure Test)
:
(Long Test),
(Complex Test),
(Verbose Test)

,
.

.
,
.
(Tests as Documentation, . 79). , 
.
, 
, .

, .

(Obscure Test) ,
, .
(Tests as Documentation),
(High Test Maintenance Cost, . 300).
, 
, (Obscure Test). 
(Buggy Test, . 296). ,
(Eager Test) ,
, .

,
(Obscure Test) 
(Test Method, . 378). 
(Mystery Guest). (Eager Test) 
(Irrelevant Information)  
.
(Obscure Test)
. 
, , 
. (Obscure Test) .

(Test Method),
.

.

. 230

231

(Eager Test).
(Test Method).

(Mystery Guest).
 ,
(Test Method).

(Verbose Test) ( 
) 
.

(General Fixture). 
, , 
.

(Irrelevant Information). 
, 
, .

(HardCoded Test Data). 


, 
(Test Method),  
.

(Indirect Testing). (Test Method)


, 
.

: (Eager Test)
$
(Test Method).

, , . 
, , 
.
public void testFlightMileage_asKm2() throws Exception {
//
//
Flight newFlight = new Flight(validFlightNumber);
//
assertEquals(validFlightNumber, newFlight.number);
assertEquals("", newFlight.airlineCode);
assertNull(newFlight.airline);
//
newFlight.setMileage(1122);
//
int actualKilometres = newFlight.getMileageAsKm();
//
int expectedKilometres = 1810;
assertEquals(expectedKilometres, actualKilometres);
// ,

. 231

232

15

newFlight.cancel();
try {
newFlight.getMileageAsKm();
fail("Expected exception");
} catch (InvalidRequestException e) {
assertEquals(
" ",
e.getMessage());
}
}



, .
, .

.


(Single Condition Test, . 99), $
(Defect Localization, . 78).
: (Mystery Guest)
 
, $
(Test Method).

. 
(FourPhase Test, . 387)

. ( ) ,
(Assertion Method, . 390)
.

, ,
, , 
(Mystery Guest). ,
, , 
.
public void testGetFlightsByFromAirport_OneOutboundFlight_mg()
throws Exception {
loadAirportsAndFlightsFromFile("test-flights.csv");
//
List flightsAtOrigin =

. 232

233

facade.getFlightsByOriginAirportCode("YYC");
//
assertEquals( 1, flightsAtOrigin.size());
FlightDto firstFlight = (FlightDto) flightsAtOrigin.get(0);
assertEquals( "Calgary", firstFlight.getOriginCity());
}

(Mystery Guest) 
( ) 
.
(Tests as Documentation). , 
, .
: (Resource
Optimism; . , Erratic Test, . 267)!
(Mystery Guest) $
(Shared Fixture, . 350),
(Erratic Test).

, 
. (Mystery Guest) .


. .


. .


(Assertion Method) .

(Shared Fixture) $
(Setup Decorator, . 471). 
.

(General Fixture)
(Implicit Setup, . 449), (Test Method) 
.

: 
,
.
, (Mystery Guest).


(Fresh
Fixture, . 344) (Inline Setup, . 433). 

( , Setup External Re
source, . 741) (Test Stub) 
(. , In

. 233

234

15

line Resource, . 738). (Irrelevant Informa


tion), ,
(Creation Method, . 441) .
(Shared Fixture) $
(Implicit Setup), 
(Finder Method; . , Test
Utility Method, . 610) . 
, , ,
, .

: (General Fixture)
, ,
.

, 
, . 
,
.
.
public void testGetFlightsByFromAirport_OneOutboundFlight()
throws Exception {
setupStandardAirportsAndFlights();
FlightDto outboundFlight = findOneOutboundFlight();
//
List flightsAtOrigin = facade.getFlightsByOriginAirport(
outboundFlight.getOriginAirportId());
//
assertOnly1FlightInDtoList("Flights at origin",
outboundFlight,
flightsAtOrigin);
}
public void testGetFlightsByFromAirport_TwoOutboundFlights()
throws Exception {
setupStandardAirportsAndFlights();
FlightDto[] outboundFlights =
findTwoOutboundFlightsFromOneAirport();
//
List flightsAtOrigin = facade.getFlightsByOriginAirport(
outboundFlights[0].getOriginAirportId());
//
assertExactly2FlightsInDtoList("Flights at origin",
outboundFlights,
flightsAtOrigin);
}

,
. 
(Fresh Fixture), 
( setupStan-

. 234

235

dardAirportsAndFlights). ,
(General Fixture).
(Standard Fixture,
. 338) ,
, .
, (Slow Tests, . 289)
(Fragile Fixture; . , Fragile Test, . 277).


, 
.
(Implicit Setup) $
(Shared Fixture) 
. 
. , . 
(Standard
Fixture), .
,
(General Fixture).

, 
, , .
(Tests as Documentation)
(Fragile Fixture), 
. ,
(Slow Test),
, 
.


(Minimal Fixture, . 336). $
(Fresh Fixture, . 344).
(Shared Fixture), $
(Make Resource Unique, . 739)
(Database Sandbox, . 658) . ( $
(Immutable Shared Fixture) 
, ,
; !)
: (Irrelevant Information)
, 
, .

. 235

236

15

, 
.
public void testAddItemQuantity_severalQuantity_v10(){
//
Address billingAddress =
createAddress("1222 1st St SW", "Calgary", "Alberta",
"T2N 2V2", "Canada");
Address shippingAddress =
createAddress("1333 1st St SW", "Calgary", "Alberta",
"T2N 2V2", "Canada");
Customer customer =
createCustomer(99, "John", "Doe", new BigDecimal("30"),
billingAddress, shippingAddress);
Product product =
createProduct(88,"SomeWidget",new BigDecimal("19.99"));
Invoice invoice = createInvoice(customer);
//
invoice.addItemQuantity(product, 5);
//
LineItem expected =
new LineItem(invoice, product,5, new BigDecimal("30"),
new BigDecimal("69.96"));
assertContainsExactlyOneLineItem(invoice, expected);
}

,
. 
, .
public void testGetFlightsByOriginAirport_TwoOutboundFlights()
throws Exception {
FlightDto expectedCalgaryToSanFran = new FlightDto();
expectedCalgaryToSanFran.setOriginAirportId(calgaryAirportId);
expectedCalgaryToSanFran.setOriginCity(CALGARY_CITY);
expectedCalgaryToSanFran.setDestinationAirportId(sanFranAirportId);
expectedCalgaryToSanFran.setDestinationCity(SAN_FRAN_CITY);
expectedCalgaryToSanFran.setFlightNumber(
facade.createFlight(calgaryAirportId,sanFranAirportId));
FlightDto expectedCalgaryToVan = new FlightDto();
expectedCalgaryToVan.setOriginAirportId(calgaryAirportId);
expectedCalgaryToVan.setOriginCity(CALGARY_CITY);
expectedCalgaryToVan.
setDestinationAirportId(vancouverAirportId);
expectedCalgaryToVan.setDestinationCity(VANCOUVER_CITY);
expectedCalgaryToVan.setFlightNumber(facade.createFlight(
calgaryAirportId, vancouverAirportId));

.
List lineItems = inv.getLineItems();
assertEquals("number of items", lineItems.size(), 2);
//

LineItem actual = (LineItem)lineItems.get(0);
assertEquals(expItem1.getInv(), actual.getInv());

. 236

237

assertEquals(expItem1.getProd(), actual.getProd());
assertEquals(expItem1.getQuantity(), actual.getQuantity());
//

actual = (LineItem)lineItems.get(1);
assertEquals(expItem2.getInv(), actual.getInv());
assertEquals(expItem2.getProd(), actual.getProd());
assertEquals(expItem2.getQuantity(), actual.getQuantity());
}


, (Literal
Value, . 718) . (Irrelevant Information)
(HardCoded Test Data) $
(General Fixture); 
, , , 
. 
( )
, .
,
, (Procedural State Verification;
. , State Verification, . 484) 
.

(Tests as Documentation), 
(Obscure Test), 
 .

(High Test Maintenance Cost) 
(Production Bugs, . 303)
(Buggy Test).

(Irrelevant Information) 
,
(Factory Method) [GOF]
(Parameterized Creation Method; . , Creation Method),
. 
, (.. ),
(Creation Method)
$ (Dummy Object, . 730). ,
, . 
, 
, (
, Fresh Fixture).
(Irrelevant Information) 

(Expected Object; . , State Verification) 

. 237

238

15

. (Custom Asser
tion, c. 495), .

: (Hard/Coded Test Data)


, 
(Test Method), 
.


. ,
, (Erratic Test).
public void testAddItemQuantity_severalQuantity_v12(){
//
Customer cust = createACustomer(new BigDecimal("30"));
Product prod = createAProduct(new BigDecimal("19.99"));
Invoice invoice = createInvoice(cust);
//
invoice.addItemQuantity(prod, 5);
//
LineItem expected = new LineItem(invoice, prod, 5,
new BigDecimal("30"), new BigDecimal("69.96"));
assertContainsExactlyOneLineItem(invoice, expected);
}

, .
,
(19.99), (5), 
(30) (69.96).


(HardCoded Test Data) ,
(Literal Value). 
. 

. ( ) ,
(Assertion Method). 

( )
.

, .

(Tests as Documentation),
(Obscure Test), 
 . 
. , .

. 238

239

, 
/  .
,
. $
(Shared Fixture), (Fresh
Fixture) , .


(Obscure Test)
 . , 
( ), 
, ,
.
( ) 
(Creation Method). ,
, 
. , 
,
( , Fresh Fixture).
, 
,
(Derived Value, . 722), 
.
(Shared Fixture),
(Distinct Generated
Value; . , Generated Value, . 726) 
. , 
.
(Anonymous Creation Method; . ,
Creation Method).
: (Indirect Testing)
(Test Method) 
, .

, , , 
, . ,
, . 
 $
(Indirect Testing).
private final int LEGAL_CONN_MINS_SAME = 30;
public void testAnalyze_sameAirline_LessThanConnectionLimit()
throws Exception {
//
FlightConnection illegalConn =

. 239

240

15

createSameAirlineConn( LEGAL_CONN_MINS_SAME - 1);


//
FlightConnectionAnalyzerImpl sut =
new FlightConnectionAnalyzerImpl();
String actualHtml =
sut.getFlightConnectionAsHtmlFragment(
illegalConn.getInboundFlightNumber(),
illegalConn.getOutboundFlightNumber());
//
StringBuffer expected = new StringBuffer();
expected.append("<span class="boldRedText">");
expected.append("Connection time between flight ");
expected.append(illegalConn.getInboundFlightNumber());
expected.append(" and flight ");
expected.append(illegalConn.getOutboundFlightNumber());
expected.append(" is ");
expected.append(illegalConn.getActualConnectionTime());
expected.append(" minutes.</span>");
assertEquals("html", expected.toString(), actualHtml);
}

,
. .
(Tests as Documentation).
(Indirect Testing) $
(Fragile Test), 
.

,
. 
, .
.
, 
. 
.


.
(Extract Testable Component) [WEwLC]
. 
(Humble Object, . 700) ,
.
public void testAnalyze_sameAirline_EqualsConnectionLimit()
throws Exception {
//
Mock flightMgntStub = mock(FlightManagementFacade.class);
Flight firstFlight = createFlight();
Flight secondFlight = createConnectingFlight(

. 240

241

firstFlight, LEGAL_CONN_MINS_SAME);
flightMgntStub.expects(once()).method("getFlight")
.with(eq(firstFlight.getFlightNumber()))
.will(returnValue(firstFlight));
flightMgntStub.expects(once()).method("getFlight")
.with(eq(secondFlight.getFlightNumber()))
.will(returnValue(secondFlight));
//
FlightConnAnalyzer theConnectionAnalyzer =
new FlightConnAnalyzer();
theConnectionAnalyzer.facade =
(FlightManagementFacade)flightMgntStub.proxy();
FlightConnection actualConnection =
theConnectionAnalyzer.getConn(
firstFlight.getFlightNumber(),
secondFlight.getFlightNumber());
//
assertNotNull("actual connection", actualConnection);
assertTrue("IsLegal", actualConnection.isLegal());
}

, 
. , $
(Indirect Testing),
(Test Utility Method).
(Creation Method),  $
(Verification Method; . , Custom Assertion).
(SUT
API Encapsulation; . , Test Utility Method).
public void testAnalyze_sameAirline_LessThanConnLimit()
throws Exception {
//
FlightConnection illegalConn =
createSameAirlineConn(LEGAL_CONN_MINS_SAME - 1);
FlightConnectionAnalyzerImpl sut =
new FlightConnectionAnalyzerImpl();
//
String actualHtml =
sut.getFlightConnectionAsHtmlFragment(
illegalConn.getInboundFlightNumber(),
illegalConn.getOutboundFlightNumber());
//
assertConnectionIsIllegal(illegalConn, actualHtml);
}

(Custom Assertion) 
 .
(Extract Method) [Ref]. , 
HTML
.
(Presentation level test; . , Layer
Test, . 368) HTML.

. 241

242

15

private void assertConnectionIsIllegal(FlightConnection conn,


String actualHtml) {
//
StringBuffer expected = new StringBuffer();
expected.append("<span class="boldRedText">");
expected.append("Connection time between flight ");
expected.append(conn.getInboundFlightNumber());
expected.append(" and flight ");
expected.append(conn.getOutboundFlightNumber());
expected.append(" is ");
expected.append(conn.getActualConnectionTime());
expected.append(" minutes.</span>");
//
assertEquals("html", expected.toString(), actualHtml);
}


. 
, ,

.
.

(Test Utility Method) $
(Parameterized Test, . 618) 
(Expected Object).

(Obscure Test), .
(FourPhase Test) 
(Test Utility Method). 
. , 
, . ,
$
(Test Utility Test) 
(Test Utility Method).

. 242

243

(Conditional Test Logic)


,
.

:

(Indented Test Code)

(Fully Automated Tests, . 81)


, . , ,
? , 
? : (Test Method, . 378)
, .
(Conditional Test Logic) ,
, .

(Conditional Test Logic)


, . 
(Test
Method)! , ,
. (Conditional Test Logic), 
, if.
//
, Vancouver
actual = null;
i = flightsFromCalgary.iterator();
while (i.hasNext()) {
FlightDto flightDto = (FlightDto) i.next();
if (flightDto.getFlightNumber().equals(
expectedCalgaryToVan.getFlightNumber()))
{
actual = flightDto;
assertEquals("Flight from Calgary to Vancouver",
expectedCalgaryToVan,
flightDto);
break;
}
}
}

:
, ?
(High Test
Maintenance Cost, . 300) , ,
(Conditional Test Logic).

. 243

244

15

(Conditional Test Logic) ,


. 
. 
.
(SelfChecking Test, . 81) 
. 
,  ?
( ), , 
. ,
, 
.
$
(Conditional Test Logic). ,
, ,
? ( (Obscure Test, . 229),
(Buggy
Test, . 296).)


(Conditional Test Logic) .

if fail 
, 
.


( , Conditional Verification Logic).
(Obscure Test).

(Conditional Test Logic)


(
, Conditional Verification Logic).
equals Foreign Method [Ref].

(Conditional Test Logic) 


(Expected Object; .
, State Verification, . 484),
( , Flexible Test).

if 
( , Complex Teardown).

. 244

245

: (Flexible Test)
.

,
.
(Conditional Test Logic) 
.
, 
.
public void testDisplayCurrentTime_whenever() {
//
TimeDisplay sut = new TimeDisplay();
//
String result = sut.getCurrentTimeAsHtmlFragment();
//
Calendar time = new DefaultTimeProvider().getTime();
StringBuffer expectedTime = new StringBuffer();
expectedTime.append("<span class=\"tinyBoldText\">");
if ((time.get(Calendar.HOUR_OF_DAY) == 0)
&& (time.get(Calendar.MINUTE) <= 1)) {
expectedTime.append( "Midnight");
} else if ((time.get(Calendar.HOUR_OF_DAY) == 12)
&& (time.get(Calendar.MINUTE) == 0)) { //
expectedTime.append("Noon");
} else {
SimpleDateFormat fr = new SimpleDateFormat("h:mm a");
expectedTime.append(fr.format(time.getTime()));
}
expectedTime.append("</span>");
assertEquals(expectedTime, result);
}


(Flexible Test) .
, 
, .

(Flexible Test) ,
, . , 
, .
, ?
? , , 
, ,
.

. 245

246

15


(Flexible Test) 
, .
/
(substitutable dependency). $
(Test Double, . 538), (Test Stub, . 544) $
(Mock Object, . 558). 
.
: (Conditional Verification Logic)
(Conditional Verification Logic) 
. ,
,

.
//
, Vancouver
actual = null;
i = flightsFromCalgary.iterator();
while (i.hasNext()) {
FlightDto flightDto = (FlightDto) i.next();
if (flightDto.getFlightNumber().equals(
expectedCalgaryToVan.getFlightNumber()))
{
actual = flightDto;
assertEquals("Flight from Calgary to Vancouver",
expectedCalgaryToVan,
flightDto);
break;
}
}
}


if fail
(Guard Assertion, . 510), 
, .
,
(Expected Exception Test; . , Test Method). 

(Expected Exception Test), xUnit.
(Conditional Test Logic) 
(Equality Assertion; . , As
sertion Method, . 390) (Expected Object). 
equals , $
(Custom Assertion, . 495)
(testspecific equality).

(Custom Assertion).

. 246

247

(Custom Assertion Test; . , Custom


Assertion).
(Test Utility Method, . 610) 
. $
(Parameterized Test, . 618), 
(Expected Object).

: (Production Logic in Test)

(Conditional Test Logic)


. .
public void testCombinationsOfInputValues() {
//
Calculator sut = new Calculator();
int expected; //
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
//
int actual = sut.calculate( i, j );
//
if (i==3 & j==4) //
expected = 8;
else
expected = i+j;
assertEquals(message(i,j), expected, actual);
}
}
}
private String message(int i, int j) {
return "Cell( " + String.valueOf(i)+ ","
+ String.valueOf(j) + ")";
}

(LoopDriven Test; . $
, Parameterized Test)
i j. (Conditional
Test Logic) .


(Production Logic in Test) 

(Test Method). , ,
. 
,
. 

(Calculated Value; . , Derived Value, . 722). 
( )
.

. 247

248

15


,
.
() .
public void testMultipleValueSets() {
//
Calculator sut = new Calculator();
TestValues[] testValues = {
new TestValues(1,2,3),
new TestValues(2,3,5),
new TestValues(3,4,8), // !
new TestValues(4,5,9)
};
for (int i = 0; i < testValues.length; i++) {
TestValues values = testValues[i];
//
int actual = sut.calculate( values.a, values.b);
//
assertEquals(message(i), values.expectedSum, actual);
}
}
private String message(int i) {
return "Row "+ String.valueOf(i);
}

: (Complex Teardown)


, . 
, , 
. 
.
public void testGetFlightsByOrigin_NoInboundFlight_SMRTD()
throws Exception {
//
BigDecimal outboundAirport = createTestAirport("1OF");
BigDecimal inboundAirport = null;
FlightDto expFlightDto = null;
try {
inboundAirport = createTestAirport("1IF");
expFlightDto =
createTestFlight(outboundAirport, inboundAirport);
//
List flightsAtDestination1 =
facade.getFlightsByOriginAirport(inboundAirport);
//
assertEquals(0,flightsAtDestination1.size());
} finally {
try {
facade.removeFlight(expFlightDto.getFlightNumber());
} finally {
try {

. 248

249

facade.removeAirport(inboundAirport);
} finally {
facade.removeAirport(outboundAirport);
}
}
}
}


, 
(garbage collection). (Complex
Teardown) ,
(Test Method).

,
(Implicit Teardown, . 533), ,
(Automated Teardown, . 521), 
.
,

(Fresh Fixture, . 344) 
(Test Double).
: (Multiple Test Conditions)


, . 

.
public void testMultipleValueSets() {
//
Calculator sut = new Calculator();
TestValues[] testValues = {
new TestValues(1,2,3),
new TestValues(2,3,5),
new TestValues(3,4,8), // !
new TestValues(4,5,9)
};
for (int i = 0; i < testValues.length; i++) {
TestValues values = testValues[i];
//
int actual = sut.calculate( values.a, values.b);
//
assertEquals(message(i), values.expectedSum, actual);
}
}
private String message(int i) {
return "Row "+ String.valueOf(i);
}

. 249

250

15



(Test Method).
(Conditional Test Logic). 
, if 
.

(Conditional Test Logic)
(Multiple Test Conditions) . 

(Defect Localization, . 78) .
$
(Extract Method) [Ref]
(Parametrized Test) . (Defect Lo
calization) (Parameterized Test) 
(Test Method) . 

(DataDriven Test, . 322).

. 250

251

(Hard/to/Test Code)
.
 ,

. , , 
(Fully Automated Tests, . 81). 
.
, .
( ,
. (Frequent De
bugging, . 285)
(Defect Localization, . 78).)
(HardtoTest Code) , 

.

,
, .
. 
. 
, ,
.

(HardtoTest Code)
. ,
, 
, . ,
.


. 
, .
.

(Hardto
Test Code). .

. 251

252

15

: (Highly Coupled Code)


.

:

(Hard-Coded Dependency)

,
.

(Highly Coupled Code) 
, , 
, 
.

. 
.
$
(Test Double, . 538),  (Test Stub, . 544) $
(Mock Object, . 558).
11, .
,
. ,
[WEwLC].
: (Asynchronous Code)

.
(, , 
) .

,
. 

. ,
, 
.

,
.

. 252

253



. (Humble Object,
. 700), (Humble Dialog)
(Humble Executable),
.
: (Untestable Test Code)

(Test Method, . 378) (.


, Obscure Test, . 230)
(Conditional Test Logic, . 243), .

(Conditional Test Logic) (Test


Method) (Buggy Test,
. 296) (High Test
Maintenance Cost, . 300).
.

(Test Method) 
(SelfChecking Test, . 81).
(Test Double), 

(Expected Exception Test; . , Test Method) 
, .

(Test Method) 
, (Conditional
Test Logic) (Test Utility Method, . 610).
(SelfChecking Test)
.

. 253

254

15

(Test Code Duplication)


.
. , 
, . 
. 
.

(Test Code Duplication).

,
.
public void testInvoice_addOneLineItem_quantity1_b() {
//
inv.addItemQuantity(product, QUANTITY);
//
List lineItems = inv.getLineItems();
assertEquals("number of items", lineItems.size(), 1);
//
LineItem expItem = new LineItem(inv, product, QUANTITY);
LineItem actual = (LineItem)lineItems.get(0);
assertEquals(expItem.getInv(), actual.getInv());
assertEquals(expItem.getProd(), actual.getProd());
assertEquals(expItem.getQuantity(), actual.getQuantity());
}
public void testRemoveLineItemsForProduct_oneOfTwo() {
//
Invoice inv = createAnonInvoice();
inv.addItemQuantity(product, QUANTITY);
inv.addItemQuantity(anotherProduct, QUANTITY);
LineItem expItem = new LineItem(inv, product, QUANTITY);
//
inv.removeLineItemForProduct(anotherProduct);
//
List lineItems = inv.getLineItems();
assertEquals("number of items", lineItems.size(), 1);
LineItem actual = (LineItem)lineItems.get(0);
assertEquals(expItem.getInv(), actual.getInv());
assertEquals(expItem.getProd(), actual.getProd());
assertEquals(expItem.getQuantity(), actual.getQuantity());
}

.
public void testInvoice_addTwoLineItems_sameProduct() {
Invoice inv = createAnonInvoice();
LineItem expItem1 = new LineItem(inv, product, QUANTITY1);
LineItem expItem2 = new LineItem(inv, product, QUANTITY2);
//

. 254

255

inv.addItemQuantity(product, QUANTITY1);
inv.addItemQuantity(product, QUANTITY2);
//
List lineItems = inv.getLineItems();
assertEquals("number of items", lineItems.size(), 2);
//
LineItem actual = (LineItem)lineItems.get(0);
assertEquals(expItem1.getInv(), actual.getInv());
assertEquals(expItem1.getProd(), actual.getProd());
assertEquals(expItem1.getQuantity(), actual.getQuantity());
//
actual = (LineItem)lineItems.get(1);
assertEquals(expItem2.getInv(), actual.getInv());
assertEquals(expItem2.getProd(), actual.getProd());
assertEquals(expItem2.getQuantity(), actual.getQuantity());
}

(Test Code Duplication).


: , 
(Testcase Class, . 401).


. 
( , 
, , ). 
(. $
, High Test Maintenance Cost, . 300), 
, .

: (Cut/and/Paste Code Reuse)


,
, 
.


(CutandPaste Code Reuse) 
. ,
,  , ,
( ) () .
, , 
,
. ,
. 
, .

. 255

256

15


(Test Code Duplication) 
(Extract Method) [Ref]
(Test Utility Method, . 610)

. (Test Code Duplication)
, (Crea
tion Method, . 441) (Finder Method; . $
, Test Utility Method). ,
(Custom Assertion, . 495) $
(Verification Method; . ).
(Introduce Parameter) [JBrains] 
, 
.
(Test Code Duplication) 
(Test Method) , 
. ,
, , $
(Test Utility Method).
(Test Utility Method), 
. (
, 
.)
: (Reinventing the Wheel)
(CutandPaste Code Reuse)

,
.


 $
(Test Utility Method). ,
.

$
(CutandPaste Code Reuse),
. (
)
(Test Utility Method).

(Test Code Duplication)
XP2001, Refactoring Test Code [RTC].

. 256

257

(Test Logic in Production)


,
.
, 
. ,
.

,
. ,

. 
, .

(Test Logic in Production),


,
. ,
, !

: (Test Hook)
,
, , .


. 
.
if (testing) {
return hardCodedCannedData;
} else { // ...
return gatheredData;
}

ARIANE
Ariane 5 : 37 
. , , ,
, , , ,
40 . 64 , 

. 257

258

15

, 16
, !
, 
. (Test
Logic in Production, . 257), , .

? , , 

, ,
.
, , ,
.
.
, , Ariane 4,
. ,
Ariane 5 
.
( ) , ...,
http://www.around.com/ariane.html.


.
Ariane 5 37 , , 
, 40
. 64 , 
, 16 .
, (.
). , (Test Hook)
, ?

(Test Logic in Production) 

() . (Test
Logic in Production) , 
. ,
,
.
, 
. ,
, (Fake
Database; . , Fake Object, . 565). ,
 .

. 258

259



. , ,
Strategy [GOF], 
Null Object [PLoPD3] . , ,
, Strategy [GOF],
Null Object. , 
Strategy.
(Constructor
Test; . , Test Method, . 378),
, Strategy, 
.
, 
(TestSpecific Subclass, . 591). ,
.
: (For Tests Only)
, .

. 
, .

,
(For Tests Only), .
 ,
. ,

.

, 

(, , Test Double).
,
. 
, 
.
(For Tests Only) ,
. ( , 
)
, , , 
.

. 259

260

15



(TestSpecific Subclass), ,
.

, .
 $
(TestSpecific Subclass),
(For Tests Only). 
( FTO_).
: (Test Dependency in Production)
.

.
. , 
, .

,
. 
, 
. , 
.

(Test Dependency in Production)
 .
, (builtin selftest) 
,
(Test Utility Method, . 610), .

,
, .
, , , 
, .
: (Equality Pollution)
(Test Logic in Production)
equals 
.

. 260

261

(Equality Pollution)  


, 
equals. , 
equals
equals 
.

equals
. , equals ,
 .
(Equality Pollution) 
, .

(Equality Pollution)
.
(Mock Object, . 558) 
equals ,
(Equality Pollution).

,
(Custom Assertion, . 495),
equals (Equality Asser
tion; . , Assertion Method, . 390).
(Mock
Object) Comparator [WWW], equals,
. , equals
(TestSpecific Subclass) (Expected
Object; . , State Verification, . 484), 
.

(For Tests Only) (Equality Pollution)
Refactoring Test Code [RTC] XP2001.

. 261

. 262

16

16


:
(Assertion Roulette)................................................. 264
(Erratic Test)............................................................... 267
(Fragile Test) .................................................................... 277
(Frequent Debugging) ........................................................ 285
(Manual Intervention) ........................................... 287
(Slow Tests)................................................................... 289

. 263

264

16

(Assertion Roulette)
, /
.

. (Test Run
ner, . 405), , .


, . 
( ,
, Resource Optimism), 
.

: (Eager Test)
.


, 
.
public void testFlightMileage_asKm2() throws Exception {
//
//
Flight newFlight = new Flight(validFlightNumber);
//
assertEquals(validFlightNumber, newFlight.number);
assertEquals("", newFlight.airlineCode);
assertNull(newFlight.airline);
//
newFlight.setMileage(1122);
//
int actualKilometres = newFlight.getMileageAsKm();
//
int expectedKilometres = 1810;
assertEquals(expectedKilometres, actualKilometres);
// ,
newFlight.cancel();
try {
newFlight.getMileageAsKm();
fail("Expected exception");
} catch (InvalidRequestException e) {

. 264

265

assertEquals("Cannot get cancelled flight mileage",


e.getMessage());
}
}


(Test Automation Framework, . 332)
.


(Eager Test) 
,
(Test Method, . 378).
( ,
),
(Fully Automated Tests, . 81) .
(Eager Test) 
xUnit .
. ,
, .

(Single
Condition Test, . 99). 
(Extract Method) [Ref],
(Test Method).
(Test Method)
( ). , 
, 
(Creation Method, . 441).
, .
xUnit 
, .

.
(Back Door Setup; . , Back Door Manipulation, . 359)

, .
(Defect Localization). , 
,
(Communicate Intent, . 95).
: (Missing Assertion Message)

. (Test
Runner) , .

. 265

266

16


(Assertion Method,
. 391) (Assertion Mes
sage, . 398).
(CommandLine Test Runner) , 
.
(Equality Assertion;
. , Assertion Method).
public void testInvoice_addLineItem7() {
LineItem expItem = new LineItem(inv, product, QUANTITY);
//
inv.addItemQuantity(product, QUANTITY);
//
List lineItems = inv.getLineItems();
LineItem actual = (LineItem)lineItems.get(0);
assertEquals(expItem.getInv(), actual.getInv());
assertEquals(expItem.getProd(), actual.getProd());
assertEquals(expItem.getQuantity(), actual.getQuantity());
}

, ?
(Equality Assertion) , ,
,
. 
(Assertion Message),
(Assertion Method) .


, 
, 
.

.
,
,
. ,
. , 
(Assertion Message)
(Assertion Method).

(Assertion Roulette) (Eager Test)
Refactoring Test Code [RTC] XP2001.

. 266

267

(Erratic Test )
;
, //// .

, , 
. $
(Erratic Test)
,  .
(Erratic Test)
(Test Runner, . 405).

, $
(Lost Test; . , Production Bugs, . 303). $
(Erratic Test) , 
, .
,
, 
.


 (Erratic Test)
. , 
.
. ( ) 
, ? 
?
?
(Test Runner) ?

. 

. . 16.1 
(Erratic Test).

.

. 
.

. 267

268

16

,
/

xUnit!

. 16.1. (Erratic Test)

: (Interacting Tests)
. , $
(Interacting Test Suites) (Lonely Test)
(Interacting Tests).


:

( );

(Test Runner).


(Interacting Tests)
(Shared Fixture, . 350), 
. (Interacting
Tests) :

(, 
) . ,
, .
, . , 

. 268

269

, 
(Test Automation Framework, . 332)!
. 411. Singleton [GOF] Registry [PEAA]
,
. , &
.
, &
, :

, ;

,
;

,
.

, :

,
;

(
(Testcase Class, . 401).

, :

.
: &
. &
&&&& ,
. .
,
& . xUnit
. ( TestNG &
.)


(Fresh Fixture, . 344) &
(Interacting Tests). &
. 
(Shared Fixture),
(Immutable Shared Fixture). &
( &
).

. 269

270

16


, , $
(Lazy Setup, . 460) . 

. $
(Creation Method, . 441)
(Test Code Duplication, . 254). (Testcase
Class),
(Test Helper, . 651).
, 
, .
(Automated Fixture
Teardown; . , Automated Teardown, . 521)
.

. , 
. 
(Interacting Tests).

: (Interacting Test Suites)


(Interacting Tests), 
.

.
(Suite of Suites, . , Test Suite Object, . 414) 
.
Suite1.run()-->
Suite2.run()-->
Suite(Suite1,Suite2).run()--> C Suite2


(Interacting Test Suites) , 
. 
, .

(Test Method,
. 378). ,
. ,
,
( ). ,
, (Shared Fix
ture), .
(Test Method), setUp
(Test Utility Method, . 610).

. 270

271

: , 
!

(Suite Fixture Setup, . 465) (Setup Decorator, . 471) 
(Testcase Class), $
(Test Method)!
xUnit, (Testcase Class Dis
covery; . , Test Discovery, . 420), NUnit,
. , 
(Test Suite Factory) $
(Test Suite Object) (Test Runner).


$
(Fresh Fixture). , 
(Immutable Shared
Fixture) .
, 
, $
(Automated Teardown) .
: (Lonely Test)
(Lonely Test)
(Interacting Tests). , 
, (Shared Fixture), 
(. , Chained Tests, . 477) 
(, , Setup Decorator).
$
(Fresh Fixture) (Lazy Setup)
(Lonely Test), .

: (Resource Leakage)
.


. (Test Runner), 
(Database Sandbox, . 658)
, .

,
. 
.
.

. 271

272

16

. 
, .

, 
.


, , 
. ,
.  
, $
(Guaranteed Inline Teardown)
(Automated Teardown).
1,
, .
: (Resource Optimism)
, 
.

 .

, .


(Fresh Fixture), .
.
,
.
, 
, (Test Runner) 
.
: (Unrepeatable Test)
.
.


, 
. .

. 272

273

Suite.run()-->
Suite.run()--> C
Suite.run()--> C
-
Suite.run()-->
Suite.run()--> C

.
Suite.run()--> C
Suite.run()-->
Suite.run()-->
-
Suite.run()--> C
Suite.run()-->

, , (Unrepeatable
Test), .
Suite.run()--> C
Suite.run()--> X
Suite.run()--> X
-
Suite.run()--> C
Suite.run()--> X

C FailPassPass, X 
PassFailFail. ,
. , 
.


(Unrepeatable Test) 
(Shared Fix
ture). ,
.

(Prebuilt Fixture), 
, .
(Database Sandbox)
,
(Test Runner).
(Lazy Setup)

.
,
(Test Runner).

(Shared Fixture) 
(Unrepeatable Test),

. 273

274

16

, (Fresh Fixture) .
, 
, (Database Sandbox),
. (Fake
Database). , 
(Distinct Generated Value, . 728)
, .
(Automated Teardown)
.

: (Test Run War)


,
.

,
. , 
.
Suite.run()
Suite.run()
Suite.run()
Suite.run()

>
>
>
>

3
2

1

, ,
. 
, .

(Test Run War) , 


.
: ! 

( ). , ,
,
, .

(Test Run War) 
(Shared Fixture),
.
, ,
.
:

. 274

, 
( );

275

,
, .


(Fresh Fixture) 
(Test Run War).
(Test Runner)
(Database Sandbox).
, (Test Run War). 
(Erratic Test) , 
(Shared Fixture)
(Database Sandbox).  
(Shared Fixture), 
. 
(Test Method).

, $
(Automated Teardown) .
(Test Run War),
.
: (Nondeterministic Test)
,
(Test Runner).

.
Suite.run()
Suite.run()
Suite.run()
Suite.run()

>
>
>
>

3
3

3

(Test Run War) 


, 
.
(Unrepeatable Test),
(Nondeterministic Test)
. , 
, .

(Nondeterministic Test)
,  .
,
. ( 
, .)

. 275

276

16


(Nondeterministic Test) 
. ,
. , (Distinct
Generated Value) , 
. ,
, 
(Nondeterministic Test), .

, ( )
 .
, 
,  .

,
.

,
.

, 
. , 
( (Repeatable Tests, . 81).

(Conditional Test Logic, . 243).
. .
(Flexible Test; .
, Conditional Test Logic). , 
, !



(Conditional Test Logic). 
. 
, , 
.
. 
(Test Code Duplication),
(Parameterized Test, . 618) 
, (Data
Driven Test, . 322).

. 276

277

(Fragile Test)

, .

, 
, .
.
, (Fragile Test).

. 
(Fully Automated Tests, . 81) 
.
.
, .

(Fragile Test) , 

. (Fragile Test)
, 
(, ).


. :
? 
, . 
.
. 16.2 .
, . ,
(Interface Sensitivity).

 $
(Interface Sensitivity).
, , 
, . ,
, .
, ,
(Behavior Sensitivity). ( , 
. 
, .)

. 277

278

16

!

?


!
?

. 16.2.

,
,  , ,
(Data Sensitivity) (Context Sensitivity).
(Shared Fixture,
. 350) .
(Context Sensitivity).
,
.

(Fragile Test) .
(Indirect Testing; . , Ob
scure Test, . 230),
. "
(Eager Test; . , Assertion Roulette, . 264), 
. (Fragile Test)
, 
(. , HardtoTest
Code, . 251), "
(Test Double, . 538) ( "
, Overspecified Software).
(Fragile Test) 
. .

.

: (Interface Sensitivity)
(Interface Sensitivity) , 
 .

. 278

279

(Interface Sen
sitivity) . 
. 

(application programming interface 
API). .
, 
, . $
(Recorded Test, . 312),
1, .

. (
) .
 , 
.

,
(SUT API Encapsulation; . , Test
Utility Method, . 610)
(Interface Sensitivity).
, , 
.
(HigherLevel Language, . 95), .

.
.
(Test Utility Method), (Creation Method, . 441)
(Verification Method, . 613), 
.
(Interface Sensi
tivity) .
(, Windows DLL),
, .. 
.
, 
.
: (Behavior Sensitivity)
(Behavior Sensitivity) , 
.

. 279

280

16


.

 
.
(Behavior Sensitivity), .
.

, 

, 

,
(Context Sensitivity), ..
.
, .



(Creation Method).
$
(Custom Assertion) (Verification Method).

, .
: (Data Sensitivity)
(Data Sensitivity) , 
, .

.


:

. 280

(Standard Fix
ture, . 338);

281

(Shared Fixture) 
.

, , $
(Standard Fixture), (Fresh Fixture,
. 344), (Shared Fixture) $
(Prebuilt Fixture).


, 
, 
. 
, . 
.
, 
.

, 
,
.

. ,
.  
, .

?
. 
: " 
?"
 
.
, .

, .
XML , 
.
XML QaRun (
, Record and Playback Test),
.
,
. , $
(Fresh Fixture, . 344) .
(Prebuilt Fixture, . 454). 
(Interacting Tests),
(Shared Fixture),
(Database Sandbox, . 658) (Database

. 281

282

16

Partitioning Scheme) .
, .
, ,
. .

% , %
%
.
( ) %
.
, %
.
, (Data
Sensitivity),
, .. (Fresh Fixture). %
, (Database Parti%
tioning Scheme; . , Database Sandbox, . 658) %
, (.
?).
. 
 (Delta Assertion, . 505)
, .
.

: (Context Sensitivity)
(Context Sensitivity) , %
% %
.

. %
(Erratic Test, . 267) %
. , %
.

:

% ;

(), %
.

(Context Sensitivity)
. , %
, . %
. %
(, )

. 282

283

(Context Sensitivity),
. ,
, .  
, .
(Context Sensitivity) 

. , ,
. ,
.
, , 
.
, 
.
, . 
(Context
Sensitivity) (Erratic Test, . 267).



. 
, (Test
Stub, . 544), .
, , 
.
(Virtual Clock) [VCTP],
, .
: (Overspecified Software)

:


(Overcoupled Test)
. (Behavior
Sensitivity; . , Fragile Test, . 277)
, (Behavior Veri
fication, . 489).
(Mock Object, . 558) . 
, ,  , 
, .. 
.
, (Use the Front Door First,
. 94). , ,
.

: (Sensitive Equality)

. (Behavior Sensitivity), 
. $

. 283

284

16

(Interface Sensitivity), 
.  . 

.

: (Fragile Fixture)
(Standard Fixture) 
.
(Data Sensitivity)
(Context Sensitivity) .


(Sensitive Equality)
(Fragile Fixture) [RTC], 
. 
[ARTRP], , 
(Fragile Test)
(Recorded Test).

. 284

285

(Frequent Debugging )

.

:

(Manual Debugging)

. $
(Test Runner, . 405) 
. (
) .
, .
, 
(Frequent Debugging).

(Frequent Debugging) $
(Defect Localization, . 78) .
(. $
, Assertion Message, . 398), .
, :

,
;

(.. ), 
. ( 
(Mock Ob
ject, . 558) , 
(Mock Object).)

(
) , 
. ( ,
, 
.)
(Frequent Debugging) $
(Infrequently Run Tests; . , Production Bugs, . 303).
,
, . , 
 
, !

. 

. 285

286

16

. (Frequent Debugging) 
,
.



, 
, , (Untested Re
quirement; . , Production Bugs).
:
? , 
.
. ,

, .
$
(Frequent Debugging). 
, .. 
,  .
(Defect Localization).

. 286

287

(Manual Intervention)
.


. . 
.


, . 
(.. , Manual
Intervention), , 
.
, (Frequent Debugging, . 285) $
(High Test Maintenance Cost, . 300).
(Manual Intervention) 
.

(Manual Intervention). 
, , .

: (Manual Fixture Setup)


. ,

(Prebuilt Fixture, . 454).


. ,
,
.

, (Fully Automated
Tests). 
, .
, 
.

. 287

288

16

: (Manual Result Verification)

, , 
, .

(SelfChecking Test, . 81),
, 
.


(Test Method, . 378)
(Assertion Method, . 390).
: (Manual Event Injection)


.

.
,
.

 ,
.

.

, 
. 
, (Test Method)
. 

,
(Test Stub, . 544). ,
.


11, .

. 288

289

(Slow Tests)
, .

, 
. 
.
( , 
) .

(Slow Test) :
, .
,
.
.
(Slow Test) .

,  
,
.

, , 
.

, , 
. ,
, . 
, 
.

(Slow Test) 
(Shared Fixture,
. 350). , 
, (Erratic Test, . 267).
(Fake Object, . 565) (,
) . 
(Shared Fixture), 
, .


(Slow Test) 

.  
.

. 289

290

16

; (Test Method, . 378) 


. , 
( ) , ,
.

. , xUnit 
: setUp tearDown (Testcase Superclass, . 646).
/ , (Testcase Class)
(Test Method) .
, 
. 
.


.
.
, .

: (Slow Component Usage)


.



.

( , Back Door Manipulation, . 359),
50 , , , 
. 
.

, 
(Test Double, . 538), 
. , $
(Fake Database) 50 ! 

. 351.
: (General Fixture)

,
.

. 290

291


(General
Fixture) (Fresh
Fixture, . 344). (General Fixture) 
, (Minimal Fixture,
. 336), . ,
(Testcase Object, . 410),
 
!

(General Fixture)
(Shared Fixture)
. , 
(Erratic Test). .
,
.
: (Asynchronous Test)

;
.

(Test Method) 
. 
( , Asynchronous Code;
. , HardtoTest Code, . 251),
, . 

, ..
. .
public class RequestHandlerThreadTest extends TestCase {
private static final int TWO_SECONDS = 3000;
public void testWasInitialized_Async() = throws InterruptedException {
//
RequestHandlerThread sut = new RequestHandlerThread();
//
sut.start();
//
Thread.sleep(TWO_SECONDS);
assertTrue(sut.initializedSuccessfully());
}
public void testHandleOneRequest_Async()
throws InterruptedException {
//
RequestHandlerThread sut = new RequestHandlerThread();
sut.start();

. 291

292

16

//
enqueRequest(makeSimpleRequest());
//
Thread.sleep(TWO_SECONDS);
assertEquals(1, sut.getNumberOfRequestsCompleted());
assertResponseEquals(makeSimpleResponse(), getResponse());
}
}

, ,
 
. , 
.


.
(Extract Testable Component, . 737) $
(Humble Executable; . , Humble
Object, . 700).
: (Too Many Tests)

,
.

. 
, , , ,
.

!

! , 
. ,
(Subset Suite; . ,
Named Test Suite, . 604) 
. , .
.
.

. 351.
, 
. 

. 292

293

.
;
. $
(Tests as Documentation, . 79). ,
,
.

. 293

. 294

17

17


:
(Buggy Test) ................................................................... 296
(Developers Not Writing Tests).................. 298

(High Test Maintenance Cost) ..................................................................... 300
(Production Bugs) ...................................................... 303

. 295

296

17

(Buggy Test)
.
(Fully Automated Tests, . 81) 
. ,
?
(Buggy Test) , 
.

, 
. , ,
.
, , 
(Production Bugs, . 303). ,
, .

! , ,
( ), 
. , ,
( ), . , ,
!.  .

(Buggy Test). 
.
, .

: (Fragile Test)
(Buggy Test) , 
(Fragile Test, . 277).
: (Inter
face Sensitivity), (Behavior Sensitivity),
(Data Sensitivity) (Context Sensitivity).
. 

(Test Double, . 538) , 
.

. 296

297

: (Obscure Test)
( ,
) (Obscure Test, . 230). 
 , 
 .
, 
. , , 
. .
(Obscure Test) , 
. (Tests
as Documentation, . 79)  
(Buggy Test).

: (Hard/to/Test Code)
(Buggy Test),
( 
), 
, . $
(HardtoTest Code, . 251) $
(Indirect Testing; . , Obscure Test), , ,
(Fragile Test).
.
( 6, 
, 11, .) 
, 
(SUT API Encap
sulation; . , Test Utility Method, . 610).


(Buggy Test) .
? [TPS] , .. ,
/ , 
.


(Buggy Test). 
.
, 
. .

. 297

298

17

(Developers Not Writing Tests)


.

, . ,
(Production Bugs, . 303) :
?, : .


, .

, (test debt). 
, 
, ( , 
). ,
. ,
. .

: (Not Enough Time)


, 
. 
, .
, 
, .
, 
. ,
,
. ,
,
. , , 
, .

: (Hard/to/Test Code)
, 
(
), , 
. 
(HardtoTest
Code, . 251).

. 298

299

:
(Wrong Test Automation Strategy)

, (Fragile Test, . 277)
(Obscure Test, . 230) .
?. 
.


, (Developers Not
Writing Tests),
, . ,
, .

, , , ,
. 
, .
, 
. 

. 
. , ,
20% , 20% 
.
, , 
. (, 205
. 
.)

. 299

300

17

(High Test Maintenance Cost)


.
, .
, ,
, 
. (High Test
Maintenance Cost) ,
.

. 
.
.
,
, , , ,
.
, 
.

(Fragile Test, . 277) 


.

(Fragile Fixture) 
(
, Standard Fixture, . 338), $
(High Test Maintenance Cost).

(Erratic Test, . 267) , 


(Shared Fixture, . 350).

, 
.
. 
, ( 
). , 
, ,
, .

(High Test
Maintenance Cost) ,
5, . 

. 300

301

(Test Code Duplication, . 254) ,


.

: (Fragile Test)
,  
, (Fragile Test).
(High Test Maintenance Cost), 
, .

: (Interface Sensitivity), $
(Behavior Sensitivity), (Data Sensitivity) $
(Context Sensitivity).
(Test Double,
. 538) , 
.

: (Obscure Test)
(Obscure Test, . 230)
(High Test Maintenance Cost),
. , 
. 
. (Obscure Test)
, .
(Buggy Test, . 296).
(Obscure Test) , 
. (Tests
as Documentation, . 79)  
(Buggy Test).

: (Hard/to/Test Code)
(
) 
, . ,
, 
(Indirect Testing; . , Obscure Test)
, .
(Fragile Test).
,
. ,
. , 

(SUT API Encapsulation; .
, Test Utility Method, . 610). , (Creation Method, . 441)
,
.

. 301

302

17


(High Test Mainte
nance Cost) 
, . ,
, .
, ,
. 
,
.
, 
. ,
. 
, , 
.
, , 
, 
,
.

. 302

303

(Production Bugs)

.

, 

.

, 
, . , 
. 

.
,
. ,
. 
, .

,
(Infrequently Run Tests) (Untested
Code).
(Missing Unit Test) (Lost Test).
, , 
, .
(Untested Code)
(Production Bugs), ,
.
(Untested Requirement) , 
, , . ,
(Developers Not Writing Tests, . 298).

: (Infrequently Run Tests)

,
. ,
( , Slow Tests, . 289)
( , Buggy Test, . 296).
. 
, , 
.

. 303

304

17



, 
.
(Slow Test), ,
, (Unrepeatable Test),
(Manual Intervention, . 287)
.

(Unrepeatable Test),
(Fresh Fix
ture, . 344), .
(Slow Test), 
.
: (Lost Test)

( 
). ,
. , , 
, ,
.

(Lost Test)
(Test Method, . 378) (Testcase Class, . 401).
(AllTests Suite; . , Named
Test Suite, . 604).
( ,
) .

. 304

(Test Method) [test]


, 
(Test Discovery, . 420).


(Test Enumeration, . 425) suite.addTest,
(Test Method) (Test Suite Ob
ject, . 414).

xUnit (Test Suite Procedure)


(Test Method).

(Suite of Suites)
(Testcase Class) [Test Fixture].

305

(Test Method) ,
(Test Discovery) (,
test...).

xUnit,
(Test Method), [Ignore].

( ) , (
) .
(Lost Test), 
, , 
. , .


(Lost Test).
(Single Test Suite; .
, Named Test Suite) (Test
Method), . 
(Test Tree Explorer; .
, Test Runner, . 405) . 
(Chained Tests, . 477)  
(Interacting Tests). 
.
xUnit 
, , NUnit ,
[Ignore] (Test Method). 
, .
, (continuous integration)
,
.

, . ,
.
, 
(Test Discovery).
. 
(, Ant) 
, (,
Test). , 
.
: (Missing Unit Test)

, 
.  , 
. 
, .

. 305

306

17


(Missing Unit Test),
, 
.
, 
. 
.
, (Missing Unit Test) 
,
, .

: . , ,
, 
.  
, .
: (Untested Code)

, 
. , ,  ,
. 
. , 
timeProvider?
public String getCurrentTimeAsHtmlFragment()
throws TimeProviderEx {
Calendar currentTime;
try {
currentTime = getTimeProvider().getTime();
} catch (Exception e) {
return e.getMessage();
}
// ..


(Untested
Code) , 

.
.
.

, 
.

(Untested Code)
, 

. 306

307

(Test Stub, . 544) 


. 
, 
.

: (Untested Requirement)

,
.
,
. 
.
, 
.
(Fully Automated
Tests, . 81), .
public void testRemoveFlight() throws Exception {
//
FlightDto expectedFlightDto = createARegisteredFlight();
FlightManagementFacade facade =
new FlightManagementFacadeImpl();
//
facade.removeFlight(expectedFlightDto.getFlightNumber());
//
assertFalse("flight should not exist after being removed",
facade.flightExists(expectedFlightDto.
getFlightNumber()));
}

, 
. 
.
. .
public void removeFlight(BigDecimal flightNumber)
throws FlightBookingException {
System.out.println("removeFlight("+flightNumber+")");
dataAccess.removeFlight(flightNumber);
logMessage("CreateFlight", flightNumber); // !
}

, logMessage,
, ? 
, .

,
. 
. , , 
.

. 307

308

17


(Untested Require
ment) , 
. , 
(,
). , 
.
,
(Untested Requirement) 
, .

,
, .
,
.
,
(Behavior Verification, . 489)
(Mock Object, . 558). 
11, .
: (Neverfail Test)

, ,
.
, .

,
(Defect Localization, . 78).

,
assertTrue(aVariable, true) assertEquals(aVariable,
true) assertTrue(aVariable). , , 
: (Test Runner)
.

,
. 
(Humble Executable; .
, Humble Object, . 700).

. 308

III

. 309

. 310

18

18

:

(Recorded Test) .............................................................. 312
(Scripted Test).................................................... 319
(DataDriven Test)....................................... 322
(Test Automation Framework) ... 332

(Minimal Fixture)........................ 336
(Standard Fixture).......................... 338
(Fresh Fixture).......................................... 344
(Shared Fixture)....................................... 350

(Back Door Manipulation) ................. 359
(Layer Test)............................................................................. 368

. 311

312

18

(Recorded Test)
:
(Record and Playback
Test), (Robot User
Test),
/
(Capture/Playback Test)


?



.

. 

. .
, . 
, 
, 
.
(Recorded Test)
, .

. 312

313


,
. ,
, .
.
, .

. , 
. 
.

.
.



, (Recorded Test) 
. , 
( ),
(Scripted Test, . 319) . 
(Recorded Test), 
(Scripted Test). 
, , ; 
.
. , 
, 
, .
(Recorded Test) 
.

( , Interface Sensitivity; . ,
Fragile Test, . 277). ,
, .
, ,
( , Obscure Test, . 230). 
, . 

.
(Tests as Documentation,
. 79) ,
(Scripted Test). 
,
(HigherLevel Language, . 95) .
(Recorded Test) 
(Refactored Recorded Test).

. 313

314

18

: (Refactored Recorded Test)


, , (
record, refactor, playback ) 
, ,
, (Recorded Test) 

. / 
(Literal Value, . 718) 
, . 
,
, .
(Test Utility Method, . 610)
. 
(Refactored Recorded Test)
(HigherLevel Language) (Scripted Test).
, Mercury Interactive BPT (business process testing 
), . 
, 

.


(Recorded Test)
: , 
,
.

:
.
.
, , 
.
, 
, .
, 
(Scripted Test), 
.

:
.
 
, 
. , VBA Microsoft
Excel Excel.

. 314

315

:
,
(Recorded Test), , 
.
(DataDriven Test, . 322).
(Recorded Test) , 
, . $
(Recorded Test)
(Scripted Test), (Missing
Test)  .
.
.
, . 

C OS/2 ++ 
Windows. ,
(HigherLevel Language) , 
.
<interaction-log>
<commands>
<!-- more commands omitted >
<command seqno="2" id="Supply Create">
<field name="engineno" type="input">
<used-value>5566</used-value>
<expected></expected>
<actual status="ok"/>
</field>
<field name="direction" type="selection">
<used-value>SOUTH</used-value>
<expected>
<value>SOUTH</value>
<value>NORTH</value>
</expected>
<actual>
<value status="ok">SOUTH</value>
<value status="ok">NORTH</value>
</actual>
</field>
</command>
<!-- more commands omitted >
</commands>
</interaction-log>

.
actual .
status , actual
expected.
Fit . 
, .

. 315

316

18

,
.
. .
if (playback_is_on()) (
choice = get_choice_for_playback(dialog_id, choices_list);
) else (
choice = display_dialog(choices_list, row, col, title, key);
)
if (recording_is_on()) (
record_choice(dialog_id, choices_list, choice, key);
)

get_choice_for_playback used-value
. record_choice actual expected,
status . ,
recording_is_on() true .

:

. , 
(Recorded Test).
, Mercury Interactive QuickTest Professsional
(QTP). Expert View,
: VbScript! (
@@), ;
, .
@@
@@ GoToPageMaintainTaxonomy()
@@
Browser("Inf").Page("Inf").WebButton("Login").Click
Browser("Inf").Page("Inf_2").Check CheckPoint("Inf_2")
Browser("Inf").Page("Inf_2"").Link("TAXONOMY LINKING").Click
Browser("Inf").Page("Inf_3").Check CheckPoint("Inf_3")
Browser("Inf").Page("Inf_3").Link("MAINTAIN TAXONOMY").Click
Browser("Inf").Page("Inf_4").Check CheckPoint("Inf_4")
@@
@@ AddTerm("A","Top Level", "Top Level Definition")
@@
Browser("Inf").Page("Inf_4").Link("Add").Click
wait 4
Browser("Inf_2").Page("Inf").Check CheckPoint("Inf_5")
Browser("Inf_2").Page("Inf").WebEdit("childCodeSuffix").Set "A"
Browser("Inf_2").Page("Inf").
WebEdit("taxonomyDto.descript").Set "Top Level"
Browser("Inf_2").Page("Inf").
WebEdit("taxonomyDto.definiti").Set "Top Level Definition"
Browser("Inf_2").Page("Inf").WebButton("Save").Click
wait 4
Browser("Inf").Page("Inf_5").Check CheckPoint("Inf_5_2")

. 316

317

@@
@@ SelectTerm("[A]-Top Level")
@@
Browser("Inf").Page("Inf_5").
WebList("selectedTaxonomyCode").Select "[A]-Top Level"
@@
@@ AddTerm("B","Second Top Level", "Second Top Level Definition")
@@
Browser("Inf").Page("Inf_5").Link("Add").Click
wait 4
Browser("Inf_2").Page("Inf_2").Check CheckPoint("Inf_2_2")
infofile_;_Inform_Alberta_21.inf_;_hightlight id_;
_Browser("Inf_2").Page("Inf_2")_;_
@@
@@ ,

,
. :
(Obscure Test),
, (Interface Sensitivity),
(Fragile Test).



(High Test Maintenance Cost,
. 300) (Higher
Level Language) (Extract
Method) [Ref].

:
,
(Communicate Intent, . 95).
GoToPage_MaintainTaxonomy()
AddTerm("A","Top Level", "Top Level Definition")
SelectTerm("[A]-Top Level")
AddTerm("B","Second Top Level", "Second Top Level Definition")

, .
(Test Utility Method) .
Method GoToPage_MaintainTaxonomy()
Browser("Inf").Page("Inf").WebButton("Login").Click
Browser("Inf").Page("Inf_2").Check CheckPoint("Inf_2")
Browser("Inf").Page("Inf_2").Link("TAXONOMY LINKING").Click
Browser("Inf").Page("Inf_3").Check CheckPoint("Inf_3")
Browser("Inf").Page("Inf_3").Link("MAINTAIN TAXONOMY").Click
Browser("Inf").Page("Inf_4").Check CheckPoint("Inf_4")
End
Method AddTerm(code, name, description)
Browser("Inf").Page("Inf_4").Link("Add").Click
wait 4

. 317

318

18

Browser("Inf_2").Page("Inf").Check CheckPoint("Inf_5")
Browser("Inf_2").Page("Inf").
WebEdit("childCodeSuffix").Set code
Browser("Inf_2").Page("Inf").
WebEdit("taxonomyDto.descript").Set name
Browser("Inf_2").Page("Inf").
WebEdit("taxonomyDto.definiti").Set description
Browser("Inf_2").Page("Inf").WebButton("Save").Click
wait 4
Browser("Inf").Page("Inf_5").Check CheckPoint("Inf_5_2")
end
Method SelectTerm(path)
Browser("Inf").Page("Inf_5").
WebList("selectedTaxonomyCode").Select path
Browser("Inf").Page("Inf_5").Link("Add").Click
wait 4
end

, , 
xUnit. 
; , .


Agile Regression Testing Using Record and Playback [ARTRP]
,
.

. 318

319

(Scripted Test)

?
/
.

:

(Hand-Written Test),
(HandScripted Test),
(Programmatic Test),
(Automated Unit Test)

.
, 
,
. 
, ,
, , .
(Scripted Test) 
. 
.

. 319

320

18


,
.
(Recorded Test, . 312) ,
. ,
.


(Scripted Test)
.
, . , &
, .
; 
(Scripted Test) , &
. (Recor&
ded Test) , ,
. (Scripted Test)
. ,

(Scripted Test).
(Higher&Level Language, . 95)

(Data&Driven Test, . 322). &
(Data&Driven Test) ,
Fit. , FitNesse, &
Wiki.
Canoo WebTest.
( ,
, )
(Recorded Test) &
. &
.


(Scripted Test)
.
(Test Automation Framework, . 332),
xUnit, , &
.
(Test Method, . 378), (Test&
case Class, . 401). (Manual Intervention,
. 287)
(Self&Checking Test, . 81),
(Repeatable Test, . 81).

. 320

321

: (Scripted Test)
(Scripted Test), 
JUnit.
public void testAddLineItem_quantityOne() (
final BigDecimal BASE_PRICE = UNIT_PRICE;
final BigDecimal EXTENDED_PRICE = BASE_PRICE;
//
Customer customer = createACustomer(NO_CUST_DISCOUNT);
Invoice invoice = createInvoice(customer);
//
invoice.addItemQuantity(PRODUCT, QUAN_ONE);
//
LineItem expected =
createLineItem(QUAN_ONE, NO_CUST_DISCOUNT,
EXTENDED_PRICE, PRODUCT, invoice);
assertContainsExactlyOneLineItem(invoice, expected);
)
public void testChangeQuantity_severalQuantity() (
final int ORIGINAL_QUANTITY = 3;
final int NEW_QUANTITY = 5;
final BigDecimal BASE_PRICE =
UNIT_PRICE.multiply(new BigDecimal(NEW_QUANTITY));
final BigDecimal EXTENDED_PRICE =
BASE_PRICE.subtract(BASE_PRICE.multiply(
CUST_DISCOUNT_PC.movePointLeft(2)));
//
Customer customer = createACustomer(CUST_DISCOUNT_PC);
Invoice invoice = createInvoice(customer);
Product product = createAProduct(UNIT_PRICE);
invoice.addItemQuantity(product, ORIGINAL_QUANTITY);
//
invoice.changeQuantityForProduct(product, NEW_QUANTITY);
//
LineItem expected = createLineItem(NEW_QUANTITY,
CUST_DISCOUNT_PC, EXTENDED_PRICE, PRODUCT, invoice);
assertContainsExactlyOneLineItem(invoice, expected);
)



 , Tcl.


(Scripted Test)
.
[TDDBE] [TDDAPG].

. 321

322

18

(Data/Driven Test)

?
, , .
,
.

2
data

, 
, , . ,

, .
.
, ;
,
.
(DataDriven Test)
, .


(DataDriven Test),
.
.
. ,
(FourPhase Test, . 387).
.

. 322

323

. 
( , ..) 
, . ,
. , 
, 
. ,
.
, , 
. Fit
(DataDriven Test).


(DataDriven Test) , 
(Recorded Test, . 312) (Scripted Test,
. 319).
(Scripted Test), (Recorded Test) 
(DataDriven Test).
(DataDriven Test) 
. ,
,
.
(DataDriven Test)
(Scripted Test),

.
(Parameterized Test, . 618), 
(DataDriven Test). , 
, $
(Incremental Tabular Test).
.
.
(DataDriven Test)
: ,
. 
(Scripted Test), 
. 
,
1. 

(DataDriven Test); 
.

, 
, . [RDb].

. 323

324

18


, (
xUnit) (DataDriven
Test).
(Fit)
(QTP). 
xUnit.
$
(Test Automation Framework, . 332), 
. , : .
,

.
,
. ,
, FitNesse.
,
.
, ,
, . 
,
. 
, 
,
, 
. . 

, 
.

:
(Data/Driven Test Framework) (Fit)

(DataDriven Test) 
. Fit 
. Fit
, 
, 
. Fit : 
. Fit $
(DataDriven Test),
. 
. 
. ,
. ,

. 324

325

. , 
, . , 
Fit , 
.
, .
(Assertion Method, . 390) xUnit,
Fit 
, . 
. , 
, .
.
Fit .


.

, .

.
Fit / ,
.

, 
.

Fit xUnit?
Fit.

. 325

,
Fit.
; , , 
. ,
Fit ,
( ,
).


. (
. 
.) 

( ).
, (Test Method, . 378).
, 
,
, .
Fit.

Fit , 
xUnit. 

. 

326

18

Fit
. ,
, .
, . 
xUnit , Fit.
.

: xUnit (Naive xUnit Test Interpreter)


(DataDriven Test),
xUnit
(Scripted Test),
(Test Method) , 
. $
(Parametrized Test)
(Tabular Test). (Tabular Test),
(Testcase
Object, . 410) .
.

(DataDriven Test) 
. , (Parame
trized Test) (DataDriven Test) 
.

(DataDriven Test)
. $
(Defect Localization, . 78). xUnit 
.

,
.

try/catch
, . 
. 
(, 1, 3 6 ...).

,
.
(Parametrized Test) .

: (Test Suite Object Generator)


,
xUnit (Naive xUnit Test Interpreter), suite $
(Test Suite Factory; . , Test Enumeration, . 425)
(Test Suite Object, . 414), 
(Test Discovery, . 420). 
(DataDriven Test)

. 326

327

(Testcase Object), 
. (
(Test Method Discovery), xUnit. 
, (Test Method) 
.) ,
(Parametrized Test) .
(DataDriven Test) 
(Testcase Object). (Test Runner,
. 405) ,
.

: (Test Suite Object Simulator)


(Test Suite Object)
(Testcase Object), , . 
. 
, (Parametrized Test), 
. (Testcase
Object) , $
(Test Runner). ,
,
(Test Runner) (, ,
$
(Graphical Test Tree Explorer) ..).


, .
def test_extref
sourceXml = "<extref id='abc' />"
expectedHtml = "<a href='abc.html'>abc</a>"
generateAndVerifyHtml(sourceXml,expectedHtml,"<extref>")
end
def test_testterm_normal
sourceXml = "<testterm id='abc'/>"
expectedHtml = "<a href='abc.html'>abc</a>"
generateAndVerifyHtml(sourceXml,expectedHtml,"<testterm>")
end
def test_testterm_plural
sourceXml = "<testterms id='abc'/>"
expectedHtml = "<a href='abc.html'>abcs</a>"
generateAndVerifyHtml(sourceXml,expectedHtml,"<plural>")
end

$
(Parametrized Test).
def generateAndVerifyHtml(sourceXml, expectedHtml,
message, &block)
mockFile = MockFile.new
sourceXml.delete!("\t")

. 327

328

18

@handler = setupHandler(sourceXml, mockFile )


block.call unless block == nil
@handler.printBodyContents
actual_html = mockFile.output
assert_equal_html(expectedHtml,
actual_html,
message + "html output")
actual_html
end

, 
.


, $
(Parametrized Test) (Data
Driven Test) .
, , 
. $
(Parametrized Test), xUnit
.

: (Data/Driven Test) xUnit


XML
XML.
test, :

, ,
(, crossref);

, ;
sourceXml;

HTML, ( expectedHtml).

testsuite.
<testsuite id="CrossRefHandlerTest">
<test id="extref">
<action>crossref</action>
<sourceXml>
<extref id='abc'/>
</sourceXml>
<expectedHtml>
<a href='abc.html'>abc</a>
</expectedHtml>
</test>
<test id="TestTerm">
<action>crossref</action>
<sourceXml>
<testterm id='abc'/>
</sourceXml>

. 328

329

<expectedHtml>
<a href='abc.html'>abc</a>
</expectedHtml>
</test>
<test id="TestTerm Plural">
<action>crossref</action>
<sourceXml>
<testterms id='abc'/>
</sourceXml>
<expectedHtml>
<a href='abc.html'>abcs</a>
</expectedHtml>
</test>
</testsuite>

XML ,
.
,
(Parametrized Test). XML 
, . , XML 
.
CSV, XML.

: (Data/Driven Test) xUnit


CSV
CSV 
.
ID,
Action,
SourceXml,
ExpectedHtml
Extref,crossref,<extref id='abc'/>,<a href='abc.html'>abc</a>
TTerm,crossref,<testterm id='abc'/>,<a href='abc.html'>abc</a>
TTerms,crossref,<testterms id='abc'/>,<a href='abc.html'>abcs</a>

,
(Parametrized Test). 
CSV split Ruby
.
def test_crossref
executeDataDrivenTest "CrossrefHandlerTest.txt"
end
def executeDataDrivenTest filename
dataFile = File.open(filename)
dataFile.each_line do | line |
desc, action, part2 = line.split(",")
sourceXml, expectedHtml, leftOver = part2.split(",")
if "crossref"==action.strip
generateAndVerifyHtml sourceXml, expectedHtml, desc
else # new "verbs" go before here as elsif's
report_error("unknown action" + action.strip)
end
end
end

. 329

330

18

generateAndVerifyHtml
,
. 
,
(Defect Localization).

: (Data/Driven Test)
Fit
, 
Fit id,
action, source XML expected Html(), 
Web HTML (. 18.1).

18.1. (Data/Driven Test) Fit


com.xunitpatterns.fit.CrossrefHandlerFixture
id

action

source XML

extref

crossref <extref id='abc' /> <a


href='abc.html'>?abc?</a>

TestTerm

crossref <testterm id='abcd' <a


/>
href='abc.html'>?abc?</a>

TestTermPlural crossref <testterm id='abc'


suffix="s"/>

expected Html()

<a
href='abc.html'?abcs?</a>

Fit 
.
public class CrossrefHandlerFixture extends ColumnFixture
//
public String id;
public String action;
public String sourceXML;
//
public String expectedHtml() (
return generateHtml(sourceXML);
)
)

Fit 
.
(, id source
XML). , (), ,
.
. 18.2. 
.

. 330

331

18.2. Fit
com.xunitpatterns.fit.CrossrefHandlerFixture
id

action

source XML

extref

crossref <extref id='abc' /> <a


href='abc.html'>?abc?</a>

TestTerm

crossref <testterm id='abcd' <a


href='abc.html'>?abc?</a>
/>

TestTermPlural crossref <testterm id='abc'


suffix="s"/>

expected Html()

<a
href='abc.html'?abcs?</a>
<a href='abc.html'?abc?</a>

. 331

332

18

(Test Automation Framework)


?
,
, .

,
.
, 
, , .
(Test Automation Framework),

(Fully Automated Tests, . 81).


,
. ,
,
, ,
. 
, .

. 332

333


(Fully Automated Tests), 
, 
, .
, , .
(test fixture), 
.
(Fully Auto
mated Tests) . 
,
; 
. ,
, 
, xUnit.
.
, 
.
(Test Code Duplication, . 254) $
(Obscure Test, . 230).
.


(Test
Automation Framework) ,
. :
 (Scripted Test,
. 319). xUnit
(DataDriven Test, . 322).

: /

.
.
, 
, 
. 
: ,
,
, (Recorded
Test, . 312). 
,
. 
.

. 333

334

18

: xUnit
xUnit,
(HandScripted
Test). xUnit ( )
. xUnit 
.
(Test Runner, . 405), , 
. (Testcase
Object, . 410), (Test Suite Object, . 414)
(Test Method, . 378). 
xUnit (Assertion
Method, . 390), (Test Method)
.

:
,
, .
.
,

. . 
Fit,

, , .

:
$
(Test Automation Framework) . 
, (Recorded Test), $
(Scripted Test) (DataDriven Test).


$
(Test Automation Framework) JUnit (Java), SUnit (Smalltalk), CppUnit
(C++), NUnit ( .NET), runit (Ruby), PyUnit (Python) VbUnit
(Visual Basic).
http://xprogramming.com,
(, HttpUnit, Cactus ..).
,
Fit, Canoo WebTest Watir. 
QTP, BPT eCATT.
[TDDBE] 
(Test Automation
Framework) Python. 

. 334

335

,
, .
,
.

. 335

336

18

(Minimal Fixture)
:

(Minimal Context)

$
?


.

setUp
test_1
test_2

test_n

.

. , .


(Minimal Fixture)
(Tests as Documentation, . 79)
(Slow Tests, . 289). (Minimal Fix
ture) , , 
. (Fresh
Fixture, . 344), (Shared Fixture, . 350),

. .
,
.

. 336

337



, . 
, ,
.
(Minimal Fixture) 
, .
.

, .. 
. ,
.

,
.

.
, , . ,

( , ,  
).
(Obscure Test, . 230).
:
$ (Dummy Object, . 730) $
(Entity Chain Snipping; . , Test Stub, . 544).
, 
.
, ,
: ?, 
, ?, $
(Obscure Test), (Mystery Guest)?
, . 
.
,
(Test Method), 
. (Creation Method,
. 441). 
(Creation Method),
. ,
. ,
( 
).
.
. 
(One Bad Attribute; .
, Derived Value, . 722),
(Creation Method)
 .

. 337

338

18

(Standard Fixture)
:

(Standard Context)

T eardo

wn


?

.


. 
. (Standard Fixture) 

. 
.


(Standard Fixture) 
, . 
(Standard Fixture), 
, 
.
(Standard Fixture) 
. 
.
(Standard Fixture) 
(Fresh Fixture, . 344) $
(Shared Fixture, . 350). (Shared Fixture) 
(Standard Fixture).

. 338

339

, (Standard Fixture)
, 
.
(Standard Fixture) , 

.


,
:  ? 
.
,
.
, setUp
(Testcase Class per Fixture, . 639).

(Standard Fixture), .
?
(Standard Fixture) 
. $
(Standard Fixture), 
. (
),
.
. 
(Standard
Fixture) . 

(Shared Fixture).
xUnit (Standard
Fixture) , $
(Minimal Fixture, . 336) ,
: (General Fixture; . $
, Obscure Test, . 230).
(Implicit Setup, . 449) $
(Testcase Class per Fixture), (Test
Method, . 378) .
, . 
(Standard Fixture) 
.
(Fragile Fixture; . , Fragile
Test, . 277), , 
. , 
(Mystery Guest),
 
, , 

. 339

340

18

(Standard Fixture) 
.
(Standard Fixture)
, (Minimal Fixture), 
. (Fresh Fixture)
(Testcase Object, . 410) (Slow
Tests, . 289), (.
, 
).


Object Mentor (www.objectmentor.com) .
.
, .
, :
;
;
;
;
( )
.
. '
, , .
, , '
.

'
(Minimal Fixture), 
, .


, (Standard Fixture) 
(Fresh Fixture) '
(Shared Fixture),
(Implicit Setup) (Delegated Setup, . 437).
( (Inline Setup, . 434) 
 (Standard Fixture)
(Test Method).)
(Fresh Fixture) '
(Test Utility Method, . 610) ( ),
(Standard Fixture).
,
. (Implicit

. 340

341

Setup), xUnit,
setUp.
(Standard Fixture) $
(Shared Fixture)
, $
(Suite Fixture Setup, . 465), (Lazy Setup, . 460) $
(Setup Decorator, . 471).


, $
(Standard Fixture)  
. , 
(Minimal Fixture)

(Standard Fixture),
(Testcase Class per Fixture). , 
.
(Creation Method, . 441) $
(Fresh Fixture) .
public void testGetFlightsByFromAirport_OneOutboundFlight_c()
throws Exception (
FlightDto outboundFlight = createOneOutboundFlightDto();
//
List flightsAtOrigin =
facade.getFlightsByOriginAirport(
outboundFlight.getOriginAirportId());
//
assertOnly1FlightInDtoList("Flights at origin",
outboundFlight,
flightsAtOrigin);
)
public void testGetFlightsByFromAirport_TwoOutboundFlights_c()
throws Exception (
FlightDto[] outboundFlights =
createTwoOutboundFlightsFromOneAirport();
//
List flightsAtOrigin = facade.getFlightsByOriginAirport(
outboundFlights[0].getOriginAirportId());
//
assertExactly2FlightsInDtoList("Flights at origin",
outboundFlights,
flightsAtOrigin);
)

(Delegated Setup) 
(Minimal Fixture)
. 
, $
(Obscure Test).

. 341

342

18


$
(Standard Fixture) ,
.
(Standard Fixture) ,
(Test Method) .
, (Minimal Fixture) 
. ,
.

(Finder Method; .
, Test Utility Method),
(Standard Fixture). 
. 
(Test Method)
(Creation Method) .

. , (
) (Finder Method), 
. (Finder Method) , 
(Standard Fixture).

: (Standard Fixture)
,
(Standard Fixture).
public void testGetFlightsByFromAirport_OneOutboundFlight()
throws Exception (
setupStandardAirportsAndFlights();
FlightDto outboundFlight = findOneOutboundFlight();
//
List flightsAtOrigin = facade.getFlightsByOriginAirport(
outboundFlight.getOriginAirportId());
//
assertOnly1FlightInDtoList("Flights at origin",
outboundFlight,
flightsAtOrigin);
)
public void testGetFlightsByFromAirport_TwoOutboundFlights()
throws Exception (
setupStandardAirportsAndFlights();
FlightDto[] outboundFlights =
findTwoOutboundFlightsFromOneAirport();
//
List flightsAtOrigin = facade.getFlightsByOriginAirport(
outboundFlights[0].getOriginAirportId());
//
assertExactly2FlightsInDtoList("Flights at origin",
outboundFlights,
flightsAtOrigin);
)

. 342

343

(Standard Fixture)
,
(Fresh Fixture)
(Creation Method) (Standard Fixture)
(.. , Delegated Setup).
setUp, 
(Implicit Setup). 
,
(Shared Fixture).

. 343

344

18

(Fresh Fixture)
:
(Fresh Context),
(Private Fixture)


?


.

SUT

.
. 

.
(Fresh Fixture),
(Erratic Test, . 267)
, , (Tests as
Documentation, . 79).


,
.
,  . 
. ,
.1

. 344

345


(Fresh Fixture) , 
,
(Erratic Test), (Lonely Test)
(Interacting Tests). (Fresh
Fixture)  ,
(Shared Fixture) $
(Immutable Shared Fixture). , $
(Database Partitioning Scheme)
(Database Sandbox, . 658)
(Fresh Fixture),
.


(Fresh Fixture), 
.
(. 18.1).
, $
(Fresh Fixture) .
, 
. .

. 18.1. . ,
( ),

. 345

346

18


, 
(Test Method, . 378). 
, 
, .
. 
, .

( , Unrepeatable Test). 
,
(Erratic Test), (Interacting Tests)
(Test Run War).
,
. , 
(Test Method).

, , , 
.
(Test Method). ,
.
(Testcase Ob
ject) , xUnit
(Testcase Object) 2. , 

, , ,

(Fresh Fixture).
3, ,
. 
.



. .
(Inline Setup, . 434) 
.
(Delegated Setup, . 437),
(Testcase Class per Class, . 627) $
2

xUnit (Test Method) 


(Testcase Object, . 410). 
.
, ,
.
. 411.
3 . 340.

. 346

347

(Testcase Class per Feature, . 633).


(Testcase Class per Fixture, . 639),
(Implicit Setup, . 449).

: (Transient Fresh Fixture)


,

. 
(GarbageCollected Teardown, . 518), 
.
, (Standard Fixture,
. 338) (Fresh Fixture), 
(Test Method). 
, . 
, (Implicit Setup),
$
(Testcase Class per Fixture).

: (Persistent Fresh Fixture)


(Persistent Fresh
Fixture), , , .
(Inline Teardown,
. 527), (Implicit Teardown, . 533), (Delegated Tear
down, . 529) (Automated Teardown, . 521). 
, .
,
(Distinct Generated Value). 
(Database Partitioning
Scheme), .
(Resource Leakage)
. ,
, $
(Unrepeatable Test) (Interacting Tests).
, :
(Slow Tests, . 289).

, ,
. , ,
: (Keep Tests
Independent, . 96). (Shared
Fixture) (Interacting Tests)
(Unrepeatable Test) ( , ).
, !

. 347

348

18


(Shared Fixture).
static Flight flight;
public void setUp() (
if (flight == null) ( // ""
Airport departAirport = new Airport("Calgary", "YYC");
Airport destAirport = new Airport("Toronto", "YYZ");
flight = new Flight(flightNumber,
departAirport,
destAirport);
)
)
public void testGetStatus_inital_S() (
//
//
assertEquals(FlightState.PROPOSED, flight.getStatus());
//
)
public void testGetStatus_cancelled() (
//
flight.cancel();
//
assertEquals(FlightState.CANCELLED, flight.getStatus());
//
)

, ,
(Shared Fixture),
(Prebuilt
Fixture, . 454). .


, (Shared Fixture) (
, ) 
(Fresh Fixture). %
(Standard Fixture) ( , %
). 
(Minimal Fixture, . 336)
(Minimize Data, . 739).
, (Test Method)

(Testcase Class per Fixture) (Implicit Setup). %
(Standard Fixture) %
, .

: (Fresh Fixture)

(Fresh Fixture) (Interacting Tests).

. 348

349

public void testGetStatus_inital() (


//
Flight flight = createAnonymousFlight();
//
assertEquals(FlightState.PROPOSED, flight.getStatus());
//
//

)
public void testGetStatus_cancelled2() (
//
Flight flight = createAnonymousCancelledFlight();
//
assertEquals(FlightState.CANCELLED, flight.getStatus());
//
//

)

(Anonymous Crea
tion Method; . , Creation Method, . 441) 
Flight .

. 349

350

18

(Shared Fixture)
:
(Shared
Context),
(Leftover Fixture),
(Reused
Fixture),
(Stale Fixture)


? ?

.


. (Fresh Fixture,
. 344) ,
, .
, 
.


:
(Standard Fixture, . 338),
(Testcase Object, . 410).
.
(Prebuilt Fixture),
, 
.
.
.
,
, 
.

. 350

351


(Shared Fixture)
, 
.
(Shared Fixture) .
(Erratic Test, . 267),
.
, ,
(Minimal Fixture, . 336),
. 
(Fragile Fixture) , 
.
(Shared Fixture) 
(Obscure Test, . 230), 
.
(Finder Method; . , Test Utility Method,
. 610) , 
.

(Shared Fixture).

(Shared Fixture). ?

: (Slow Test)
,
(Fresh Fixture) . ,
,
(Slow Test, . 289).
, 
. , 

, , ,
.
,
.
(Slow Test)
.


(Slow Tests, . 289) 
(Shared Fixture, . 350).
. ,
.

. 351

352

18



, . $
(Shared Fixture). $
(Interacting Tests) (Test Run War) $
(Fresh Fixture, . 344).
, . 

.
15 , .
SQL (data
access layer). ,
(Fake Database; . $
, Fake Object, . 565).
. " "
.
.
.
, . 
50 , . ,
, 10 , 10 .
,
.

( 
).


' (50 ,
) .
, , $
(Slow Tests), : 2005
8 8
. . .
6700 . $
, .
2004 Toplink.
2004 , $
Java (HSQL), . $
.
2004 ,
Toplink . .
2005 $
, .
, .
2005 , $
. .

. 352

353

2005
Cruise Control. $
15$$20%.
2004 Cruise Control $
. $
.
, $
, $
. ,
5 . 8 , .
,
$$$$ , ,
, (, $
Master Data GUI, ,
Cruise Control, ).
(
) .
( ) $
. Opteron,
( , $
). .
UNIX rsync Eclipse
.
.
MyTestSuite.java, $
. $
.
,
.
( Condor) ,
$$$$ ( 11 )
( 20), , $
. rsync, $
.
, , $
, $
. , $
.


:
http://FasterTestsPaper.gerardmeszaros.com.

: (Incremental Tests)
(Shared Fixture)
,
. 

. 353

354

18

. 
.
(Eager Test; . , Assertion Rou
lette, . 264). 
(Test Method, . 378),
(Shared Fixture). $
(Chained Tests, . 477). 
: 
, .
(Fully
Automated Tests, . 81): ,
, .
, , 
, 
( 
).
.
1.
(Test Method)
(Guard Assertion, . 510),

. ,
 , 
.


(Shared Fixture) 
:
(Shared Fixture) () ?
(Shared Fixture) 
,
. ,
, . 
,
, ,
(Prebuilt Fixture, . 454), .
(, )
,
(Fragile Fixture). 
.

. 354

355

: (PerRun Fixture)
(Shared Fixture) 
(PerRun Fixture),
. 
, .
.
(, ), .
(PerRun Fixture) 
(Testcase Class, . 401),

(Lazy Setup, . 460) 
(Suite Fixture Setup, . 465)
. 
(Testcase Class),
(Setup Decorator, . 471) setUp tearDown,
(Test Fixture Registry) ( 
) .

: (Immutable Shared Fixture)


(Shared Fixture)
(Erratic Test), . ,
(Shared Fixture) (Inde
pendent Tests, . 96). , 
(Shared Fixture) . 
. ,
, .. (Im
mutable Shared Fixture). , 
.
(Fresh Fixture).

(Immutable Shared Fixture) , .
:
(Immutable
Shared Fixture), , 
. (Immutable Shared
Fixture) , 
. 
(Fresh Fixture) (Immutable
Shared Fixture).


(Testcase
Class) (Implicit Setup, . 449). 
(Test Method) 
.

. 355

356

18

public void testGetFlightsByFromAirport_OneOutboundFlight()


throws Exception (
setupStandardAirportsAndFlights();
FlightDto outboundFlight = findOneOutboundFlight();
//
List flightsAtOrigin = facade.getFlightsByOriginAirport(
outboundFlight.getOriginAirportId());
//
assertOnly1FlightInDtoList("Flights at origin",
outboundFlight,
flightsAtOrigin);
)
public void testGetFlightsByFromAirport_TwoOutboundFlights()
throws Exception (
setupStandardAirportsAndFlights();
FlightDto[] outboundFlights =
findTwoOutboundFlightsFromOneAirport();
//
List flightsAtOrigin = facade.getFlightsByOriginAirport(
outboundFlights[0].getOriginAirportId());
//
assertExactly2FlightsInDtoList("Flights at origin",
outboundFlights,
flightsAtOrigin);
)

, setUp $
(Test Method).
,
(Slow Test).


(Testcase Class) $
(Standard Fixture) (Shared Fixture)
.
, (Testcase Object).
, 
(Test Method).
(Lazy Setup). ,
(Shared Fixture), $
(Setup Decorator) (Suite
Fixture Setup).

: (Shared Fixture)
(Shared Fixture)
(Lazy Setup).
protected void setUp() throws Exception
if (sharedFixtureInitialized) (
return;
)

. 356

357

facade = new FlightMgmtFacadeImpl();


setupStandardAirportsAndFlights();
sharedFixtureInitialized = true;
)
protected void tearDown() throws Exception (
// , ,
//
)

[SBPP] setUp $
(Shared Fixture) , 
. (Test Method) 
(Finder Method)
.
public void testGetFlightsByFromAirport_OneOutboundFlight()
throws Exception (
FlightDto outboundFlight = findOneOutboundFlight();
//
List flightsAtOrigin = facade.getFlightsByOriginAirport(
outboundFlight.getOriginAirportId());
//
assertOnly1FlightInDtoList("Flights at origin",
outboundFlight,
flightsAtOrigin);
)
public void testGetFlightsByFromAirport_TwoOutboundFlights()
throws Exception (
FlightDto[] outboundFlights =
findTwoOutboundFlightsFromOneAirport();
//
List flightsAtOrigin = facade.getFlightsByOriginAirport(
outboundFlights[0].getOriginAirportId());
//
assertExactly2FlightsInDtoList("Flights at origin",
outboundFlights,
flightsAtOrigin);
)

(Test Utility Method),


setupStandardAirportsAndFlights, , 
. ,
, , $
(Test Method) 
, (Test Utility Method).

:
(Immutable Shared Fixture)
(Shared Fixture).
public void testCancel_proposed_p()throws Exception (
//
BigDecimal proposedFlightId = findProposedFlight();

. 357

358

18

//
facade.cancelFlight(proposedFlightId);
//
try (
assertEquals(FlightState.CANCELLED,
facade.findFlightById(proposedFlightId));
) finally (
//
// ,
// !
facade.overrideStatus(proposedFlightId,
FlightState.PROPOSED);
)
)

, , ..
. , 

(Immutable Shared Fixture). , 
. $
(Fresh Fixture).
, $
(Immutable Shared Fixture).
mutableFlight.
public void testCancel_proposed() throws Exception (
//
BigDecimal mutableFlightId =
createFlightBetweenInsigificantAirports();
//
facade.cancelFlight(mutableFlightId);
//
assertEquals(FlightState.CANCELLED,
facade.findFlightById(mutableFlightId));
//
// ,
// .
//
// .
)

, , 
(Distinct Generated
Value)  . , 
dummyAirport1
dummyAirport2. , 
.

. 358

359

(Back Door Manipulation)



?


(, ).

:

(Layer-Crossing Test)

Setup

Ex
ercise

SUT

Data
Data
Fixture

Ve r ify

Te
ardo wn

( )
( ). 

. .
(Back Door Ma
nipulation) / .


.
, ,
.
,
. (State Verification,
. 484) .


.

. 
,
, , Registry,
. 

. 359

360

18

, (
, TestSpecific Subclass, . 591), 
, . ,
$
(Test Double, . 539),
.


(Back Door Manipulation)
, . 

. $
(Test Utility Method, . 610) 
. ,
(Fragile Test, . 277).
. ,
(Back Door Manipulation)
(Test Utility Method).
, (Back Door Manipulation)
(Obscure Test, . 230),
. ,
(Testcase Class, . 401),
, (Finder Method) 
.
(Back Door Manipulation) 
, ,
. , 
. 
, . , 
.
, 
, ,
.
(LayerCrossing Test),
(Back Door Manipulation)
. (Back
Door Setup) . 
,
(Back Door Verification) .

: (Back Door Setup)


(Back Door Manipu
lation) . 
,
.

. 360

361



. , 
: (Back Door Setup)
, , 
.
 
. , 
.

,
, .
(Back Door Setup) 
, 
( ) .
(Back Door Setup) 
.

: (Back Door Verification)


(State Verification) 
.
( , ) . 
. 
SQL ,
.
, (Back Door Manipulation)
.
(, )
,
(Back Door Manipulation).

, 
. .
,

(,
).
(LayerCrossing Test),
. 

.

: (Back Door Teardown)


(Back Door Manipulation)
(Fresh Fixture, . 344),
. ,

. 361

362

18

, (Table Truncation Teardown,


. 668) (Transaction Rollback Teardow n, . 675).


(Back Door Manipulation)
.
,
(Back Door Manipulation). 
, .

: (Database Population Script)


, 
, (Back Door
Manipulation) 
. 
, , 
. 

, .
,
.
(Database Population Script) , 
,  
. ( 6,
.)
(Database Population Script)
,
, ,
. .

: (Data Loader)
(Data Loader) ,
.
(Database Population Script) , , 
. 
(Data Loader), 
.
,
, (Data Loader)
, . 
, , 
, (, 
). 
 ,
(Data Loader) . 

. 362

363

 
.
(.. 
), (Data Loader) , 
. 
:

,
;

,
.

,
.
XML. DbUnit
JUnit, (Data Loader)
.

: (Database Extraction Script)


,
,
(Back Door Verification).


.

: (Data Retriever)
(Data Retriever) (Data Loader),
(Back
Door Verification). , ,
. DbUnit
JUnit, (Data Retriever) .

: (Test Double)


. , 
(Back Door Manipulation)
(Test Double). 
(Fake Object, . 565), 
, 
.
. 
(Configurable Test Double, . 571),
(Mock Object, . 558) (Test Stub, . 544).

. 363

364

18

(Obscure
Test), (Test Double)
(Test Method, . 378).
(Behavior Verification, . 489)
, 
(LayerCrossing Test), 
(Test Spy, . 552) (Mock
Object). , 
(
),
(Test Stub).


, ,
.
, , 
, 
, .
. 
,
.
public void testRemoveFlight() throws Exception (
//
FlightDto expectedFlightDto = createARegisteredFlight();
FlightManagementFacade facade = new FlightManagementFacadeImpl();
//
facade.removeFlight(expectedFlightDto.getFlightNumber());
//
assertFalse("flight should not exist after being removed",
facade.flightExists(expectedFlightDto.
getFlightNumber()));
)


(Back
Door Verification),
. , 
, (Test Spy), 
.

:
(Test Spy)
,
(Test Spy) .

. 364

365

public void testRemoveFlightLogging_recordingTestStub()


throws Exception (
//
FlightDto expectedFlightDto = createAnUnregFlight();
FlightManagementFacade facade =
new FlightManagementFacadeImpl();
// (Test Double)
AuditLogSpy logSpy = new AuditLogSpy();
facade.setAuditLog(logSpy);
//
facade.removeFlight(expectedFlightDto.getFlightNumber());
//
assertEquals("number of calls", 1,
logSpy.getNumberOfCalls());
assertEquals("action code",
Helper.REMOVE_FLIGHT_ACTION_CODE,
logSpy.getActionCode());
assertEquals("date", helper.getTodaysDateWithoutTime(),
logSpy.getDate());
assertEquals("user", Helper.TEST_USER_NAME,
logSpy.getUser());
assertEquals("detail",
expectedFlightDto.getFlightNumber(),
logSpy.getDetail());
)

,
, $
(Delta Assertion, . 505) .

:

.
EmailSubscription .
, 
. .
static final String
TABLE_NAME = "EmailSubscription";
static final BigDecimal RECORD_ID = new BigDecimal("111");
static final String LOGIN_ID = "Bob";
static final String EMAIL_ID = "bob@foo.com";
public void setUp() throws Exception (
String xmlString =
"<?xml version='1.0' encoding='UTF-8'?>" +
"<dataset>" +
"
<" + TABLE_NAME +
"
EmailSubscriptionId='" + RECORD_ID + "'" +
"
UserLoginId='" + LOGIN_ID + "'" +
"
EmailAddress='" + EMAIL_ID + "'" +
"
RecordVersionNum='62' " +
"
CreateByUserId='MappingTest' " +
"
CreateDateTime='2004-03-01 00:00:00.0' " +
"
LastModByUserId='MappingTest' " +
"
LastModDateTime='2004-03-01 00:00:00.0'/>" +

. 365

366

18

"</dataset>";
insertRowsIntoDatabase(xmlString);
)
public void testRead_Login() throws Exception (
//
EmailSubscription subs =
EmailSubscription.findInstanceWithId(RECORD_ID);
//
assertNotNull("Email Subscription", subs);
assertEquals("User Name", LOGIN_ID, subs.getUserName());
)
public void testRead_Email() throws Exception (
//
EmailSubscription subs =
EmailSubscription.findInstanceWithId(RECORD_ID);
//
assertNotNull("Email Subscription", subs);
assertEquals("Email Address",
EMAIL_ID,
subs.getEmailAddress());
)

XML (Testcase
Class), (Mystery Guest),
, ( 
, Inline Resource,
. 738). , 
, DbUnit
(Table Trun
cation Teardown). (Test Utility
Method) .
private void insertRowsIntoDatabase(String xmlString)
throws Exception (
IDataSet dataSet = new FlatXmlDataSet(new StringReader(xmlString));
DatabaseOperation.CLEAN_INSERT.
execute(getDbConnection(), dataSet);
)
public void tearDown() throws Exception (
emptyTable(TABLE_NAME);
)
public void emptyTable(String tableName) throws Exception (
IDataSet dataSet = new DefaultDataSet(new DefaultTable(tableName));
DatabaseOperation.DELETE_ALL.
execute(getDbConnection(), dataSet);
)

, DbUnit, ,
xUnit.
:
(Eager Test; . , Assertion Roulette, . 264) 
. 
(Slow Tests, . 289),

. 366

367

. (Lazy Setup, . 460) $


(Suite Fixture Setup, . 465),
,
(Shared Fixture, . 350) . (
, .)



?.

?

" " (Back Door Setup; . , Back Door Manipu
lation, . 359).
(Back Door Verification). , 
,
?
,
. ( 
) .
Powerbuilder,
. .
. ,
, 
.
, ,
.
,
. , .

.
,
. 
,
.
.
? ,
(, Crystal Reports)
,
. , (DTS SQL) 
, .
1234

1
22
3
4

. 367

368

18

(Layer Test)
:
(Single Layer
Test),
(Testing by Layers), (Layered Test)

,
?

.

_1

_n

testMethod_1

testMethod_1

testMethod_2

testMethod_2


. $
(Indirect Testing; . , Obscure Test, . 230).
,
. 
( ),  
. 
.

, .


, 

5.  , 
5

.
.

. 368

369


.
. ,
. , n
n+1, n1
(Test Double, . 538).


(Layer Test) 
,
. ,
. 
, .
,
.
.
(Layer Test)
, 
. 
. , 
. (Layer Test) 
.
(Layer Test) 
, 
.
; ,
(Layer Test).
, 
.

: (Presentation Layer Test)


. 
(,
, Web,
Web, Web).
, 
. (
!)

.
(Humble Dialog; . , Humble Object, . 700) 
.
. $
(Humble Dialog) ,
 . 

. 369

370

18

, ..
.

: (Service Layer Test)


(Service Layer)
.  
,
(Indirect Testing) $
(Sensitive Equality; . , Fragile Test, . 277). ,
(Fragile Test)
(High Test Maintenance Cost, . 300).
.
(Slow Tests, . 289) 
(Fake Database; . ,
Fake Object, . 565) .

. , 
http://alistair.cockburn.us [WWW].
. 
( ), 
Microsoft Excel
.

: (Persistence Layer Test)


. 
,
. :
.
, 
! ,

.
,
,
. 
(Back Door
Manipulation).

: (Subcutaneous Test)
(Subcutaneous Test)
(Layer Test). 
. 
, , , 
. (Subcutaneous Test) 
, (Service Layer Test),

. 370

371

. (Subcutaneous Test)
. 
6,
.
.

: (Component Test)
(Component Test)
(Layer Test), ,
. (Component Test)

,
.


(Layer Test) ,
. .
. 
(, (Fake
Object) n1). n 
.


(Layer Test) 
, $
(Simple Success Test; . , Test Method, . 378). 
,
.
(Fake Object). ,

(Slow Test).


(Test Stub, . 544),

(, 0001 , 0002
, 0003 ).

. $
(Expected Exception Test) ,

, ,
.

. 371

372

18

7. $
(Back Door Manipulation) .


,
(Mock Object, . 558) (Test
Spy, . 552) .

.
(Back Door Manipulation) 
.



 . 
 
.
private final int LEGAL_CONN_MINS_SAME = 30;
public void testAnalyze_sameAirline_LessThanConnectionLimit()
throws Exception (
//
FlightConnection illegalConn =
createSameAirlineConn(LEGAL_CONN_MINS_SAME - 1);
//
FlightConnectionAnalyzerImpl sut =
new FlightConnectionAnalyzerImpl();
String actualHtml =
sut.getFlightConnectionAsHtmlFragment(
illegalConn.getInboundFlightNumber(),
illegalConn.getOutboundFlightNumber());
//
StringBuffer expected = new StringBuffer();
expected.append("<span class="boldRedText">");
expected.append("Connection time between flight ");
expected.append(illegalConn.getInboundFlightNumber());
expected.append(" and flight ");
expected.append(illegalConn.getOutboundFlightNumber());
expected.append(" is ");
expected.append(illegalConn.getActualConnectionTime());
expected.append(" minutes.</span>");
assertEquals("html", expected.toString(), actualHtml);
)

 ( 
) ( ).
, , FlightConnection 
. , .
7

. 372

373


:  ( 
?), 
( ?).
(Testcase Class, . 401),
(Test Method) 
 (Test Method)
.
,
(Testcase Class) ,
. ( 
/ ), ,
.  (
)
( )8. ,
,
, .
,
(Replace Dependency with Test Double, . 740) $
(Subcutaneous Test) .

:
,
.
FlightConnAnalyzer 
HtmlFacade. 
.
public void testGetFlightConnAsHtml_illegalConnection()
throws Exception (
//
FlightConnection illegalConn = createIllegalConnection();
Mock analyzerStub = mock(IFlightConnAnalyzer.class);
analyzerStub.expects(once()).method("analyze")
.will(returnValue(illegalConn));
HTMLFacade htmlFacade =
new HTMLFacade((IFlightConnAnalyzer)analyzerStub.proxy());
//
String actualHtmlString =
htmlFacade.getFlightConnectionAsHtmlFragment(
illegalConn.getInboundFlightNumber(),
illegalConn.getOutboundFlightNumber());
//
StringBuffer expected = new StringBuffer();
expected.append("<span class="boldRedText">");
expected.append("Connection time between flight ");
8

,
, (Layer Test) .

. 373

374

18

expected.append(illegalConn.getInboundFlightNumber());
expected.append(" and flight ");
expected.append(illegalConn.getOutboundFlightNumber());
expected.append(" is ");
expected.append(illegalConn.getActualConnectionTime());
expected.append(" minutes.</span>");
assertEquals("returned HTML",
expected.toString(),
actualHtmlString);
)

HTML 
. , 
.

: (Subcutaneous Test)
, (Subcutaneous
Test)
.
.
private final int LEGAL_CONN_MINS_SAME = 30;
public void testAnalyze_sameAirline_LessThanConnectionLimit()
throws Exception (
//
FlightConnection expectedConnection =
createSameAirlineConn(LEGAL_CONN_MINS_SAME -1);
//
IFlightConnAnalyzer theConnectionAnalyzer =
new FlightConnAnalyzer();
FlightConnection actualConnection =
theConnectionAnalyzer.getConn(
expectedConnection.getInboundFlightNumber(),
expectedConnection.getOutboundFlightNumber());
//
assertNotNull("actual connection", actualConnection);
assertFalse("IsLegal", actualConnection.isLegal());
)

,
. (Slow Tests) $
(Erratic Test, . 267).

: /
, 
. $
(Mock Object) JMock.

.

. 374

375

public void testAnalyze_sameAirline_EqualsConnectionLimit()


throws Exception (
//
Mock flightMgntStub = mock(FlightManagementFacade.class);
Flight firstFlight = createFlight();
Flight secondFlight = createConnectingFlight(
firstFlight, LEGAL_CONN_MINS_SAME);
flightMgntStub.expects(once()).method("getFlight")
.with(eq(firstFlight.getFlightNumber()))
.will(returnValue(firstFlight));
flightMgntStub.expects(once()).method("getFlight")
.with(eq(secondFlight.getFlightNumber()))
.will(returnValue(secondFlight));
//
FlightConnAnalyzer theConnectionAnalyzer = new FlightConnAnalyzer();
theConnectionAnalyzer.facade =
(FlightManagementFacade)flightMgntStub.proxy();
FlightConnection actualConnection =
theConnectionAnalyzer.getConn(
firstFlight.getFlightNumber(),
secondFlight.getFlightNumber());
//
assertNotNull("actual connection", actualConnection);
assertTrue("IsLegal", actualConnection.isLegal());
)

,
. , , 
.

. 375

. 376

19

19

xUnit
:

(Test Method)................................................................... 378
(FourPhase Test)..................................................... 387
(Assertion Method) ............................................... 390
(Assertion Message)..................................... 398
(Testcase Class)........................................................................ 401

(Test Runner) .................................................. 405
(Testcase Object).................................................................... 410
(Test Suite Object)................................................... 414
(Test Discovery)........................................................ 420
(Test Enumeration).................................................. 425
(Test Selection)..................................................................... 429

. 377

378

19

(Test Method)
?
(Test Method) .

testMethod_1

testMethod_1

testMethod_n

testMethod_n

(Fully Automated Tests, . 81) 


.  .


, , 
(. , FourPhase Test, . 387), 
(Fully Automated Tests). 
(Test Method) .
(SelfChecking Test, . 81).

(Test Method), . $
(Simple Success Test)

. (Expected Exception Test)
. ,
,  .
(Constructor Test) 
.


 .
, .  

(Testcase Class, . 401). 

. 378

xUnit

379

(Testcase Object, . 410) $


(Test Discovery, . 420) (Test Enumeration, . 425).
$
(Test Method). 

. , $
(Expected Exception Test)
, try/catch.


(Test Method)
(Testcase Class). 
(Testcase Class), . 
, .
,
(Test Suite Object, . 414)
(Test Method) (
. 411). ,
(Testcase Class) (Test Method)
(Test Discovery) (Test Enumeration).
Java C# throws 
(Test Method),
, .
, (Test Runner, . 405)
.
, (Test
Method). .

: (Simple Success Test)



( ). (Simple Success Test)
.
, 
.
. , $
(FourPhase Test). , , 
. (Test Automation
Framework, . 332). (Obscure Test,
. 230), , ,
.
(Tests as Documentation).
try/catch
, $
(Test Automation Framework)
, (Assertion Method,

. 379

380

19

. 390) (, fail assertTrue). 


, .

: (Expected Exception Test)


,
(Simple Success Test).
,
, $
(Untested Requirement; . , Production Bugs, . 303)
(Untested Code). (Expected Ex
ception Test) , .
,
. 
. , 
. ,
( ) (,
), $
(Equality Assertion). , fail, 
.
(Expected Exception Test) 
, .
, (.. ) 
. ,
.
(Expected Exception Test) ,
, ,

(Simple Success Test). , 
, . 
(Test Stub,
. 544) 
(Test Stub).
,
xUnit. JUnit 3.x ExpectedException. (Testcase Class) 
(Test Method),
try/catch
(Testcase Class). JUnit NUnit ( .NET) 
( Java ) ExpectedException, ,
. , 
, .
(, Smalltalk Ruby) 
, /
. (Assertion Method)
, . $

. 380

xUnit

381

(Test Method)
.

: (Constructor Test)

, (Test
Code Duplication, . 254). ,
,
, (Test Method).
(Constructor Test) (Defect Lo
calization, . 78), . 
.
(Constructor Test)
(Simple Success Test), (Expected
Exception Test) .

, . ,
(Equality Assertion) 
. 
(Stated Outcome Assertion)
(, assertNull(anObjectReference) 
). ,
(Testcase Class per Fixture, . 639) 
(Test Method)
(Defect Localization).

: (Dependency Initialization Test)


, ,
. $
(Dependency Initialization Test) (Cons
tructor Test), .
(Test Method) .

: (Simple Success Test)


, 
( ).
public void testFlightMileage_asKm() throws Exception {
//
Flight newFlight = new Flight(validFlightNumber);
try {
//
newFlight.setMileage(1122);
//
int actualKilometres = newFlight.getMileageAsKm();
int expectedKilometres = 1810;
//

. 381

382

19

assertEquals( expectedKilometres, actualKilometres);


} catch (InvalidArgumentException e) {
fail(e.getMessage());
} catch (ArrayStoreException e) {
fail(e.getMessage());
}
}

. , 
. xUnit 
. 
(Test Automation Framework)
.
, . ,
, .
public void testFlightMileage_asKm() throws Exception {
//
Flight newFlight = new Flight(validFlightNumber);
newFlight.setMileage(1122);
//
int actualKilometres = newFlight.getMileageAsKm();
//
int expectedKilometres = 1810;
assertEquals( expectedKilometres, actualKilometres);
}

Java ( ),
$
(Test Method).

: (Expected Exception Test)


try/catch

.
.
public void testSetMileage_invalidInput() throws Exception {
//
Flight newFlight = new Flight(validFlightNumber);
//
newFlight.setMileage(-1122); //
// ?
}

(Test Automation Framework) 


,
(Test Runner)
. 
(
; , ).
, JUnit 3.x.

. 382

xUnit

383

public void testSetMileage_invalidInput() throws Exception {


//
Flight newFlight = new Flight(validFlightNumber);
try {
//
newFlight.setMileage(-1122);
fail("Should have thrown InvalidInputException");
} catch(InvalidArgumentException e) {
//
assertEquals("Flight mileage must be positive",
e.getMessage());
}
}

try/catch , 
. 
(Assertion Method) fail
, , 
catch. $
(Expected Exception Test),
(Custom Assertion, . 495).
public void testSetMileage_invalidInput2() throws Exception {
//
Flight newFlight = new Flight(validFlightNumber);
try {
//
newFlight.setMileage(-1122);
// ,
// fail()
} catch(AssertionFailedError e) {
//
assertEquals("Flight mileage must be positive",
e.getMessage());
return;
}
fail("Should have thrown InvalidInputException");
}

: (Expected Exception Test)



NUnit , $
(Expected Exception Test) try/catch.
[Test]
[ExpectedException(typeof(InvalidArgumentException),
"Flight mileage must be > zero")]
public void testSetMileage_invalidInput_AttributeWithMessage()
{
//
Flight newFlight = new Flight(validFlightNumber);
//
newFlight.setMileage(-1122);
}

. 383

384

19

, ,
.
( (Sensitive Equality); .
, Fragile Test, . 277), try/catch.

: (Expected Exception Test)



SUnit Smalltalk 
.
testSetMileageWithInvalidInput
self
should: [Flight new mileage: -1122]
raise: RuntimeError new 'Should have raised error'

Smalltalk , should:raise: 
Exception. Test::Unit
Ruby .
def testSetMileage_invalidInput
flight = Flight.new();
assert_raises( RuntimeError, "Should have raised error") do
flight.setMileage(-1122)
end
end

do/end , assert_raises. ( RuntimeError), .

: (Constructor Test)

( ). , 
.
public void testFlightMileage_asKm2() throws Exception {
//
//
Flight newFlight = new Flight(validFlightNumber);
//
assertEquals(validFlightNumber, newFlight.number);
assertEquals("", newFlight.airlineCode);
assertNull(newFlight.airline);
//
newFlight.setMileage(1122);
//
int actualKilometres = newFlight.getMileageAsKm();
//
int expectedKilometres = 1810;
assertEquals(expectedKilometres, actualKilometres);

. 384

xUnit

385

// ,
newFlight.cancel();
try {
newFlight.getMileageAsKm();
fail("Expected exception");
} catch (InvalidRequestException e) {
assertEquals("Cannot get cancelled flight mileage",
e.getMessage());
}
}

(Single Condition Test, . 99),


.
, ,
.
(Eager Test; . $
, Assertion Roulette, . 264) (Single Condition Test). 
(Test Method) 
. 
.
(Constructor Test).
public void testFlightConstructor_OK() throws Exception {
//
//
Flight newFlight = new Flight(validFlightNumber);
//
assertEquals(validFlightNumber, newFlight.number);
assertEquals("", newFlight.airlineCode);
assertNull(newFlight.airline);
}

, ,
.
(Expected Exception Test).
public void testFlightConstructor_badInput() {
//
BigDecimal invalidFlightNumber = new BigDecimal(-1023);
//
try {
Flight newFlight = new Flight(invalidFlightNumber);
fail("Didn't catch negative flight number!");
} catch (InvalidArgumentException e) {
//
assertEquals("Flight numbers must be positive",
e.getMessage());
}
}

,
(Simple Success Test) . 
, ,
.

. 385

386

19

public void testFlightMileage_asKm() throws Exception {


//
Flight newFlight = new Flight(validFlightNumber);
newFlight.setMileage(1122);
//
int actualKilometres = newFlight.getMileageAsKm();
//
int expectedKilometres = 1810;
assertEquals(expectedKilometres, actualKilometres);
}

, ?
, , . 
. , ,
. 
. , getMileageAsKm. 
(Defect Localization).

. 386

xUnit

387

(Four/Phase Test)
,
?
,
.

testMethod_1

testMethod_1

Testcase

testMethod_n

testMethod_n


, 
: ,
, .

( 
), 
,
(, , Test Double, . 538).

,
.


,
. ,
( , 
 ,  
). 
.

. 387

388

19


, .

. , 
.
. , ,
. 
, (Tests as Documentation, . 79) 
.

(Test Method, . 378),
(Obscure Test, . 230).
(Single Condition Test, . 99). 
,
( 
). ,
(Defect Localization, . 78)
(Single Condition Test).


(FourPhase
Test).
(Test Method). 
(Inline Setup, . 434)
(GarbageCollected Teardown, . 518) (Inline Teardown, . 527).

(Testcase Class per Class, . 627)
(Testcase Class per Fixture, . 639).
(Implicit Setup, . 449)
(Implicit Teardown, . 533)
(Test Automation Framework, . 332). 
setUp tearDown (Testcase
Class, . 401). (Test Method)
.
(Testcase Class per
Fixture). ,

(Testcase Class per Class) (Testcase Class per
Feature), 
(Automated Teardown, . 521).

: (FourPhase Test)
.
public void testGetFlightsByOriginAirport_NoFlights_inline()
throws Exception {

. 388

xUnit

389

//
NonTxFlightMngtFacade facade =new NonTxFlightMngtFacade();
BigDecimal airportId = facade.createTestAirport("1OF");
try {
//
List flightsAtDestination1 =
facade.getFlightsByOriginAirport(airportId);
//
assertEquals(0, flightsAtDestination1.size());
} finally {
//
facade.removeAirport(airportId);
}
}

. $
(Assertion Method, . 390) ,
try/finally 
.

: (Four/Phase Test) c
, 
(Test Method).
NonTxFlightMngtFacade facade = new NonTxFlightMngtFacade();
private BigDecimal airportId;
protected void setUp() throws Exception {
//
super.setUp();
airportId = facade.createTestAirport("1OF");
}
public void testGetFlightsByOriginAirport_NoFlights_implicit()
throws Exception {
//
List flightsAtDestination1 =
facade.getFlightsByOriginAirport(airportId);
//
assertEquals(0, flightsAtDestination1.size());
}
protected void tearDown() throws Exception {
//
facade.removeAirport(airportId);
super.tearDown();
}

tearDown 
, try/finally .
, 
, .

. 389

390

19

(Assertion Method)
?
,
.

testMethod_1

testMethod_1

Test
Suite

t
Ex ercise
Te

testMethod_n

testMethod_n

(Fully Automated Tests,


. 81) (SelfChecking Test, . 81), 
. 
,
.
(Assertion Method)
, , ,
(Tests as Documentation, . 79).


. 
, . 
(Assertion Method), 
. (Assertion Method)
(Test Automation Framework, . 332) 
(Custom Assertion, . 495).


(Conditional Test
Logic, . 243) 
. , (Test Code Du
plication, . 254) (Buggy Test, . 296). 
(Assertion Method)

. 390

xUnit

391

(Test Utility
Method, . 610). $
(Test Utility Test).


xUnit (Assertion
Method),
. :

(Assertion Method);

(Assertion Method);

, (Assertion Mes
sage, . 398).


(Assertion Method) (Test
Method) . 
,
. (Assertion Method)
. 
(Assertion Method).

. 391

(Assertion Method) (Testcase


Superclass, . 646), . 
(Testcase Class, . 401). ,
Java JUnit $
(Testcase Superclass), Assert ( 
, Assertion Method).

(Assertion Method) 
. 
(Assertion Method). 
NUnit (, Assert.isTrue(x);). JUnit 
Assert (
, Assert.assertTrue(x)), , 
(Testcase Superclass).

(Assertion Method)
. , Test::Unit Ruby $
(Assertion Method) Assert, , 

(Testcase Class) (, assert_equal(a,b)). (
(Mock Object, . 558),
(Testcase Class),
(Assertion Method).) , 
CppUnit (Assertion Method) ,
.

392

19


(Assertion Method) $
(Assertion Message) .
, . 
, (Assertion Method)
. 
, (Assertion Method) 
. (Assertion Method)
, (Assertion
Method) .
(Equality Assertion).
xUnit
(Assertion Message)
. .
JUnit (Assertion Message) .


(Assertion Method) (Test
Method), :

, ;

(..
, Tests as Documentation).


(Assertion Method). 
xUnit, 
, .

. 392

(Single Outcome Assertion),


fail. , .

(Stated Outcome Assertion),


assertNotNull(anObjectReference) assertTrue(aBooleanExpression).
,
.

(Expected Exception Assertion),


assert_raises(expectedError) { codeToExecute }.
.

(Equality Assertion), assertEqual(expected,


actual). .

(Fuzzy Equality Assertion), assertEqual(expected, actual, tolerance).


.
.

xUnit

393

: (Equality Assertion)
(Equality Assertion)
(Assertion Method).
, $
(Literal Value, . 718) (Expected Object; . $
, State Verification, . 484). ,
. 
. 
equals . 
equals ,
(Equality Assertion) 
$
(TestSpecific Subclass, . 591) (Expected Object).

: (Fuzzy Equality Assertion)



, $
(Fuzzy Equality Assertion).
(Equality Assertion)
( ), , 
. $
(Fuzzy Equality Assertion) 
, .
( ).
XML, 
,
.
, 
. (Equality Assertion) 
.

: (Stated Outcome Assertion)


(Stated Outcome Assertion)
. 
, (Assertion
Method). .

assertTrue(aBooleanExpression). ,
FALSE.

assertNotNull(anObjectReference). , objectReference .

(Stated Outcome Assertion)


(Guard Assertion, . 510), $
(Conditional Test Logic).

. 393

394

19

: (Expected Exception Assertion)


$
(Stated Outcome Assertion), 
. $
(Expected Exception Assertion) : ,
. 
try/catch.
:

should: [aBlockToExecute] raise: expectedException  Smalltalk SUnit;

assert_raises( expectedError) { codeToExecute }  Ruby Test::Unit.

: (Single Outcome Assertion)


(Single Outcome Assertion)
. fail, 
. .

(Unfinished Test Assertion, . 514),



(Test Method). fail, (Test
Runner, . 405) .

try/catch ( ) $
(Expected Exception Test). fail
try , . 
,
catch
success, , .

, (Single Outcome Asser


tion) , (Conditional Test Logic).
$
(Test Method),
(Assertion Method). , $
(Guard Assertion)
.


,
(Assertion Method).
if (x.equals(y)) {
throw new AssertionFailedError(
"expected: <" + x.toString() +
"> but found: <" + y.toString() + ">");
} else { // ,
// ...
}

. 394

xUnit

395

, NullPointerException,
x null. 
. , 
, AssertionFailedException.
if (x == null) { // null.equals(null)
if (y == null ) { // null, ,
return;
} else {
throw new AssertionFailedError(
"expected null but found: <" + y.toString() +">");
}
} else if (!x.equals(y)) { // , !
throw new AssertionFailedError(
"expected: <" + x.toString() +
"> but found: <" + y.toString() + ">");
} //

! . 
. , .


, xUnit 
(Extract Method) $
(Assertion Method). if 
(Assertion Method). 
assertEquals JUnit.
, 
, .
/**
* . ,
* AssertionFailedError
* .
*/
static public void assertEquals(String message,
Object expected,
Object actual) {
if (expected == null && actual == null)
return;
if (expected != null && expected.equals(actual))
return;
failNotEquals(message, expected, actual);
}

failNotEquals (Test Utility


Method), .

. 395

396

19

: (Equality Assertion)
, $
(Equality Assertion) JUnit.
assertEquals(x, y);

C#. 
.
Assert.AreEqual(x, y);

: (Fuzzy Equality Assertion)


(
) $
(Fuzzy Equality Assertion).
assertEquals(3.1415, diameter/2/radius, 0.001);
assertEquals(expectedXml, actualXml, elementsToCompare);

: (Stated Outcome Assertion)



(Stated Outcome Assertion).
assertNotNull(a);
assertTrue(b > c);
assertNonZero(b);

: (Expected Exception Assertion)


. 
Smalltalk Sunit.
self
should: [Flight new mileage: -1122]
raise: RuntimeError new 'Should have raised error'

should: ( 
), raise: . Ruby
.
assert_raises(RuntimeError,
"Should have raised error")
{flight.setMileage(-1122)}

, Ruby 
do/end .
assert_raises(RuntimeError, "Should have raised error") do
flight.setMileage(-1122)
end

. 396

xUnit

397

: (Single Outcome Assertion)


$
(Single Outcome Assertion).
fail("Expected an exception");
unfinishedTest();

. 397

398

19

(Assertion Message)

?

.

testMethod_1

testMethod_1

Te st

run

ite

Object

testMethod_n

testMethod_n

(SelfChecking Test, . 81) 


(Assertion Method, . 390), 
. (Test Runner, . 405)
.
(Assertion Message)

.


(Assertion Method) 
, .
, (Assertion Message) $
(Test Runner) .


. , 
, , $
(Assertion Message) , 
, , .
(Assertion Method) ,
.
,
, . 

. 398

xUnit

399

,
(CommandLine Test Runner), 
.



. ?
:
?

: ,
(Assertion/Identifying Message)
$
(Test Method, . 378), ,
. (Asser
tion Message), .
.
. , .
, , 
.

: , (Expectation/Describing Message)
, . 
: ? 
. , .
$
(Assertion Message). (Equality
Assertion) , $
(Stated Outcome Assertion) .

: (Argument/Describing Message)
(Assertion Method)
. $
(Stated Outcome Assertion), assertTrue(aBooleanExpression). ,
, .
(Assertion Message) ( 
).
, .


assertTrue(a > b);
assertTrue(b > c);

. 399

400

19

, 
Assertion failed. ,
. , ?


$
(Assertion Method). , a
b. , a b.
(Assertion Mes
sage) .

: ,

(ArgumentDescribing Message).
assertTrue("Expected a >
"' and
a.gt(b));
assertTrue("Expected b >
"' and
b > c);

b but a was '" + a.toString() +


b was '" + b.toString() + "'",
c but b was '" + b.toString() +
c was '" + c.toString + "'",

.
Assertion Failed. Expected a > b but a was '17' and b was '19'.

, ,
!

. 400

xUnit

401

(Testcase Class)
?

(Test Method)
(Testcase Class).

:

(Test Fixture)

testMethod_1

testMethod_ 1

testMethod_n

testMethod_ n

(Test Method), ,
, . (Testcase Class) 
(Testcase
Object, . 410).



(Testcase Class). (Testcase Class) $
(Test Suite Factory; . , Test Enumeration,
. 425), (Testcase Object)
(Test Method). (Test Suite Object,
. 414), (Test Runner, . 405).


 (Test Method)
, ( 
). (Testcase Class),
(Testcase Object) ,
(Testcase Class) (Test Method).
(Test Method)
.

. 401

402

19


. 
, (, ), 
(, ). (Testcase Class, . 401) 
. , .
xUnit : , 
, Testcase, $
(Test Method)? TestSuite?
, ( 
).
(Test
Method). (Testcase Class) .
(Implicit
Setup, . 449), ( ) 
setUp (Test
Method). xUnit 
.
, .
xUnit
(Testcase Class) (Test Method).
(Testcase Class) (Test Suite Factory; . $
, Test Enumeration, . 425), (Test Suite Ob
ject, . 414) ( 
). , 
, .
, xUnit
(Test Method) 
.
,
. (Test Suite Object), $
(Test Suite Factory),
(Testcase Object, . 410).
(Testcase Class). (Test
Method). , .
( (Test
Discovery, . 420).) , (Testcase Class)
(test case). (Test Method) 
, .


, JUnit New
Instance.
, (Test Method)
, 
. , ( 
) .

. 402

xUnit

403


(Test Method):
, (Test Util
ity Method, . 610), (Isolate the SUT, . 97) ..
(Testcase Class) 
(Testcase Object) (Test
Runner). (Test Method), 
, (Test Runner)
. (Test Code Duplication,
. 254), (Extract Method) $
(Test Utility Method). $
(Testcase Class) (Abstract
Testcase; . , Testcase Superclass, . 646), $
(Test Helper, . 651) (Test Helper Mixin; . $
(Testcase Superclass).

: (Testcase Class)
(Testcase Class).
public class TestScheduleFlight extends TestCase {
public void testUnscheduled_shouldEndUpInScheduled() throws Exception {
Flight flight = FlightTestHelper.
getAnonymousFlightInUnscheduledState();
flight.schedule();
assertTrue("isScheduled()", flight.isScheduled());
}
public void testScheduledState_shouldThrowInvalidRequestEx()
throws Exception {
Flight flight = FlightTestHelper.
getAnonymousFlightInScheduledState();
try {
flight.schedule();
fail("not allowed in scheduled state");
} catch (InvalidRequestException e) {
assertEquals("InvalidRequestException.getRequest()",
"schedule",
e.getRequest());
assertTrue("isScheduled()", flight.isScheduled());
}
}
public void testAwaitingApproval_shouldThrowInvalidRequestEx()
throws Exception {
Flight flight = FlightTestHelper.
getAnonymousFlightInAwaitingApprovalState();
try {
flight.schedule();
fail("not allowed in schedule state");
} catch (InvalidRequestException e) {
assertEquals("InvalidRequestException.getRequest()",
"schedule",

. 403

19

404

e.getRequest());
assertTrue("isAwaitingApproval()",
flight.isAwaitingApproval());
}
}
}


xUnit ( , VbUnit NUnit) (Testcase
Class) .
( ), ,
( ). ,
Fit, , 
Fit
(DataDriven Test, . 322).

. 404

xUnit

405

(Test Runner)
?
, (Test Suite Object)
(Testcase Object).

testMethod_1

testMethod_1

testMethod_n

testMethod_n

, (Test Method, . 378) 


(Testcase Class, . 401). $
(Test Automation Framework, . 332) 
?


(Test Automation Frame
work) xUnit 
, 
. (Test Runner)
(Test Enumeration, . 425), (Test Discovery, . 420)
(Test Selection, . 429) Composite. 
(Testcase Object), (Test Suite Object, . 414)
Composite ( , Suite of Suites).
, (Test Runner) ,
. (Test Runner)
, 
. .



. 
.

. 405

406

19

(Test Runner) ,
. , .


(Test Runner).

. 
(Testcase Object).


(, Java C#) 
( ), , 
(Testcase Object) $
(Test Suite Object). (, C# Java 5.0)

(Testcase Class).
. .

. (Test Enumeration),
(Testcase Class)
(Test Suite Factory; . , Test Enumeration,
. 425), suite.

: (Graphical Test Runner)


(Graphical Test Runner)
.
(IeUnit) Web. 

. , 
. ,
,
. xUnit 
(Test Tree Explorer),
.

(Graphical Test Runner) JUnit Eclipse.
, 
. 
.
.

: (Command/Line Test Runner)


(CommandLine Test Runner) 


. 406

xUnit

407

. 
, make, Ant /
(continuous integration), Cruise Control.

runit ( xUnit 
Ruby).
>ruby testrunner.rb c:/examples/tests/SmellHandlerTest.rb
Loaded suite SmellHandlerTest
Started
.....
Finished in 0.016 seconds.
5 tests, 6 assertions, 0 failures, 0 errors
>Exit code: 0

.
, (Test
case Class)  SmellHandlerTest.
. , 
. $
(CommandLine Test Runner) E F,
.
. 
. 

.

. 407

408

19

: (File System Test Runner)


(CommandLine Test
Runner) , .
. 
(Testcase Class Discovery) 
(Suite of Suites)
(Lost Test; . , Production Bugs, . 303).
, . 
(Test Runner)
.

: (Test Tree Explorer)


xUnit, (Test Method)
(Testcase Object), . 
(Suite of Suites), 
(Test Suite Object) $
(Testcase Object).
(Single Test Suite; . , Named Test Suite, . 604)
.
(Test Tree Explorer)
JUnit Eclipse.

. 408

xUnit

409

JUnit.
. (Test
Tree Explorer),  . 
, (Test Suite Object) $
(Test Tree Explorer) , 
. (Testcase Object)
. (Test Suite Ob
ject) , .
(Test Suite Object) Test for com.clrstream.ex8.test 
(Suite of Suites) com.clrstream.ex8.test. Test
for allJUnitTests .

. 409

410

19

(Testcase Object)
?
Command, run /
, .

testMethod_1

testMethod_1

testMethod_n

testMethod_n

(Test Runner, . 405) 


(Test Method, . 378),
. 

. (Test
Runner)
.


Command (Test
Method). (Testcase Class, . 401) $
(Test Suite Factory) (Test Suite Object,
. 414), (Testcase Object)
(Testcase Class). (Testcase Object) $
(Test Discovery, . 420) (Test Enumeration).



, .
(Test Runner) (Test Automation
Framework, . 332) . 
( , Test Suite Object), ,
..

. 410

xUnit

411

xUnit (Testcase Object)


. 
. , , 
(Test Automation Framework)
.


(Testcase Object)
(Test Runner) . 
(Testcase Object) Com
mand. (Testcase Object), 
,
.

(Testcase Object) .
(Testcase Class) (Testcase Object).
(Test Method)
(Testcase Class),
(Test Util
ity Method, . 610). , (Testcase Ob
ject) (Testcase Class)
(Test Method).
(Pluggable Behavior). (Testcase
Class)
. (Test Runner) 
run (Testcase Object), 
, .


,
!
xUnit 
(Testcase Object, . 410)
(Test Method, . 378) . xUnit, 
. xUnit,
: TestNG NUnit ( 2.).
NUnit 2.0 (Testcase
Object) (Test Method) 
(Testcase Class, . 401). /
(test fixture), .
NUnit 2.0, , .
, NUnit v2.0
.
, , ,
JUnit . ,

. 411

412

19

, $
.
, $
. .
.
, ( ) ,
JUnit (Testcase Object)
. , ,
,
. (Shared Fixture,
. 350) (Erratic Test, . 267), .
.
NUnit,
, . $
, .
, NUnit
, .
JUnit $
, NUnit.
,
JUnit, http://martinfowler.com/bliki/
JunitNewInstance.html.

: (Testcase Object)
(Testcase Object) 
(Test Tree Explorer) $
(Test Suite Object)
(Testcase Object). JUnit 
Eclipse. ,
(Testcase Class).
TestSuite("...flightstate.featuretests.AllTests")
TestSuite("...flightstate.featuretests.TestApproveFlight")
TestApproveFlight("testScheduledState_shouldThrowIn..ReEx")
TestApproveFlight("testUnsheduled_shouldEndUpInAwai..oval")
TestApproveFlight("testAwaitingApproval_shouldThrow..stEx")
TestApproveFlight("testWithNullArgument_shouldThrow..ntEx")
TestApproveFlight("testWithInvalidApprover_shouldTh..ntEx")
TestSuite("...flightstate.featuretests.TestDescheduleFlight")
TestDescheduleFlight("testScheduled_shouldEndUpInSc..tate")
TestDescheduleFlight("testUnscheduled_shouldThrowIn..stEx")
TestDescheduleFlight("testAwaitingApproval_shouldTh..stEx")
TestSuite("...flightstate.featuretests.TestRequestApproval")
TestRequestApproval("testScheduledState_shouldThrow..stEx")
TestRequestApproval("testUnsheduledState_shouldEndU..oval")
TestRequestApproval("testAwaitingApprovalState_shou..stEx")
TestSuite("...flightstate.featuretests.TestScheduleFlight")
TestScheduleFlight("testUnscheduled_shouldEndUpInSc..uled")
TestScheduleFlight("testScheduledState_shouldThrowI..stEx")
TestScheduleFlight("testAwaitingApproval_shouldThro..stEx")

. 412

xUnit

413

.  , 
. (Test Method)
( .. 
) (Testcase Object)
(Test Suite Object) , 
(Test Suite Object).
(Testcase Class).

(Test Tree Explorer).

. 413

414

19

(Test Suite Object)


?
, .
(Testcase Object).

testMethod_1

testMethod_1

testMethod_n

testMethod_n

(Test Method, . 378), ,


(Testcase Class, . 401)
(Testcase Object) , .


(Testcase Object) ( Composite), 
(Test Suite Object) 
(Testcase Object). 
(Test Runner, . 405)
(Test Suite Object).



(Test Runner) $
(Test Automation Framework, . 332).
(Test Suite Object) (Test Runner)
(Testcase Object) , , .. 
, ,
(Suite of Suites).

: (Testcase Class Suite)


(Test Method) (Testcase
Class) (Test Suite Object)

. 414

xUnit

415

(Testcase Class) (Testcase Object) $


(Test Method). (Test Method)
(Testcase Class), (Test Runner) .

: (Suite of Suites)
,
(Named Test Suite, . 604). Composite
(Test Runner), 
(Suite of Suites) ,
(Testcase Class Suite) (Testcase Object).


Composite (Test Suite Object) 
, (Testcase Object). , $
(Test Runner), (Test Suite Object)
, , .
, 
, .
(Test Suite Object) .
.

(Test Discovery, . 420). $


(Test Automation Framework)
(Testcase Class) (Test Method).

(Test Enumeration, . 425). ,


(Test Method)
(Test Suite Object).
(Test Suite Factory).

(Test Selection, . 429).


(Testcase Object),
(Test Suite Object).

: (Test Suite Procedure)


.
(Test Runner) $
(Test Method). (Test Suite Procedure) 
, .
(Test Suite Object). ,
(Test Suite Procedure)
(Test Suite Procedure) (Suite of Suites).

(Test Enumeration),
(Lost Test). ,
.

. 415

416

19


(Suite of Suites).

: (Test Suite Object)


xUnit (Test Discovery),
(Test Suite Object) . 
(Test Tree Explorer)
(Testcase Object). 
JUnit, Eclipse.

: (Suite of Suites)
(Test Enumeration)
(Test Enumeration)
(Suite of Suites).
public class AllTests {
public static Test suite() {
TestSuite suite = new TestSuite("Test for allJunitTests");
suite.addTestSuite(
com.clrstream.camug.example.test.InvoiceTest.class);
suite.addTest(com.clrstream.ex7.test.AllTests.suite());
suite.addTest(com.clrstream.ex8.test.AllTests.suite());
suite.addTestSuite(com.xunitpatterns.guardassertion.Example.class);
return suite;
}
}

. 416

xUnit

417

(Test Suite Object), 


(Testcase Class). 
(Test Suite Factory) (Suite of
Suites). (Test Suite Object) 
.
1. (Test Suite
Object).
2. (Test Suite Object) AllTests,
.
3. (Test Suite Object) (Testcase
Class), (Test Suite Object).
.
TestSuite("Test for allJunitTests");
TestSuite("com.clrstream.camug.example.test.InvoiceTest")
TestCase("testInvoice_addLineItem")
...
TestCase("testRemoveLineItemsForProduct_oneOfTwo")
TestSuite("com.clrstream.ex7.test.AllTests")
TestSuite("com.clrstream.ex7.test.TimeDisplayTest")
TestCase("testDisplayCurrentTime_AtMidnight")
TestCase("testDisplayCurrentTime_AtOneMinAfterMidnight")
TestCase("testDisplayCurrentTime_AtOneMinuteBeforeNoon")
TestCase("testDisplayCurrentTime_AtNoon")
...
TestSuite("com.clrstream.ex7.test.TimeDisplaySolutionTest")
TestCase("testDisplayCurrentTime_AtMidnight")
TestCase("testDisplayCurrentTime_AtOneMinAfterMidnight")
TestCase("testDisplayCurrentTime_AtOneMinuteBeforeNoon")
TestCase("testDisplayCurrentTime_AtNoon")
...
TestSuite("com.clrstream.ex8.test.AllTests")
TestSuite("com.clrstream.ex8.FlightMgntFacadeTest")
TestCase("testAddFlight")
TestCase("testAddFlightLogging")
TestCase("testRemoveFlight")
TestCase("testRemoveFlightLogging")
...
TestSuite("com.xunitpatterns.guardassertion.Example")
TestCase("testWithConditionals")
TestCase("testWithoutConditionals")
...

, . TestSuite
$
(Test Suite Factory).

: (Test Suite Procedure)


,
, Excel

. 417

418

19

.
(, ,
..) .
(),
. 
. ,
.
, xUnit
VBA, (Tests as
Safety Net, . 79). .
.
'Main Macro
Sub summarizeActivities()
Call VerifyVersionCompatability
Call initialize
Call SortByActivity
For row = firstTaskDataRow To lastTaskDataRow
If numberOfNumberlessTasks < MaxNumberlessTasks Then
thisActivity =
ActiveSheet.Cells(row, TaskActivityColumn).Value
If thisActivity <> currentActivity Then
Call finalizeCurrentActivityTotals
currentActivity = thisActivity
Call initializeCurrentActivityTotals
End If
Call accumulateActivityTotals(row)
Else
lastTaskDataRow = row
' end the For loop right away
End If
Next row
Call cleanUp
End Sub

(Test Automation Frame


work) .
. 
,
. VBA Visual Basic 5,
. , (Testcase Class) $
(Testcase Object) . $
(Test Suite Procedure) (Test Method).
Sub TestAll()
Call TestAllStoryMacros
Call TestAllTaskMacros
Call TestReportingMacros
Call TestToolbarMenus 'All The Same
End Sub
Sub TestAllStoryMacros()
Call TestActivitySorting
Call TestStoryHiding
Call ReportSuccess("All Story Macros")

. 418

xUnit

419

End Sub
Sub TestActivitySorting()
Call SortStoriesbyAreaAndNumber
Call SortActivitiesByIteration
Call SortActivitiesByIterationAndOrder
Call SortActivitiesByNumber
Call SortActivitiesByPercentDone
End Sub
Sub TestReportingMacros()
Call summarizeActivities
End Sub

(Test Suite Procedure) (Suite


of Suites). (Test Suite Procedure)
(Test Suite Object). $
(Test Method) . 
summarizeActivities
(Prebuilt Fixture, . 454). (
, . $
(SelfChecking Test) (Single Condition Test).)

. 419

420

19

(Test Discovery)
(Test Runner) , ?
(Test Automation Framework)
, .

testMethod_1

testMethod_1

testMethod_n

testMethod_n

(Test Method, . 378) 


(Testcase Class, . 401) (Test Runner,
. 405) .
(Test Discovery) ,
(Test Enumeration, . 425).


(Test Automation Framework, . 332) 
( ,
) (Test Method), 
/ (Test Suite Object, . 414), 
(Suite of Suites).
(Test Suite Object), (Testcase Object, . 410)
(Test Suite Object).


(Test Discovery) 
, (Test
Automation Framework). , 
,
(Lost Test). (Test Enumeration)
.

. 420

xUnit

421

1. (Test Automation Framework)


(Test Discovery).
2. (Named Test Suite,
. 604), (
, Smoke Test) ,
(Test Automation Framework)
(Test Selection, . 429).
(Test Suite Enumeration)
(Test Method Discovery). 
.


(Suite of Suites)
(Test Runner) . ,
(Test Method) (Test Suite Object). 
, (Test Suite Object), 
. .
(Test Method Enumera
tion) (Test Suite Enumeration) 
(Test Method Discovery) $
(Testcase Class Discovery).

: (Testcase Class Discovery)


(Testcase Class Discovery) $
(Testcase Class)
(Test Automation Framework).
(Testcase Class) (Testcase Superclass, . 646)
Marker Interface. .NET 
JUnit. (, [Test Fixture]) (, @Testcase)
(Testcase Class).  (Testcase Class)
(Test Runner) 
.
(Testcase Class) 
, .
(Testcase Class) (Test Method Discovery)
(Test Method Enumeration).

: (Test Method Discovery)


(Test Method Discovery) 
(Test Automation Framework) 
(Test Method),
(Testcase Class). (Testcase
Class) (Test Method). 

. 421

422

19

(Test Method) (,
test).
(Test Automation Framework) (Testcase Class),
, test (, testCounters), 
(Testcase Object)
(Test Method). , .NET
JUnit, (,
[Test]) (, @Test) $
(Test Method).


,
(Test Method Enumeration) (Test Discovery).
public:
static CppUnit::Test *suite()
{
CppUnit::TestSuite *suite =
new CppUnit::TestSuite("ComplexNumberTest");
suite>addTest(
new CppUnit::TestCaller<ComplexNumberTest>(
"testEquality",
&ComplexNumberTest::testEquality));
suite>addTest(
new CppUnit::TestCaller<ComplexNumberTest>(
"testAddition",
&ComplexNumberTest::testAddition));
return suite;
}

CppUnit. 
.


xUnit, 
(Test Discovery). 
, . 
xUnit , 

(Rename Method). , 
(Test Method).

: (Test Method Discovery)




, , 
. CppUnit
, (Test Method)

. 422

xUnit

423

, .
(Test
Method Discovery).
CPPUNIT_TEST_SUITE_REGISTRATION( FlightManagementFacadeTest);

. 
(Testcase Object). 
TestCaller, .

: (Test Method Discovery)



 , . 
, (Test Method)
(Test Suite Object) .
Java 
, test.
public class TimeDisplayTest extends TestCase {
public void testDisplayCurrentTime_AtMidnight()
throws Exception {
//
TimeDisplay theTimeDisplay = new TimeDisplay();
//
String actualTimeString =
theTimeDisplay.getCurrentTimeAsHtmlFragment();
//
String expectedTimeString =
"<span class=\"tinyBoldText\">Midnight</span>";
assertEquals("Midnight",
expectedTimeString,
actualTimeString);
}
public void testDisplayCurrentTime_AtOneMinuteAfterMidnight()
throws Exception {
//
TimeDisplay actualTimeDisplay = new TimeDisplay();
//
String actualTimeString =
actualTimeDisplay.getCurrentTimeAsHtmlFragment();
//
String expectedTimeString =
"<span class=\"tinyBoldText\">12:01 AM</span>";
assertEquals("12:01 AM",
expectedTimeString,
actualTimeString);
}
}

: (Test Method Discovery)



C# [Test].
(Test Method) CsUnit, NUnit.

. 423

424

19

[Test]
public void testFlightMileage_asKm()
{
//
Flight newFlight = new Flight(validFlightNumber);
newFlight.setMileage(1122);
//
int actualKilometres = newFlight.getMileageAsKm();
int expectedKilometres = 1810;
//
Assert.AreEqual( expectedKilometres, actualKilometres);
}
[Test]
[ExpectedException(typeof(InvalidArgumentException))]
public void testSetMileage_invalidInput_attribute()
{
//
Flight newFlight = new Flight(validFlightNumber);
//
newFlight.setMileage(-1122);
}

: (Testcase Class Discovery)




(Testcase Class) ( NUnit ).
[TestFixture]
public class SampleTestcase
{
}

: (Testcase Class Discovery)


(Testcase Superclass)
Ruby
.rb tests 
require. Test::Unit
, (Testcase Class)
Test::Unit::TestCase.
Dir['tests/*.rb'].each do |each|
require each
end

Dir['tests/*.rb'] . 
each, require each,
(Testcase Class Discovery).
Ruby Test::Unit ,
(Test Method Discovery) .

. 424

xUnit

425

(Test Enumeration)
(Test Runner)
, ?
,
.

testMethod_1

:

(Test Suite Factory)

testMethod_1

Testcase
Class

testMethod_n

testMethod_ n

(Test Method, . 378)


(Testcase Class, . 401) (Test Runner, . 405) 
. (Test Enumeration) 
(Test Discovery, . 420).


(Test Method)
(Test Suite Object, . 414),
(Suite of Suites). 
suite (Testcase Class)
(Test Method Enumeration) (Test Suite Factory) $
(Test Suite Enumeration).


(Test Enumeration) , $
(Test Automation Framework) 
(Test Discovery). , 
(Test Selection),
(Named Test Suite, . 604), 
.

. 425

426

19

xUnit (Test Discovery)


(Test Method), (Testcase Class) 
(Test Enumeration).


(Suite of Suites) (Test Run
ner) . , (Test
Method) (Test Suite Object). ,
(Test Suite Object),
. . 
(Test Method Enumeration)
(Test Suite Enumeration) $
(Test Method Discovery)
(Testcase Class Discovery).

: (Test Suite Enumeration)


xUnit $
(Test Suite Factory), (Suite of Suites) 
( AllSuites), ,
(Test Suite Object) .
. (Factory Method) 
suite. addTest $
(Test Suite Object) .
,
(Lost Test). 
(AllTests Suite)
(Test Runner) 
. , NUnit
(Testcase Class Discovery). ,
(Testcase Class)
(, Ant).
, Java,
(Test Suite Factory)
.
(Test Suite Object) (Testcase Class) $
(Test Suite Factory), .

: (Test Method Enumeration)


xUnit (Test
Method Discovery). ,
(Test Method) (Testcase Class),
(Testcase Object, . 410) (Test Suite
Object). (Test Method Enumeration) 
suite, (Testcase Class).

. 426

xUnit

427

, , 
(Test Automation Framework) $
(Testcase Superclass, . 646)
Include. xUnit $
(Pluggable Behavior) (.
CppUnit).

: (Direct Test Method Invocation)


(Test Method)
. ,
(Test Suite Procedure) .
(Test Method) ( , Test Suite Procedure).

: (Test Method Enumeration)


CppUnit
xUnit
(Test Method) . 
. ,
CppUnit.
public:
static CppUnit::Test *suite()
{
CppUnit::TestSuite *suite =
new CppUnit::TestSuite("ComplexNumberTest");
suite>addTest(
new CppUnit::TestCaller<ComplexNumberTest>(
"testEquality",
&ComplexNumberTest::testEquality));
suite>addTest(
new CppUnit::TestCaller<ComplexNumberTest>(
"testAddition",
&ComplexNumberTest::testAddition));
return suite;
}

, CppUnit (Test Method)


TestCaller (Testcase Object).

: (Test Method)
, VBA
(Visual Basic for Applications  Microsoft Office),
.
Sub TestAllStoryMacros()
Call TestActivitySorting
Call TestStoryHiding
Call ReportSuccess("All Story Macros")
End Sub

. 427

428

19

: (Test Suite Enumeration)


,
(Test Automation Framework) (Test Discove
ry) (Named Test Suite), 
.
(Test Suite Enu
meration)
(Lost Test), (AllTests
Suite). , ,
. ,
, .
public class AllTests {
public static Test suite() {
TestSuite suite = new TestSuite("Test for allJunitTests");
//$JUnit-BEGIN$
suite.addTestSuite(
com.clrstream.camug.example.test.InvoiceTest.class);
suite.addTest(com.clrstream.ex7.test.AllTests.suite());
suite.addTest(com.clrstream.ex8.test.AllTests.suite());
suite.addTestSuite(
com.xunitpatterns.guardassertion.Example.class);
//$JUnit-END$
return suite;
}
}

(,
) . ( Eclipse
.)
, 
(Lost Test) (Test Discovery).

. 428

xUnit

429

(Test Selection)
(Test Runner) , ?
(Test Automation Framework)
(Test Method)
.

testMethod_1

testMethod_n

(Test Method, . 378)


(Testcase Class, . 401) (Test Runner, . 405)
. (Test Selection) 
.


, .
(Testcase
Class) (Test Method).


(Test Selection) ,
, , 
(Test Enumeration, . 425). 
(Smoke Test).
,
(Named Test Suite, . 604).


(Test Selection) $
(Subset Suite) (Test Suite Object,

. 429

430

19

. 414) (Test Suite Object)


(Testcase Object, . 410).
(Test Discovery, . 420)
(Test Enumeration), (Test Selection)
: (Testcase Class) (Test
Method). (Test Selection)
(Test Automation Framework, . 332), 
.

: (Testcase Class Selection)


(Testcase Class)
(Test Method).
(Testcase Class Selection) (Testcase Class)
. ,

(Tests as Documentation, . 79).
,
WebServer, ,
. .
(Test Selection) 
(Test Automation Framework). 
(.NET) (Java) 
(Testcase Class). 
(Test Method).

: (Test Method Selection)


(Test
Automation Framework) (Test Method Selection) 
( ),
(Test Method). (.NET)
(Java) . , 
,
(Test Runner).

: (Testcase Class Selection)



(Testcase Class Selection) 
NUnit. Category("FastSuite") ,
(Testcase Class) ( 
), FastSuite (Test Runner).
[TestFixture]
[Category("FastSuite")]
public class CategorizedTests
{

. 430

xUnit

431

[Test]
public void testFlightConstructor_OK()
//
}

: (Test Method Selection)



(Test Method Selection)
NUnit. Category("SmokeTest") , $
(Test Method) ( )
SmokeTest (Test Runner).
[Test]
[Category("SmokeTests")]
public void testFlightMileage_asKm()
{
//
Flight newFlight = new Flight(validFlightNumber);
newFlight.setMileage(1122);
//
int actualKilometres = newFlight.getMileageAsKm();
int expectedKilometres = 1810;
//
Assert.AreEqual(expectedKilometres, actualKilometres);
}

. 431

. 432

20

20

:

(Inline Setup)....................................................... 434
(Delegated Setup)........................................... 437
(Creation Method) ........................................................... 441
(Implicit Setup)........................................................... 449

(Prebuilt Fixture)..........454
(Lazy Setup) ....................................................................460
(Suite Fixture Setup)...................465
(Setup Decorator)............................................................471
(Chained Tests)..........................................................................477

. 433

434

20

(In/line Setup)
(Fresh Fixture)?
(Test Method)
(Fresh Fixture), .

setup

test_1
test_2

test_n


. (Minimal
Fixture, . 336) (Fresh Fixture,
. 344).
.


(Test Method, . 378) 
, .
(Four
Phase Test, . 387) (Test Method).


(Inline Setup)
. , 
(Delegated Setup, . 437) $
(Implicit Setup, . 449) .

. 434

435

, (Inline Setup)
, , 
. RedGreen
Refactor . 
, .
(Inline Setup)  
. 
(Inline Method) [Ref]
(Creation Method, . 441) setUp. 
(Extract Method) [Ref]
(Creation Method) 
.



, (Inline Setup)
(Implicit Setup) (Delegated Setup), 
(Inline Setup).

: (In/line Setup)
.
(Test Method).
public void testStatus_initial() {
// (In-line Setup)
Airport departureAirport = new Airport("Calgary", "YYC");
Airport destinationAirport = new Airport("Toronto", "YYZ");
Flight flight = new Flight(flightNumber,
departureAirport,
destinationAirport);
//
assertEquals(FlightState.PROPOSED, flight.getStatus());
// :
//

}
public void testStatus_cancelled() {
// (In-line Setup)
Airport departureAirport = new Airport("Calgary", "YYC");
Airport destinationAirport = new Airport("Toronto", "YYZ");
Flight flight = new Flight(flightNumber,
departureAirport,
destinationAirport);
flight.cancel(); //
//
assertEquals(FlightState.CANCELLED, flight.getStatus());
// :
//

}

. 435

436

20


(Inline Setup) , 
. ,
, $
(Mystery Guest; . , Obscure Test, . 230). 
.
,
.
(Inline Method) (Inline Setup).
(Extract Class) [Ref]
. ,
(Extract Method) 
.

. 436

437

(Delegated Setup)
(Fresh Fixture)?
(Test Method)
(Fresh Fixture), (Creation Method).

setUp
test_1
test_2

test_n


. (Minimal
Fixture, . 336) (Fresh Fixture,
. 344). (Test Code Dupli
cation, . 254).
(Delegated Setup)
(Tests as
Documentation, . 79).


(Test Method, . 378) ,
(Creation Method, . 441).
(Tests as Documentation)
(Minimal Fixture) (Creation Method). 
, .
,
, 
.

. 437

438

20


(Delegated Setup) , 
(Test Code Duplication) 
.
(Test Method).
, 
, 
(Test Method). 
(Tests as Documentation)
(Inline Setup, . 434), .
, (Mystery Guest), 
(Creation Method)
(Test Method).
, (Delegated Setup)
(Test Method). , 
(Test Method)
(Testcase Class, . 401) setUp,
(Implicit Setup, . 449).
(Delegated Setup) (Fragile Test, . 277)

(Test Method) $
(Creation Method), .



(Creation Method)
(Extract Method). 
, (Test Code Duplication)
. 
(Creation Method),
, .
(Creation Method)
(Testcase Class). ,
(Abstract Testcase; . , Testcase
Superclass, . 646) (Test Helper, . 651).


, Flight.
.
, .
, , .
, 
.

. 438

439

public void testStatus_initial() {


// (In-line Setup)
Airport departureAirport = new Airport("Calgary", "YYC");
Airport destinationAirport = new Airport("Toronto", "YYZ");
Flight flight = new Flight(flightNumber,
departureAirport,
destinationAirport);
//
assertEquals(FlightState.PROPOSED, flight.getStatus());
// :
//

}
public void testStatus_cancelled() {
// (In-line Setup)
Airport departureAirport = new Airport("Calgary", "YYC");
Airport destinationAirport = new Airport("Toronto", "YYZ");
Flight flight = new Flight(flightNumber,
departureAirport,
destinationAirport);
flight.cancel(); //
//
assertEquals(FlightState.CANCELLED, flight.getStatus());
// :
//

}

(Test Code Duplication).



(Extract Method) 

. (Test Method),
, .
, 
. (Delegated Setup)
(Testcase Class), 
(Pull up method)
(Testcase Superclass) (Move method) $
(Test Helper).

: (Delegated Setup)
,
(Test Method).
, .
public void testGetStatus_initial() {
//
Flight flight = createAnonymousFlight();
//
assertEquals(FlightState.PROPOSED, flight.getStatus());

. 439

440

20

//
//

}
public void testGetStatus_cancelled2() {
//
Flight flight = createAnonymousCancelledFlight();
//
assertEquals(FlightState.CANCELLED, flight.getStatus());
//
//

}

(Creation Method),
, 
.
private int uniqueFlightNumber = 2000;
public Flight createAnonymousFlight() {
Airport departureAirport = new Airport("Calgary", "YYC");
Airport destinationAirport = new Airport("Toronto", "YYZ");
Flight flight =
new Flight(new BigDecimal(uniqueFlightNumber++),
departureAirport,
destinationAirport);
return flight;
}
public Flight createAnonymousCancelledFlight() {
Flight flight = createAnonymousFlight();
flight.cancel();
return flight;
}

. 440

441

(Creation Method)
(Fresh Fixture)?

, .


. (, )
, .

(Obscure Test, . 230) $
(Tests as Documentation, . 79)!

(Inline Setup, . 434)? , .
(Delegated Setup, . 437)
,
. ? (Creation Method) 
,
.


, 
. ! ( ,
, ,
.)
, 
.

. 441

442

20


. (Creation Method).
.
,
. , $
(Creation Method)
.
(Creation Method) , $
(Test Utility Method, . 610). ,
(Creation
Method) . 
(Object Mother; . , Test Helper,
. 651), (Creation Method),
(Test Helper)
(Automated Teardown, . 521).


(Creation Method) , 
(Fresh Fixture, . 344) , 
(Tests as Documentation).
(Creation Method) 

( ). 

(SUT API Encapsulation),
(Fragile Test, . 277) (Obscure Test).
(Creation Method)
, .
, 
, .
,
(factory method), .
(Prebuilt
Fixture, . 454)
(Finder Method; . , Test Utility Method).
(Creation Method) 
,
(Immutable Shared Fixture).
(Creation Method).

: (Parameterized Creation Method)


( )
(Creation Method) , 
. 
. 

. 442

443

, ( , ) 
. $
(Obscure Test).

: (Anonymous Creation Method)


(Anonymous Creation Method) 
(Distinct Generated Value; .
, Generated Value, . 726)
, .
(Unrepeatable Test),
( 
). ,
(Creation Method).
(Anonymous Creation Method)
(Parameterized Anonymous Creation Method).

:
(Parameterized Anonymous Creation Method)
(Parameterized Anonymous Creation
Method) (Creation
Method) 
.
, (Creation Method) ,
.

: , (Named State Reaching Method)


, ..
. , 
, 
.
(Test Method, . 378),
(Eager Test).
(Single Condition Test, . 99). ,
(Test Code Du
plication, . 254).
,
, (Testcase Class) 
setUp (Implicit
Setup, . 449). $
(Testcase Class per Fixture, . 639). 
(Delegated Setup)
(Named State Reaching Method).
(Testcase Class).
.

. 443

444

20

(Named State Reaching Method). 


( , Testcase Class,
, Test Helper)
.

: (Attachment Method)
, 
. , 
.
(Attachment Method). (Creation
Method) (
, Creation Method) .


(Creation Method) 
(Extract Method) .
,
(Creation Method) , . 
(HigherLevel Language, . 95)
. $
(Creation Method).

:
(Reuse Test for Fixture Setup)
, (Test
Method). , , 
. Registry [PEAA],
(Testcase Object, . 410).
(Creation Method) , 
, ,
.
, , 
, . 
. , 
, , (Fake Object, . 565).
(Test Method) (Creation Method)
, (Test Method),
,
. (Creation Method) 
 (Test Method), 
. ,
(Lonely Test), 
, .
,
(Interacting Tests): 

. 444

445

, 
, 
.


testPurchase Customer 
(buyer). 
, Customer.
(G) Customer.
public void testPurchase_firstPurchase_ICC() {
Customer buyer =
new Customer(17, "FirstName", "LastName", "G","ACTIVE");
// ...
}
public void testPurchase_subsequentPurchase_ICC() {
Customer buyer =
new Customer(18, "FirstName", "LastName", "G","ACTIVE");
// ...
}

,
. 

.


(Extract Method) 
. (Creation Method)
createCustomer, .

: (Anonymous Creation Method)


Customer 
(Creation Method).
.
Customer (, ), 
(Creation Method),
. , 
.
public void
Customer
// ...
}
public void
Customer
// ...
}

. 445

testPurchase_firstPurchase_ACM() {
buyer = createAnonymousCustomer();
testPurchase_subsequentPurchase_ACM() {
buyer = createAnonymousCustomer();

446

20

(Anonymous Creation Method),


. (Anonymous
Creation Method) , .
public Customer createAnonymousCustomer() {
int uniqueid = getUniqueCustomerId();
return new Customer(uniqueid,
"FirstName" + uniqueid,
"LastName" + uniqueid,
"G", "ACTIVE");
}

(Distinct
Generated Value), Customer
.

: (Parameterized Creation Method)


Customer 
, (Parameterized Creation
Method).
public void testPurchase_firstPurchase_PCM() {
Customer buyer =
createCreditworthyCustomer("FirstName", "LastName");
// ...
}
public void testPurchase_subsequentPurchase_PCM() {
Customer buyer = createCreditworthyCustomer("FirstName", "LastName");
// ...
}


(Parameterized Creation Method).
public Customer createCreditworthyCustomer(
String firstName, String lastName) {
int uniqueid = getUniqueCustomerId();
Customer customer =
new Customer(uniqueid,firstName,lastName,"G","ACTIVE");
customer.setCredit(CreditRating.EXCELLENT);
customer.approveCredit();
return customer;
}

: (Attachment Method)
, (Attachment Method)
.
public void testPurchase_relatedCustomerDiscount_AM() {
Customer buyer = createCreditworthyCustomer("Related", "Buyer");
Customer discountHolder =

. 446

447

createCreditworthyCustomer("Discount", "Holder");
createRelationshipBetweenCustomers(buyer, discountHolder);
// ...
}

(Attachment Method)
.
private void createRelationshipBetweenCustomers(
Customer buyer,
Customer discountHolder) {
buyer.addToRelatedCustomersList(discountHolder);
discountHolder.addToRelatedCustomersList(buyer);
}

, , 
, .

:
(Reuse Tests For Fixture Setup)
. 
, .
private Customer buyer;
private AccountManager sut = new AccountManager();
private Account account;
public void testCustomerConstructor_SRT() {
//
buyer = new Customer(17, "First", "Last", "G", "ACTIVE");
//
assertEquals("First", buyer.firstName(), "first");
// ...
}
public void testPurchase_SRT() {
testCustomerConstructor_SRT(); // "buyer"
account = sut.createAccountForCustomer(buyer);
assertEquals(buyer.name, account.customerName, "cust");
// ...
}

. , $
(Test Method) ,
(, Customer buyer). , Customer; .
, (Test Method)
(Testcase Class). ,
buyer . 
(Creation Method).
private Customer buyer;
private AccountManager sut = new AccountManager();
private Account account;
public void testCustomerConstructor_RTCM() {

. 447

448

20

//
buyer = new Customer(17, "First", "Last", "G", "ACTIVE");
//
assertEquals("First", buyer.firstName(), "first");
// ...
}
public void testPurchase_RTCM() {
buyer = createCreditworthyCustomer();
account = sut.createAccountForCustomer(buyer);
assertEquals(buyer.name, account.customerName, "cust");
// ...
}
public Customer createCreditworthyCustomer() {
testCustomerConstructor_RTCM();
return buyer;
// ...
}

, . 
buyer . , $
(Test Method) .
(Creation Method)
(Testcase Class) , 
, .

. 448

449

(Implicit Setup)

(Fresh Fixture)?

setUp.

setup

:

(Hooked Setup),
(Framework-Invoked Setup),

(Shared Setup Method)

test_1
test_2

test_n


. (Fresh Fixture,
. 344) (Minimal Fixture, . 336)
.
(Implicit Setup)
(Test Method, . 378)
(Testcase Class, . 401).


(Testcase Class)
(Fresh Fixture) setUp.
(Test Automation
Framework, . 332) (Test Method).

. ,
(Test

. 449

450

20

Method), (Inline Setup, . 434) $


(Delegated Setup, . 437).


(Implicit Setup) ,
(Test Method) (Testcase Class)
(Fresh Fixture). (Test Method)
, (Minimal Fixture)
setUp.
(Test Method) (Testcase
Class per Fixture, . 639).
(Test Method) 
(Testcase Class per Feature,
. 633) (Testcase Class per Class, . 627), 
(Implicit Setup)
(Minimal Fixture) . setUp 
,
. $
(Implicit Setup) , ,
, ( )
(Test Method). ,

, , , 
. , 
, (Test
Method), , (Test Method)
.
(Fresh Fix
ture) (Inline Setup), 
(Test Method), $
(Delegated Setup), 
(Creation Method),
(Test Method).
(Implicit Setup) $
(Test Code Duplication, . 254)
(Fragile Test, . 277), 

, .
(Obscure Test, . 230), $
(Mystery Guest) 
. , 
, $
(Fragile Fixture).

. 450

451


(Implicit Setup).

setUp?

(Test Method) ?


setUp 
(Implicit Setup). (Test Automation Frame!
work) setUp (Test
Method). , setUp !
. , (Suite Fix!
ture Setup, . 465)
(Shared Fixture, . 350), (Test Method)
(Testcase Class). , (Setup
Decorator, . 471) setUp Decorator,
(Test Suite Object, . 414) (Test Run!
ner, . 405). , (Implicit
Setup), setUp (Test Method).


(Implicit
Teardown, . 533). , setUp 
(Automated Teardown, . 521) ,
tearDown.


(Test Method) ,
setUp.
. setUp (Test Method) !
. !
, 
(Shared Fixture). . 411
, .)



.
public void testStatus_initial() {
// (In-line Setup)
Airport departureAirport = new Airport("Calgary", "YYC");
Airport destinationAirport = new Airport("Toronto", "YYZ");

. 451

452

20

Flight flight = new Flight(flightNumber,


departureAirport,
destinationAirport);
//
assertEquals(FlightState.PROPOSED, flight.getStatus());
//
//

}
public void testStatus_cancelled() {
// (In-line Setup)
Airport departureAirport = new Airport("Calgary", "YYC");
Airport destinationAirport = new Airport("Toronto", "YYZ");
Flight flight = new Flight(flightNumber,
departureAirport,
destinationAirport);
flight.cancel(); //
//
assertEquals(FlightState.CANCELLED, flight.getStatus());
//
//

}



(Test Code Duplication). ,
(Testcase Class) (Implicit
Setup). .
, ,
, setUp, 
(Extract Method) setUp
. , 
, 
(Test Method).
(Testcase Class) setUp
, 
.
(Extract Class) (Test Method) 
setUp . , ,
setUp (Test
Method), setUp. 
(Testcase Class)
.

: (Implicit Setup)
, 
setUp (Testcase Class).
.

. 452

453

Airport departureAirport;
Airport destinationAirport;
Flight flight;
public void setUp() throws Exception{
super.setUp();
departureAirport = new Airport("Calgary", "YYC");
destinationAirport = new Airport("Toronto", "YYZ");
BigDecimal flightNumber = new BigDecimal("999");
flight = new Flight(flightNumber , departureAirport,
destinationAirport);
}
public void testGetStatus_initial() {
// (Implicit Setup)
//
assertEquals(FlightState.PROPOSED, flight.getStatus());
}
public void testGetStatus_cancelled() {
//
flight.cancel();
//
assertEquals(FlightState.CANCELLED, flight.getStatus());
}

,
(Test Method) $
(Testcase Class per Fixture). (
(Testcase Class per Feature).) (Test Method)
(Testcase Class) 
( ), 
. ,
, . 
flight? ? 
, , 
.

. 453

454

20

(Prebuilt Fixture)
:

(Prebuilt Context),
(Test Bed)


(Shared Fixture)
?
(Shared Fixture)
.


(Shared Fixture, . 350), .


 .
,
. 
,
, .


,
(Shared Fixture) 
. ,
(Shared Fixture) .
 (Manual Intervention, . 287),
( ) , 
, $
(Erratic Test, . 267)  .
, (Prebuilt
Fixture) (Immutable Shared Fixture)

. 454

455

(Fresh Fixture, . 344) 


.
(Prebuilt Fixture) 
(Shared Fixture),
, (Fresh Fixture). 
(Suite Fixture Setup,
. 465), (Lazy Setup, . 460) (Setup Deco
rator, . 471). (Fresh Fixture) 
(Inline Setup, . 434), (Implicit Setup, . 449) 
(Delegated Setup, . 437).

: (Global Fixture)
(Prebuilt
Fixture), .
,
.
(Database Sandbox, . 658) 
(Database Partitioning Scheme).

(Prebuilt Fixture). 
. 

(Test Runner, . 405) ,
. 
(Test Run War) 
. , (Database
Partitioning Scheme) (Distinct Generated Value)
.


,
(Shared Fixture). .
(Testcase Class, . 401),
(Setup Decorator)
(Suite Fixture Setup). , , 
, ,
(Data Loader)
(Database Population Script). (Back Door
Setup) 
. (. ?
. 367 , 
.) 
(Fixture Setup Testcase; . , Chained Tests, . 477),
(Test Runner).

. 455

456

20

(Finder Method).

(Test Fixture Registry),
. 
:
1) ,
, (Test Fixture Registry)
( ), (Finder Method) 
;
2) (Finder Method).
/, (Finder Method), 
, $
(Nondeterministic Test), 
/
(Prebuilt Fixture). , 
. 
,

.


(Shared Fix
ture) (Lazy Setup). (, 
(Shared Fixture), $
(Setup Decorator) (Suite
Fixture Setup).)
protected void setUp() throws Exception {
if (sharedFixtureInitialized) {
return;
}
facade = new FlightMgmtFacadeImpl();
setupStandardAirportsAndFlights();
sharedFixtureInitialized = true;
}
protected void tearDown() throws Exception {
// ,
// ,
}

setupStandardAirports setUp. 
(Finder Method),
, .
public void testGetFlightsByFromAirport_OneOutboundFlight()
throws Exception {
FlightDto outboundFlight = findOneOutboundFlight();
//

. 456

457

List flightsAtOrigin = facade.getFlightsByOriginAirport(


outboundFlight.getOriginAirportId());
//
assertOnly1FlightInDtoList("Flights at origin",
outboundFlight,
flightsAtOrigin);
}
public void testGetFlightsByFromAirport_TwoOutboundFlights()
throws Exception {
FlightDto[] outboundFlights =
findTwoOutboundFlightsFromOneAirport();
//
List flightsAtOrigin = facade.getFlightsByOriginAirport(
outboundFlights[0].getOriginAirportId());
//
assertExactly2FlightsInDtoList("Flights at origin",
outboundFlights,
flightsAtOrigin);
}


(Testcase Class) 
(Standard Fixture, . 338) 
(Prebuilt Fixture) 
(Extract Class).
, (Test Method, . 378)
. , (Finder Method) 
, , 
, 
.

:
(Prebuilt Fixture Test)
(Testcase Class),
(Test Method). ,
, (Shared Fixture).
public void testGetFlightsByFromAirport_OneOutboundFlight()
throws Exception {
FlightDto outboundFlight = findOneOutboundFlight();
//
List flightsAtOrigin = facade.getFlightsByOriginAirport(
outboundFlight.getOriginAirportId());
//
assertOnly1FlightInDtoList("Flights at origin",
outboundFlight,
flightsAtOrigin);
}
public void testGetFlightsByFromAirport_TwoOutboundFlights()
throws Exception {
FlightDto[] outboundFlights =

. 457

458

20

findTwoOutboundFlightsFromOneAirport();
//
List flightsAtOrigin = facade.getFlightsByOriginAirport(
outboundFlights[0].getOriginAirportId());
//
assertExactly2FlightsInDtoList("Flights at origin",
outboundFlights,
flightsAtOrigin);
}


(Finder Method).

: (Fixture Setup Testcase)


(Prebuilt
Fixture) xUnit. ,
(Creation Method, . 441) 
(Database Sandbox).
setUp , , 
setUp (Fixture
Setup Testcase). ,
(Prebuilt Fixture).
public class FlightManagementFacadeSetupTestcase
extends AbstractFlightManagementFacadeTestCase {
public FlightManagementFacadeSetupTestcase(String name) {
super(name);
}
protected void setUp() throws Exception {
facade = new FlightMgmtFacadeImpl();
helper = new FlightManagementTestHelper();
setupStandardAirportsAndFlights();
saveFixtureInformation();
}
protected void tearDown() throws Exception {
//
}
}

, (Testcase Class)
(Test Method) tearDown . 
 .

saveFixtureInformation.
. 
$
(Test Method) (Test Utility Method). 

. ,
.

. 458

459

: ,

$
(Prebuilt Fixture)
(Database Sandbox)  SQL Perl Ruby.
. 
(Database
Sandbox). .

. 459

460

20

(Lazy Setup)
(Shared Fixture)
?

.

setUp

testMethod_1

testMethod_n

(Shared Fixture, . 350) 



. , , 
, ; (Lonely Test; .
, Erratic Test, . 267).
, $
(Lazy Setup) .


(Lazy Initialization) [SBPP]
, . 
, .
, 
.


(Lazy Setup) ,
(Shared Fixture),
. , (Lazy Setup)
, $
(Setup Decorator, . 471)

. 460

461

(Suite Fixture Setup, . 465), 


. , (Lazy Setup) , 
(GarbageCollected Teardown,
. 518). , (Lazy Setup) $
(Distinct Generated Value)
, . 
$ (Delta Assertion, . 505).
(Lazy Setup) 
, .
xUnit
( (Setup Decorator) 
). $
(Suite Fixture Setup), NUnit, VbUnit JUnit 4.0, setUp/
tearDown (Testcase Class, . 402). , 
Ruby, Python PL/SQL.
(Test Runner, . 405)
.

. 
(Lazy Setup) .
(Prebuilt Fixture, . 454)
(Shared Fixture) 
.
(Unrepeatable Test), .


(Lazy Setup) $
(Shared Fixture), ,
.
(Lazy Setup)
(Shared Fixture) (Testcase Class).
. , 
(Testcase Class). 
(Testcase
Superclass, . 646), 
.
(Test Helper, . 651).
, , (Test Method, . 378) ,
.
, (Testcase Object, . 410)
(Test Suite Object, . 414),
tearDown. , 
! (Test Runner) 
tearDown (Test Suite Object)
(Suite Fixture Setup).

. 461

462

20



(Testcase Object).
public void testGetFlightsByFromAirport_OneOutboundFlight()
throws Exception {
setupStandardAirportsAndFlights();
FlightDto outboundFlight = findOneOutboundFlight();
//
List flightsAtOrigin = facade.getFlightsByOriginAirport(
outboundFlight.getOriginAirportId());
//
assertOnly1FlightInDtoList("Flights at origin",
outboundFlight,
flightsAtOrigin);
}
public void testGetFlightsByFromAirport_TwoOutboundFlights()
throws Exception {
setupStandardAirportsAndFlights();
FlightDto[] outboundFlights =
findTwoOutboundFlightsFromOneAirport();
//
List flightsAtOrigin = facade.getFlightsByOriginAirport(
outboundFlights[0].getOriginAirportId());
//
assertExactly2FlightsInDtoList("Flights at origin",
outboundFlights,
flightsAtOrigin);
}

, 
. 
setUp (. , Implicit
Setup, . 449).
protected void setUp() throws Exception {
facade = new FlightMgmtFacadeImpl();
helper = new FlightManagementTestHelper();
setupStandardAirportsAndFlights();
oneOutboundFlight = findOneOutboundFlight();
}
protected void tearDown() throws Exception {
removeStandardAirportsAndFlights();
}
public void testGetFlightsByOriginAirport_NoFlights_td()
throws Exception {
//
BigDecimal outboundAirport = createTestAirport("1OF");
try {
//
List flightsAtDestination1 =
facade.getFlightsByOriginAirport(outboundAirport);
//
assertEquals(0,flightsAtDestination1.size());

. 462

463

} finally {
facade.removeAirport(outboundAirport);
}
}
public void testGetFlightsByFromAirport_OneOutboundFlight()
throws Exception {
//
List flightsAtOrigin = facade.getFlightsByOriginAirport(
oneOutboundFlight.getOriginAirportId());
//
assertOnly1FlightInDtoList("Flights at origin",
oneOutboundFlight,
flightsAtOrigin);
}
public void testGetFlightsByFromAirport_TwoOutboundFlights()
throws Exception {
FlightDto[] outboundFlights =
findTwoOutboundFlightsFromOneAirport();
//
List flightsAtOrigin = facade.getFlightsByOriginAirport(
outboundFlights[0].getOriginAirportId());
//
assertExactly2FlightsInDtoList("Flights at origin",
outboundFlights,
flightsAtOrigin);
}

, $
(Test Automation Framework) setUp tearDown
(Testcase Object).
.
.


,
(Lazy Setup).
setUp,
, 
. tearDown,
, 
(Test Method)! ,
xUnit (Suite Fixture Setup),
.

: (Lazy Setup)
, $
(Lazy Setup).
protected void setUp() throws Exception {
if (sharedFixtureInitialized) {
return;

. 463

464

20

}
facade = new FlightMgmtFacadeImpl();
setupStandardAirportsAndFlights();
sharedFixtureInitialized = true;
}
protected void tearDown() throws Exception {
// , ,
//
}

tearDown AirportFixture , ,
! (Lazy Setup).
, . 
, 
.
(Implicit Setup).
public void testGetFlightsByFromAirport_OneOutboundFlight()
throws Exception {
FlightDto outboundFlight = findOneOutboundFlight();
//
List flightsAtOrigin = facade.getFlightsByOriginAirport(
outboundFlight.getOriginAirportId());
//
assertOnly1FlightInDtoList("Flights at origin",
outboundFlight,
flightsAtOrigin);
}
public void testGetFlightsByFromAirport_TwoOutboundFlights()
throws Exception {
FlightDto[] outboundFlights =
findTwoOutboundFlightsFromOneAirport();
//
List flightsAtOrigin = facade.getFlightsByOriginAirport(
outboundFlights[0].getOriginAirportId());
//
assertExactly2FlightsInDtoList("Flights at origin",
outboundFlights,
flightsAtOrigin);
}

. 464

465

(Suite Fixture Setup)


(Shared Fixture)
?
/ ,
(Test Automation Framework)
.
SuiteFixture setUp

SuiteFixture tearDown

(Shared Fixture, . 350) 


.

,
. 
.
(Suite Fixture Setup) 
, (Test
Method, . 378) (Testcase Class, . 401).


(Test Automation Framework, . 332) 
, .
xUnit,
:
(Suite Fixture Setup) setUp
(Test Method). (Suite Fixture Teardown) 
tearDown (Test
Method). ( , /

. 465

466

20

(Testcase Object), : NUnit


(Testcase Object).
. 411.)


(Suite Fixture Setup)
, $
(Test Method) (Testcase Class),
xUnit . ,
.
VbUnit, NUnit JUnit 4.0
(Suite Fixture Setup).
xUnit.
, 
(Prebuilt Fixture,
. 454), (Setup Decorator, . 471) (Lazy
Setup, . 460). 
, , (Implicit Setup, . 449)
(Delegated Setup, . 437).
(Shared Fixture)
(Suite Fixture Setup) 
(Slow Tests, . 289), 
, . ,
(Shared Fixture)
(Interacting Tests) (Test Run War). 

. 351.


(Suite Fix
ture Setup)
(Test Method). 
, Registry [PEAA] Singleton [GOF]
( NUnit,
. 411). 
xUnit. .

. 466

VbUnit (Testcase Class) IFixtureFrame, (Test Automation Frame


work) IFixtureFrame_Create
(Test Method) IFixtureFrame_Destroy 
.

NUnit [TestFixtureSetUp] [TestFixtureTearDown]




467

.
.

JUnit 4.0 @BeforeClass


, (Test
Method). @AfterClass 
. JUnit 
.
.

$
(Suite Fixture Setup) , 
(Implicit Setup). $
(Creation Method, . 441) 
(Suite Fixture Setup).
, ,
, (Testcase Superclass, . 646)
(Test Helper, . 651).


, .
[SetUp]
protected void setUp() {
helper.setupStandardAirportsAndFlights();
}
[TearDown]
protected void tearDown() {
helper.removeStandardAirportsAndFlights();
}
[Test]
public void testGetFlightsByOriginAirport_2OutboundFlights(){
FlightDto[] expectedFlights =
helper.findTwoOutboundFlightsFromOneAirport();
long originAirportId = expectedFlights[0].OriginAirportId;
//
IList flightsAtOrigin =
facade.GetFlightsByOriginAirport(originAirportId);
//
AssertExactly2FlightsInDtoList(
expectedFlights[0], expectedFlights[1],
flightsAtOrigin, "Flights at origin");
}
[Test]
public void testGetFlightsByOriginAirport_OneOutboundFlight(){
FlightDto expectedFlight = helper.findOneOutboundFlight();
//
IList flightsAtOrigin = facade.GetFlightsByOriginAirport(
expectedFlight.OriginAirportId);
//
AssertOnly1FlightInDtoList( expectedFlight,
flightsAtOrigin, "Outbound flight at origin");
}

. 467

468

20

. 20.1 .
-------------------setUp
setupStandardAirportsAndFlights
testGetFlightsByOriginAirport_OneOutboundFlight
tearDown
removeStandardAirportsAndFlights
-------------------setUp
setupStandardAirportsAndFlights
testGetFlightsByOriginAirport_TwoOutboundFlights
tearDown
removeStandardAirportsAndFlights
-------------------. 20.1. (Test Method)
(Implicit Setup). setupStandardAirportsAndFlights
.


,
(Shared Fixture).
, (Lazy Setup). 

(Suite Fixture Setup), setUp
tearDown suiteFixtureSetUp suiteFixtureTearDown .
NUnit $
(Test Automation Framework) [TestFixtureSetUp] [TestFixtureTearDown]. setUp/tearDown 
, [Setup] [TearDown] [TestFixtureSetUp] [TestFixtureTearDown] .

: (Suite Fixture Setup)


$
(Suite Fixture Setup).
[TestFixtureSetUp]
protected void suiteFixtureSetUp()
{
helper.setupStandardAirportsAndFlights();
}
[TestFixtureTearDown]
protected void suiteFixtureTearDown() {
helper.removeStandardAirportsAndFlights();
}
[SetUp]
protected void setUp() {
}
[TearDown]

. 468

469

protected void tearDown()


{
}
[Test]
public void testGetFlightsByOrigin_TwoOutboundFlights(){
FlightDto[] expectedFlights =
helper.findTwoOutboundFlightsFromOneAirport();
long originAirportId = expectedFlights[0].OriginAirportId;
//
IList flightsAtOrigin =
facade.GetFlightsByOriginAirport(originAirportId);
//
AssertExactly2FlightsInDtoList(
expectedFlights[0], expectedFlights[1],
flightsAtOrigin, "Flights at origin");
}
[Test]
public void testGetFlightsByOrigin_OneOutboundFlight() {
FlightDto expectedFlight = helper.findOneOutboundFlight();
//
IList flightsAtOrigin = facade.GetFlightsByOriginAirport(
expectedFlight.OriginAirportId);
//
AssertOnly1FlightInDtoList(expectedFlight,
flightsAtOrigin, "Outbound flight at origin");
}

, (Testcase Class),
(. 20.2).
suiteFixtureSetUp
setupStandardAirportsAndFlights
-----------------setUp
testGetFlightsByOriginAirport_OneOutboundFlight
tearDown
-----------------setUp
testGetFlightsByOriginAirport_TwoOutboundFlights
tearDown
-----------------suiteFixtureTearDown
removeStandardAirportsAndFlights
. 20.2.
(Suite Fixture Setup). setupStandardAndAirportsAndFlights (Testcase Class),
(Test Method).

setUp (Test Method).


suiteFixtureSetUp, setupStandardAirportsAndFlights . 
(Lazy Setup).

. 469

470

20

removeStandardAirportsAndFlights
.


, 
xUnit . 

Microsoft Java/Pearl/
Ruby .. (Suite Fixture Setup)
(Shared Fixture). 

(Testcase Class), (Test Suite
Object, . 414). , (Test Suite Object),
.



(Suite Fixture Setup) VbUnit :
http://www.vbunit.com/doc/Advanced.htm

NUnit 
nunit.org.

. 470

471

(Setup Decorator)
(Shared Fixture)
?
,
/
.

setUp

tearDown

(Shared Fixture,
. 350), 
(Prebuilt Fixture, . 454) , 
. 
(Lazy Setup),
. 
? , 
?


(Setup Decorator) 
setUp tearDown.
Decorator. (Setup Decorator)
(Test Suite Object, . 414), $
(Test Runner, . 405). , $
(Test Runner) run (Setup
Decorator), (Test Suite Object). $
(Setup Decorator) 

. 471

472

20

run (Test Suite Object). 


run .


(Setup Decorator) ,
(Shared Fixture) 
.
, (HardCoded
Value),
(. , Unrepeatable Test).
,
.
, (Setup Decorator) 

. 
(Fake Database) 
(Slow Tests, . 289).

. (Setup Decorator) ,

( ).

(Testcase Class, . 401),
(Setup Decorator) $
(Suite Fixture Setup, . 465) ( xUnit
). ,
(Lazy Setup).


(Setup Decorator) , 
, 
.
setUp,  tearDown.
run (Setup Decorator) .
void run() {
setup();
decoratedSuite.run();
teardown();
}

(Setup Decorator).

: (Abstract Setup Decorator)


xUnit ,
(Setup Decorator). setUp/run/tearDown 

. 472

473

Template Method. 
setUp tearDown, (Testcase Class). 
(Setup Decorator)
(Test Suite Object) .

: (Hard/Coded Setup Decorator)


(Setup Decorator) ,

suite (Setup Decorator). $
(Setup Decorator) (Test Suite
Factory) .

: (Parameterized Setup Decorator)


(Setup Decorator)
,
(Test Suite Object). ,
(Setup Decorator) $
(Test Helper, . 651) 
.

: (Decorated Lazy Setup)


(Setup Decorator) 
, $
(Setup Decorator), .
, (Lazy Setup) setUp,
(Testcase Object, . 410) 
. , (Testcase Object) 
tearDown.
(Testcase Superclass, . 646).
.

(Pushdown Decorator), 
(Shared Fixture).
(Pushdown Decorator) ,
(Setup Decorator) 
(Shared Fixture).

: (Pushdown Decorator)
(Setup Deco
rator) ,
, . 

. , 
(Setup Decorator)

. 473

474

20

(Testcase Object), (Test Discovery,


. 420). (Test Method,
. 378), (Setup Decorator)
(Test Suite Object).
, , !
(Setup Decorator), !
.
. 351.


(Lazy
Setup) (Shared Fixture)
(Finder Method) . ,
(Unrepeatable Test), !
.
protected void setUp() throws Exception {
if (sharedFixtureInitialized) {
return;
}
facade = new FlightMgmtFacadeImpl();
setupStandardAirportsAndFlights();
sharedFixtureInitialized = true;
}
protected void tearDown() throws Exception {
// , ,
//
}


(Lazy Setup), .
(Setup Decorator).


(Setup Decorator)
. !
. , , ,
setUp (Testcase Class) setUp
(Setup Decorator). ,
(Abstract Setup Decorator). !
setUp tearDown.
xUnit
(Setup Decorator), !
!
. Extract Superclass [Ref]
.

. 474

475

: (Hard/Coded Setup Decorator)


setUp $
(Setup Decorator), $
(Abstract Setup Decorator).
tearDown.
public class FlightManagementTestSetup extends TestSetup {
private FlightManagementTestHelper helper;
public FlightManagementTestSetup() {
// (Test Suite Object)
//
// (Abstract Setup Decorator)
super( SafeFlightManagementFacadeTest.suite() );
helper = new FlightManagementTestHelper();
}
public void setUp() throws Exception {
helper.setupStandardAirportsAndFlights();
}
public void tearDown() throws Exception {
helper.removeStandardAirportsAndFlights();
}
public static Test suite() {
//
return new FlightManagementTestSetup();
}
}

(HardCoded Setup Decorator),


(Test Suite Factory) (Test
Suite Object) . suite .

:
(Parameterized Setup Decorator)
(Setup Decorator)
, $
(Introduce parameter) (Test Suite
Factory) .
public class ParameterizedFlightManagementTestSetup extends TestSetup {
private FlightManagementTestHelper helper =
new FlightManagementTestHelper();
public ParameterizedFlightManagementTestSetup(
Test testSuiteToDecorate) {
super(testSuiteToDecorate);
}
public void setUp() throws Exception {
helper.setupStandardAirportsAndFlights();
}
public void tearDown() throws Exception {
helper.removeStandardAirportsAndFlights();
}
}

. 475

476

20


(Test Runner) (Test Suite Factory),
(Setup Decorator) $
(Test Suite Object) .
public class DecoratedFlightManagementFacadeTestFactory {
public static Test suite() {
//
return new ParameterizedFlightManagementTestSetup(
SafeFlightManagementFacadeTest.suite());
}
}

(Test Suite
Factory).  $
(Setup Decorator).

: (Abstract Decorator Class)


.
public class TestSetup extends TestCase {
Test decoratedSuite;
AbstractSetupDecorator(Test testSuiteToDecorate) {
decoratedSuite = testSuiteToDecorate;
}
public void setUp() throws Exception {
//
}
public void tearDown() throws Exception {
//
}
void run() {
setup();
decoratedSuite.run();
teardown();
}
}

. 476

477

(Chained Tests)
(Shared Fixture)
?
.

Fixture

(Shared Fixture, . 350) 


. 
,
. 
()
.
(Chained Tests) 
, .


(Chained Tests) 
. 
 

. 
, (SelfChecking Test,
. 81), , , 
.
(Reuse Test for Fixture Setup),
(Test Method, . 378) . ,

. 477

478

20

,
.


(Chained Tests) . 
,
(Interacting Tests; . , Erratic Test, . 267),
.  
, 
(Shared Fixture) (Slow Tests, . 289).
, 
. 
. $
(Chained Tests) , 
.
(Independent Tests, . 96).
(Chained Tests) $
(Fragile Test, . 277),
(SUT API Encapsulation).
,
.
(Fragile Fixture),
. 
, , . ,
.
(Shared Fixture) 
, .
(Chained Tests) 
. xUnit 
( TestNG).
, xUnit
(Test Method) (
xUnit (Testcase Object, . 410) ).
, $
(Lonely Test), 
. , , 
. 
.

, 
(Mystery Guest; . , Obscure Test, . 230).
, (Finder
Method)
(Shared Fixture). , (Test Method)
(Testcase Class, . 401) ,
.

. 478

479

: (Fixture Setup Testcase)


(Shared Fixture)
 , (Lazy Setup,
. 460), (Suite Fixture Setup, . 465) $
(Setup Decorator, . 471),  $
(Fixture Setup Testcase) .
, (Test Enumeration, . 425).
addTest (Test
Suite Factory).
(Chained Tests), $
(Fixture Setup Testcase).


(Chained Tests) :

, .

xUnit
, 
.
. , 
(Test Method) 
(
). $
(Test Enumeration)
(Testcase Object) .
, , 
.
(Test Method) (Testcase Class), 
( 
, 
;
. 411).
(Test Method)
(Testcase Class), (Suite of Suites),
.
(Test Fixture Registry) 
. .
, , 
. $
(Chained Tests) (Fresh
Fixture, . 344).

. 479

480

20


(Tabular Test),
(Clint Shank).
public class TabularTest extends TestCase {
private Order order = new Order();
private static final double tolerance = 0.001;
public void testGetTotal() {
assertEquals("initial", 0.00, order.getTotal(), tolerance);
testAddItemAndGetTotal("first", 1, 3.00, 3.00);
testAddItemAndGetTotal("second",3, 5.00, 18.00);
// ..
}
private void testAddItemAndGetTotal(String msg,
int lineItemQuantity,
double lineItemPrice,
double expectedTotal) {
//
LineItem item = new LineItem(lineItemQuantity, lineItemPrice);
//
order.addItem(item);
//
assertEquals(msg,expectedTotal,order.getTotal(),tolerance);
}
}

, 
, (. 20.3). 
, 
, . , ,
. , 
, ?


(Tabular Test) (Chained
Tests), (Test Method) ,
. 
(Extract Method).
(Introduce field) 
(Extract Method). (Test
Method)
(Test Automation Framework, . 332)
(Test Method) . ( ,
.
. 
(Shared Fixture)
(Test Method).)
. JUnit,
, (Testcase Object) , 
, .

. 480

481

. 20.3. (Tabular Test).


,
. $

, (Fresh Fixture)
(Shared Fixture). order ( 
) (
Java), order.

: (Chained Tests)
.
private static Order order = new Order();
private static final double tolerance = 0.001;
public void test_01_initialTotalShouldBeZero() {
assertEquals("initial", 0.00, order.getTotal(), tolerance);
}
public void test_02_totalAfter1stItemShouldBeOnlyItemAmount(){
testAddItemAndGetTotal("first", 1, 3.00, 3.00);
}
public void test_03_totalAfter2ndItemShouldBeSumOfAmounts() {
testAddItemAndGetTotal("second",3, 5.00, 18.00);
}
private void testAddItemAndGetTotal(String msg,
int lineItemQuantity,
double lineItemPrice,

. 481

482

20

double expectedTotal) {
//
LineItem item =
new LineItem(lineItemQuantity, lineItemPrice);
//
order.addItem(item);
//
assertEquals(msg,expectedTotal,order.getTotal(),tolerance);
}

(Test Runner, . 405) , ,


 (. 20.4).
, ,
(Lonely Test).

. 20.4. (Chained Tests).


, .

. 482

21

21

:

(State Verification).................................................... 484
(Behavior Verification) ............................................. 489

(Custom Assertion) ......................................... 495
 (Delta Assertion) ....................................................... 505
(Guard Assertion).............................................. 510
(Unfinished Test Assertion) .............. 514

. 483

484

21

(State Verification)
,
?

:

(State-Based Testing)

B
A

(/

(SelfChecking Test, . 81) 


.
? 
. ,
.
.
(State Verification) 
.


.

. 
(Assertion Method, . 390).

, . 
, .
.

. 484

485

(TestSpecific Subclass, . 592)


(Test Logic
in Production, . 257).
: ?
,  ,
. (State Verification)
( , Layer
Crossing Test). , (Behavior Verification, . 489) 
.


(State Verification) , 
, , 
.
.
(State Verification)
, .. 
,
. ,
(Test Stub, . 544) . 
(Production Bugs, . 303), 
.
.
,
,  , 
(Behavior Verification) .
,
(Fragile Test, . 277).


(State Verification).

: (Procedural State Verification)


(Procedural State Verification) 
(Assertion Method),

.
. 
(Obscure Test, . 230),
, .

(Test Method, . 378),
(Test Code Duplication, . 254).

. 485

486

21

: (Expected State Specification)



.

.
$
(Equality Assertion). 
. (Expected State Specification)
,
,
. ,
(Expected State Specifi
cation). ,
, ,
. Fit 
. , DbUnit, 
(Back Door Ma
nipulation, . 359) .
(Expected State Specification)

(Parameterized Creation Method), ,
. (Expected
State Specification) ,
. ,
,
equals ,
(Expected State Specification) .
(Custom Assertion, . 495),
. ,
(Expected State Specification) 
, .
(TestSpecific Subclass), 
equals ,
equals(TheRealObjectClass other). 
equals (
, Equality Pollution). 
, (Fake Object, . 565)
equals, .
, (Equality Asser
tion) 
, .
(Expected State Specification)

(Equality Assertion) . 
(Expected State Specification)
$
:

(Expected Object)

. 486

487

(Derived Value, . 722) .



(Expected State Specification) , , ,
(Tests as Documentation, . 79). 
,
, (Creation Method).


,
. , (Self
Checking Test). (
(State Verification) (Behavior Verification).
, (Behavior Verification),
, ,
(State Verification).)
public void testInvoice_addOneLineItem_quantity1() {
//
inv.addItemQuantity(product, QUANTITY);
}

invoice product setUp


(Implicit Setup, . 450).
public void setUp() {
product = createAnonProduct();
anotherProduct = createAnonProduct();
inv = createAnonInvoice();
}


, 
( ): , 
.
(Procedural State Verification), (Test Method)
(Assertion Method).
,
(Expected Object). (Expected Object)
(Test Double, . 538).
, . 
(Equality Asser
tion), (Expected Object). 
, $
(Custom Assertion).

. 487

488

21

: (Procedural State Verification)


(Test Method) , 
(SelfChecking Test).
, $
(Obscure Test).
public void testInvoice_addOneLineItem_quantity1() {
//
inv.addItemQuantity(product, QUANTITY);
//
List lineItems = inv.getLineItems();
assertEquals("number of items", lineItems.size(), 1);
//
LineItem actual = (LineItem) lineItems.get(0);
assertEquals(inv, actual.getInv());
assertEquals(product, actual.getProd());
assertEquals(QUANTITY, actual.getQuantity());
}

: (Expected Object)

(Expected Object) (Equality Assertion).
public void testInvoice_addLineItem1() {
LineItem expItem = new LineItem(inv, product, QUANTITY);
//
inv.addItemQuantity(expItem.getProd(), expItem.getQuantity());
//
List lineItems = inv.getLineItems();
assertEquals("number of items", lineItems.size(), 1);
LineItem actual = (LineItem) lineItems.get(0);
assertEquals("Item", expItem, actual);
}

(Expected Object)
,
.

. 488

489

(Behavior Verification)
,
,
?

:

(Interaction Testing)

(/

(SelfChecking Test, . 81) 


.
? 
; ,
. ,
.
(Behavior Verification)
.


,
, .
, ,
.
(Behavior Verification)
( ),

. 489

490

21

. (Behavior Verification)
(State Verification, . 485) ,
, 
.
( , State Veri
fication) 
( , Behavior Verification).


(Behavior Verification)
. ,
. $
(Behavior Verification) ,


.
.
(Behavior Verification) 
.  (need
driven development) 
. 
, .
(Test Double,
. 538) . $
(Fragile Test, . 277), 
.
,
.
(Overspecified Software; . , Fragile Test)
(High Test Maintenance Cost, . 300).
(Behavior
Verification) (State Verification) . $
(State Verification) , (Behavior
Verification)  . , (Behavior Veri
fication)
(State Verification), (Behavior Verification) 
, .



. 
,
. ,
(Test Double) 
. (Test Double)

. 490

491

, . 
(Dependency Injection, . 684)
(Dependency Lookup, . 692).

(Behavior Verification). .
(Mock Object, . 558) $
(Expected Behavior Specification).
. (Mock
Object)  (Behavior Verification).

: (Procedural Behavior Verification)



:

.
(Expected Behavior)
(Test Method, . 378) 
. 

(Equality Assertion; . , Assertion Method, . 390).

(Test Spy, . 552) 
. $
(Test Spy) 
. (Test Spy) 
.

. , 
(Test Double) 
(Overspecified Software).
(Test Method) ( $
, Test Code Duplication, . 254), (Expected
Object) $
(Custom Assertion, . 495).

: (Expected Behavior Specification)


.

(Expected Behavior Specification) (Mock Object),
.
(Expected Behavior Specification) 
, , ,
(Procedural Behavior Verification)
(Test Method).
(, )

.
(Mock Object)
(Test Double)

. 491

492

21

xUnit.
(Expected Behavior Specification),
(Test Double) . 
(Mock Object) 
, .


,
. (Assertion
Method) (Mock Object).
,
logger, .
.
public void testRemoveFlightLogging_NSC() throws Exception {
//
FlightDto expectedFlightDto = createARegisteredFlight();
FlightManagementFacade facade =
new FlightManagementFacadeImpl();
//
facade.removeFlight(expectedFlightDto.getFlightNumber());
//
//
//
}

, ,

.
(SelfChecking Test)
(Expected State Specification).
public void testRemoveFlightLogging_ESS() throws Exception {
//
FlightDto expectedFlightDto = createAnUnregFlight();
FlightManagementFacadeImplTI facade =
new FlightManagementFacadeImplTI();
//
facade.removeFlight(expectedFlightDto.getFlightNumber());
//
assertFalse("flight still exists after being removed",
facade.flightExists(expectedFlightDto.
getFlightNumber()));
}

, , 
. ,
(Behavior Verification):


. 492

493

,
.



, .
, .
(State Verification)
(Behavior Verification)
(Replace Dependency with Test Double, . 740) 

(Test Spy) (Mock Object).
(Expected Behavior Specifica
tion) (Procedural Behavior Verification) $
(Mock Object) (Test Spy). 
,
(Test Spy). 
, (Mock Object), 
(Test Spy).
(Procedural Behavior Verifica
tion) (Expected Behavior Specification)
(Mock Object) ,
(Test Spy) . $
(Test Spy) (Mock Object).

: (Procedural Behavior Verification)


, 

(Procedural Behavior Verification).
(Test Spy),
(Assertion Method).
public void testRemoveFlightLogging_recordingTestStub()
throws Exception {
//
FlightDto expectedFlightDto = createAnUnregFlight();
FlightManagementFacade facade =
new FlightManagementFacadeImpl();
//
AuditLogSpy logSpy = new AuditLogSpy();
facade.setAuditLog(logSpy);
//
facade.removeFlight(expectedFlightDto.getFlightNumber());
//
assertEquals("number of calls", 1,
logSpy.getNumberOfCalls());
assertEquals("action code",
Helper.REMOVE_FLIGHT_ACTION_CODE,

. 493

494

21

logSpy.getActionCode());
assertEquals("date", helper.getTodaysDateWithoutTime(),
logSpy.getDate());
assertEquals("user", Helper.TEST_USER_NAME,
logSpy.getUser());
assertEquals("detail",
expectedFlightDto.getFlightNumber(),
logSpy.getDetail());
}

: (Expected Behavior Specification)



JMock. expects mockLog $
(Mock Object), ( ,
).
public void testRemoveFlight_JMock() throws Exception {
//
FlightDto expectedFlightDto = createAnonRegFlight();
FlightManagementFacade facade =
new FlightManagementFacadeImpl();
//
Mock mockLog = mock(AuditLog.class);
mockLog.expects(once()).method("logMessage")
.with(eq(helper.getTodaysDateWithoutTime()),
eq(Helper.TEST_USER_NAME),
eq(Helper.REMOVE_FLIGHT_ACTION_CODE),
eq(expectedFlightDto.getFlightNumber()));
//
facade.setAuditLog((AuditLog) mockLog.proxy());
//
facade.removeFlight(expectedFlightDto.getFlightNumber());
//
// verify()
// JMock
}

. 494

495

(Custom Assertion)

?
(Test
Code Duplication),
?
(Conditional Test Logic)?

:
(Bespoke
Assertion)


(Assertion Method),
, /
.

xUnit
(Assertion Method, . 390). ,
, .
?
(Custom Assertion),
. 
(Assertion Method)
.


 () 
. $
(Custom Assertion), .
(Custom Equality Assertion) :
(Expected Object; . , State Verification, . 484) .

. 495

496

21

(Custom Assertion) 

. , 
.
(Custom Assertion) 
.
(Custom As
sertion).
, .


(Custom Assertion) , 
.

( ) 
(. , Test Code Duplication,
. 254).

(Conditional Test
Logic, . 243), .. (Assertion Method)
if .

(Obscure Test, . 230),


.

, 
(Frequent Debugging, . 285).

(Minimize Untestable Code, . 98) 


(Custom Asser
tion). (Custom Assertion)
(Custom Assertion Test) 
.
(Obscure
Test), (Communicate Intent, . 95),
.

, (Custom Assertion)
(Verification Method).
/ , 
, $
(Parameterized Test, . 618).
(Custom Assertion)
. (Custom Assertion)
, (
).
(Custom Assertion) $
(Equality Assertion), .

. 496

497

: (Custom Equality Assertion)


(Expected Object)
. ,
(Assertion Message, . 398), $
(Assertion Roulette, . 264). equals,
(Foreign Method).

: (Object Attribute Equality Assertion)


(Custom Assertion),
(Expected Object),
. ( 
(Custom Assertion).)
(Custom Assertion)
(Verification Method) . $
(Object Attribute Equality Assertion) 
, .

: (Domain Assertion)
(Assertion Method) 
. (Custom Equality Assertion) 
, .
(Custom Assertion) $
(HigherLevel Language)  $
(Domain Assertion).
(Domain Assertion) $
(Stated Outcome Assertion),
. 
, .

: (Diagnostic Assertion)
(Frequent Debugging) ,
,  ,
(..
, , ).
(Custom Assertion) , 
,
. (, ,
.)
, XML.

. , , $
(Custom Assertion), .
, , 
.

. 497

498

21

: (Verification Method)

. (Verification Method)
(Custom Assertion),
, .
.
(Custom Assertion) 
.
(Verification Method) .
(Parameterized Test), 

(Test Utility Method, . 610).


(Custom Assertion) 
(Assertion Method).

(Equality Assertion) 
null. (Custom Assertion) $
(Assertion Method),
. ( 
(Verification Method).)

: (Custom Assertion Test)


(Custom
Assertion Test) (Custom Assertion).
: .
(Custom Assertion Test)
, (Assertion Method) 
.
(Custom Assertion)

. (Single Outcome Asser
tion) , (
, Assertion Message).
(Stated Outcome Assertion) ( 
) . (Equality Assertion)
,
, 
. 
, (Equality Assertion)
.
(Custom Assertion Test)
(Simple Success Test)
(Expected Exception Test) :

. 498

499

(Assertion Method) ,
.
(Expected Object) 
(Custom Assertion). 
, . ( $
(Test Automation Framework, . 332) 
.) ,
(Custom Assertion),
(Expected Exception Test),
(Custom Assertion).
$
(One Bad Attribute), .. 
.
. , 
.
xUnit: 
(Test
Runner, . 405), fail 
,
(Custom Assertion Test).
 
, 
.



.
public void testInvoice_addOneLineItem_quantity1_b() {
//
inv.addItemQuantity(product, QUANTITY);
//
List lineItems = inv.getLineItems();
assertEquals("number of items", lineItems.size(), 1);
//
LineItem expItem = new LineItem(inv, product, QUANTITY);
LineItem actual = (LineItem)lineItems.get(0);
assertEquals(expItem.getInv(), actual.getInv());
assertEquals(expItem.getProd(), actual.getProd());
assertEquals(expItem.getQuantity(), actual.getQuantity());
}
public void testRemoveLineItemsForProduct_oneOfTwo() {
//
Invoice inv = createAnonInvoice();
inv.addItemQuantity(product, QUANTITY);
inv.addItemQuantity(anotherProduct, QUANTITY);
LineItem expItem = new LineItem(inv, product, QUANTITY);
//
inv.removeLineItemForProduct(anotherProduct);

. 499

500

21

//
List lineItems = inv.getLineItems();
assertEquals("number of items", lineItems.size(), 1);
LineItem actual = (LineItem)lineItems.get(0);
assertEquals(expItem.getInv(), actual.getInv());
assertEquals(expItem.getProd(), actual.getProd());
assertEquals(expItem.getQuantity(), actual.getQuantity());
}
//
//
//
public void testInvoice_addTwoLineItems_sameProduct() {
Invoice inv = createAnonInvoice();
LineItem expItem1 = new LineItem(inv, product, QUANTITY1);
LineItem expItem2 = new LineItem(inv, product, QUANTITY2);
//
inv.addItemQuantity(product, QUANTITY1);
inv.addItemQuantity(product, QUANTITY2);
//
List lineItems = inv.getLineItems();
assertEquals("number of items", lineItems.size(), 2);
//
LineItem actual = (LineItem)lineItems.get(0);
assertEquals(expItem1.getInv(), actual.getInv());
assertEquals(expItem1.getProd(), actual.getProd());
assertEquals(expItem1.getQuantity(), actual.getQuantity());
//
actual = (LineItem)lineItems.get(1);
assertEquals(expItem2.getInv(), actual.getInv());
assertEquals(expItem2.getProd(), actual.getProd());
assertEquals(expItem2.getQuantity(), actual.getQuantity());
}

, 
,
. (Test Code Duplication).


, $
(Extract Method) .
(Assertion Method), . 
(Custom Assertion). , 
(Expected Object), ,
(Assertion Method). 
(Custom Assertion) .

: (Custom Assertion)
(Custom Assertion) 
LineItem.

. 500

501

$
(Equality Assertion).
public void testInvoice_addOneLineItem_quantity1_() {
Invoice inv = createAnonInvoice();
LineItem expItem = new LineItem(inv, product, QUANTITY);
//
inv.addItemQuantity(product, QUANTITY);
//
List lineItems = inv.getLineItems();
assertEquals("number of items", lineItems.size(), 1);
//
LineItem actual = (LineItem)lineItems.get(0);
assertLineItemsEqual("LineItem", expItem, actual);
}
public void testAddItemQuantity_sameProduct_() {
Invoice inv = createAnonInvoice();
LineItem expItem1 = new LineItem(inv, product, QUANTITY1);
LineItem expItem2 = new LineItem(inv, product, QUANTITY2);
//
inv.addItemQuantity(product, QUANTITY1);
inv.addItemQuantity(product, QUANTITY2);
//
List lineItems = inv.getLineItems();
assertEquals("number of items", lineItems.size(), 2);
//
LineItem actual = (LineItem)lineItems.get(0);
assertLineItemsEqual("Item 1",expItem1,actual);
//
actual = (LineItem)lineItems.get(1);
assertLineItemsEqual("Item 2",expItem2, actual);
}

.
, , .
(Custom Assertion) $
(Assertion Roulette) .
$
(Custom Assertion).
static void assertLineItemsEqual(
String msg, LineItem exp, LineItem act) {
assertEquals(msg+" Inv", exp.getInv(),act.getInv());
assertEquals(msg+" Prod", exp.getProd(), act.getProd());
assertEquals(msg+" Quan", exp.getQuantity(), act.getQuantity());
}

(Custom Assertion) 
, . , 
. , 
.
, 
.

. 501

502

21

: (Domain Assertion)

.
public void testAddOneLineItem_quantity1() {
Invoice inv = createAnonInvoice();
LineItem expItem = new LineItem(inv, product, QUANTITY);
//
inv.addItemQuantity(product, QUANTITY);
//
assertInvoiceContainsOnlyThisLineItem(inv, expItem);
}
public void testRemoveLineItemsForProduct_oneOfTwo_() {
Invoice inv = createAnonInvoice();
inv.addItemQuantity(product, QUANTITY);
inv.addItemQuantity(anotherProduct, QUANTITY);
LineItem expItem = new LineItem(inv, product, QUANTITY);
//
inv.removeLineItemForProduct(anotherProduct);
//
assertInvoiceContainsOnlyThisLineItem(inv, expItem);
}


(Domain Assertion).
void assertInvoiceContainsOnlyThisLineItem(
Invoice inv,
LineItem expItem) {
List lineItems = inv.getLineItems();
assertEquals("number of items", lineItems.size(), 1);
LineItem actual = (LineItem)lineItems.get(0);
assertLineItemsEqual("item",expItem, actual);
}


(Domain Assertion) . 
, 
.
(Assertion Message, . 398).

: (Verification Method)

, $
(Custom Assertion). $
(Custom Assertion) , 
, verify.
(Verification Method)
.
.
, 

. 502

503

, $
(Verification Method).
public void testAddOneLineItem_quantity2() {
Invoice inv = createAnonInvoice();
LineItem expItem = new LineItem(inv, product, QUANTITY);
//
verifyOneLineItemCanBeAdded(inv, product, QUANTITY, expItem);
}

(Verification Method)
.
public void verifyOneLineItemCanBeAdded(
Invoice inv, Product product,
int QUANTITY, LineItem expItem) {
//
inv.addItemQuantity(product, QUANTITY);
//
assertInvoiceContainsOnlyThisLineItem(inv, expItem);
}

(Verification Method) $
(Custom Assertion), , $
(Custom Assertion) . addItemQuantity inv. (Verification
Method) (Custom Assertion).

: (Custom Assertion Test)


(Custom Assertion),
.
, , .
public void testassertLineItemsEqual_equivalent() {
Invoice inv = createAnonInvoice();
LineItem item1 = new LineItem(inv, product, QUANTITY1);
LineItem item2 = new LineItem(inv, product, QUANTITY1);
// /
assertLineItemsEqual("This should not fail",item1, item2);
}
public void testassertLineItemsEqual_differentInvoice() {
Invoice inv1 = createAnonInvoice();
Invoice inv2 = createAnonInvoice();
LineItem item1 = new LineItem(inv1, product, QUANTITY1);
LineItem item2 = new LineItem(inv2, product, QUANTITY1);
// /
try {
assertLineItemsEqual("Msg",item1, item2);
} catch (AssertionFailedError e) {
assertEquals("e.getMsg",
"Invoice-expected: <123> but was <124>",
e.getMessage());
return;
}

. 503

504

21

fail("Should have thrown exception");


}
public void testassertLineItemsEqual_differentQuantity() {
Invoice inv = createAnonInvoice();
LineItem item1 = new LineItem(inv, product, QUANTITY1);
LineItem item2 = new LineItem(inv, product, QUANTITY2);
// /
try {
assertLineItemsEqual("Msg",item1, item2);
} catch (AssertionFailedError e) {
pass(); // ,
return;
}
fail("Should have thrown exception");
}

(Custom Asser
tion Test). , 
( ,
). ,
, (Expected
Exception Test), fail , .

. ( , 
, , .)

. 504

505

/ (Delta Assertion)
,
?

.

1.

Data

2. /

3.

(Shared Fixture, . 350),


, , 
. ,
, 
, .  
(Database
Partitioning Scheme). ?
$ (Delta Assertion), 
(Shared Fixture).



(Shared Fixture).
.
$ (Delta Assertion) 

.


$ (Delta Assertion) ,
$
(Interacting Tests). $ (Delta Assertion) 

. 505

506

21

.
,  (Delta Assertion)
(Implicit Teardown, . 533)
. , !
! .
 (Delta Assertion) , 
(Test Runner) . ,
(Test Run War),
.  (Delta
Assertion) , !
.
( , ),  (Delta Assertion) !
(Test Run War).


(Shared Fixture) !
, !
. , !
, , !
. Collection,
. !
.
,
, .
!
. , ,
, :
1) ;
2) , ;
3) (Expected Object).
!
!
. (Custom Assertion, . 495)
(Verification Method; . ).



!
.
. , !
(Unrepeatable Test) (Interacting
Tests). , (Slow Tests, . 289).

. 506

507

, !
. 
(Automated Teardown, . 521).
(Fake Database).
. !
,
!!!! , .
, .
. (Fake Database), !
!, !
. setUp !
(Equality Assertion), !
tearDown . (
 (Delta Assertion, . 505).) !
, .
.
!
.
, tearDown 
(Delta Assertion). ,
(, C++).


. !
.
public void testGetFlightsByOriginAirport_OneOutboundFlight()
throws Exception {
FlightDto expectedFlightDto =
createNewFlightBetweenExistingAirports();
//
facade.createFlight(
expectedFlightDto.getOriginAirportId(),
expectedFlightDto.getDestinationAirportId());
//
List flightsAtOrigin = facade.getFlightsByOriginAirport(
expectedFlightDto.getOriginAirportId());
assertOnly1FlightInDtoList("Outbound flight at origin",
expectedFlightDto,
flightsAtOrigin);
}

, ! (Shared Fixture) !
.
, !
, .

. 507

508

21


$ (Delta Asser
tion) ( 
), .
/.
(Test Method, . 378) (Conditional Test Logic,
. 243) (Custom Assertion).

( ), 
.

: / (Delta Assertion)
$ (Delta Assertion) 
. ,
(Expected
Object), , .
public void testCreateFlight_Delta()
throws Exception {
FlightDto expectedFlightDto =
createNewFlightBetweenExistingAirports();
//
List flightsBeforeCreate =
facade.getFlightsByOriginAirport(
expectedFlightDto.getOriginAirportId());
//
facade.createFlight(
expectedFlightDto.getOriginAirportId(),
expectedFlightDto.getDestinationAirportId());
//
List flightsAfterCreate =
facade.getFlightsByOriginAirport(
expectedFlightDto.getOriginAirportId());
assertFlightIncludedInDtoList("new flight ",
expectedFlightDto,
flightsAfterCreate);
assertAllFlightsIncludedInDtoList("previous flights",
flightsBeforeCreate,
flightsAfterCreate);
assertEquals("Number of flights after create",
flightsBeforeCreate.size()+1,
flightsAfterCreate.size());
}

(data transfer object),


,
. (Custom Assertion)
, ( 
, ).
(Custom Assertion) . 

. 508

509


, (Expected Object).
(Custom Assertion) ,
,
$ (Delta Assertion).
(Custom Assertion Test)
(Custom Assertion).

. 509

510

21

(Guard Assertion)
(Conditional Test Logic)?
if ,
, .

obj
AssertNotNull

obj.attr
Assert

, 
.
, 
. (Test Runner, . 405) 
, 
, .
(Guard Assertion)
(Conditional Test Logic, . 243).


. 
(Assertion Method, . 390), ,
. (Conditional Test
Logic) , , 
, . , 
, , $
(Guard Assertion). (Guard Assertion)
, .
, .

. 510

511


(Guard Assertion) ,
(Test Method, . 378),

. 
if then else fail 
. (Guard Assertion)

(FourPhase Test, . 387).

:
(Shared Fixture State Assertion)
(Shared Fixture, . 350), $
(Guard Assertion) (
)
. , , 
. (Tests as
Documentation, . 79).


(Guard Assertion) $
(Stated Outcome Assertion) (, assertNotNil)
(Equality Assertion) (, assertEquals).
, 
.


.
public void testWithConditionals() throws Exception {
String expectedLastname = "smith";
List foundPeople = PeopleFinder.
findPeopleWithLastname(expectedLastname);
if (foundPeople != null) {
if (foundPeople.size() == 1) {
Person solePerson = (Person) foundPeople.get(0);
assertEquals(expectedLastname,solePerson.getName());
} else {
fail("list should have exactly one element");
}
} else {
fail("list is null");
}
}

, 
. , (foundPeople == null)

. 511

512

21

(foundPeople != null). C = ==,


!


(Conditional Test Logic)
$
(Replace Nested Conditional
with Guard Clauses). ( .
!) 
(Stated Outcome Assertion),
(Equality Assertion).
, . 
, .

: (Simple Guard Assertion)



. . , 
.
public void testWithoutConditionals() throws Exception {
String expectedLastname = "smith";
List foundPeople = PeopleFinder.
findPeopleWithLastname(expectedLastname);
assertNotNull("found people list", foundPeople);
assertEquals("number of people", 1, foundPeople.size() );
Person solePerson = (Person) foundPeople.get(0);
assertEquals("last name",
expectedLastname,
solePerson.getName() );
}

,
!

:
(Shared Fixture Guard Assertion)
, (Shared
Fixture). ( ) 
, 
. , 
, .
, $
(Guard Assertion) .
public void testAddFlightsByFromAirport_OneOutboundFlight_GA()
throws Exception {
//

. 512

513

List flights = facade.getFlightsByOriginAirport(


ONE_OUTBOUND_FLIGHT_AIRPORT_ID );
//
assertEquals("# flights precondition", 1, flights.size());
FlightDto firstFlight = (FlightDto) flights.get(0);
//
BigDecimal flightNum = facade.createFlight(
firstFlight.getOriginAirportId(),
firstFlight.getDestAirportId());
//
FlightDto expFlight = (FlightDto) firstFlight.clone();
expFlight.setFlightNumber(flightNum );
List actual = facade.getFlightsByOriginAirport(
firstFlight.getOriginAirportId());
assertExactly2FlightsInDtoList("Flights at origin",
firstFlight,
expFlight,
actual);
}


! (Defect Local
ization, . 78).
.

. 513

514

21

(Unfinished Test Assertion)


, ?

.
void testSomething() {
// :
// ...
// ...
// , ...
fail("Unfinished Test!");
}

,
, (Test Method, . 378)
(Testcase Class, . 401), .
, ,  .
.
(Unfinished Test Assertion)
.


(Test Method) fail. 
fail (Single Outcome
Assertion), . ,
(Assertion Message, . 398) Unfinished Test, 
.


, . 
.
,
(Unfinished Test Assertion)
. , .
.
(Unfinished Test Assertion)
(Test Method).
,
, (Unfi
nished Test Assertion) ,
(Lost Test). [Ignore] (
xUnit),
( (Test Discovery, . 420)
) (Testcase Class) (AllTests

. 514

515

Suite), (Test Enumeration, . 425)


.


xUnit fail . 
, assertTrue(false) 
. .
(Custom Assertion,
. 495) (Custom Assertion Test), 
.
.
(Test Method), 
(Unfinished Test Assertion).


(Testcase Class).
public void
}
public void
}
public void
//To do:
}
public void
//To do:
}

testPull_emptyStack() {
testPull_oneItemOnStack () {
testPull_twoItemsOnStack () {

testPull_oneItemsRemainingOnStack () {

// To do: ... , , 
.
. (Testcase Class) 
, !


(Unfinished Test Assertion) 
.
fail("Unfinished Test!");

. , $
(Custom Assertion).
private void unfinishedTest() {
fail("Test not implemented!");
}

(Unfinished Test Assertion)


.

. 515

516

21

: (Unfinished Test Assertion)



(Unfinished Test Assertion).
public void testPull_emptyStack() {
unfinishedTest();
}
public void testPull_oneItemOnStack () {
unfinishedTest();
}
public void testPull_twoItemsOnStack() {
unfinishedTest();
}
public void testPull_oneItemsRemainingOnStack () {
unfinishedTest();
}

(Testcase Class), 
, .
.

:

Eclipse ( 3.0). testmethod $
(Testcase Class) .
public void testname() throws Exception {
fail("ClassName::testname not implemented");
}

ClassName testname (Test


case Class) (Test Method).
. 
fail. (Test
Method) testmethod <Ctrl+>.

. 516

22

22

:

(GarbageCollected Teardown) ..................... 518
(Automated Teardown) ...................................... 521

(Inline Teardown) .................................................... 527
(Implicit Teardown)........................................................ 533

. 517

518

22

(GarbageCollected Teardown)
?

, .

test_method_1
test_method_2

test_method_n
tearDown



. (Fresh Fixture,
. 344). (garbage collection) 
,
.


, (
),
, .
.
 , : ,
(.. ) ,
.
(Test Automation Frame
work, . 332) (Testcase Object, . 410)
(Test Method, . 378) (Testcase Class, . 401) 
(Test Suite Object, . 414). 
. 

. 518

519

,
, .


(GarbageCollected Teardown) ,
, !

, (, , , 
), . 
(Shared Fixture, . 350) $
(GarbageCollected Teardown) ,
, 
.

(Inline Teardown, . 527), (Implicit Teardown, . 533) $
(Automated Teardown, . 521).


xUnit
. Reload
Classes . , 
(GarbageCollected Tear
down) , 

(, Cruise Contol ).



, (Inline Teardown).
( (Implicit Teardown),
.)
public void testCancel_proposed_UIT() {
//
Flight proposedFlight = createAnonymousProposedFlight();
//
proposedFlight.cancel();
//
try{
assertEquals(FlightState.CANCELLED,
proposedFlight.getStatus());
} finally {
//
proposedFlight.delete();
proposedFlight = null;
}
}

. 519

520

22

, proposedFlight
; .


(GarbageCollected Teardown) 
. 
, 
,
(Shared Fixture) (Fresh Fixture).

: (Garbage/Collected Teardown)
(GarbageCollected
Teardown).
public void testCancel_proposed_GCT() {
//
Flight proposedFlight = createAnonymousProposedFlight();
//
proposedFlight.cancel();
//
assertEquals(FlightState.CANCELLED,
proposedFlight.getStatus());
//
// proposedFlight
//
}

, !

. 520

521

(Automated Teardown)
?

/
.

:

(Test Object Registry)

test_method_1
test_method_2

test_method_n
tearDown



. (Fresh Fixture,
. 344). , 
, 
. 

, .
, ,
. , 
, . 
(Complex Teardown; . , Obscure Test, . 230)
(Conditional Test Logic,
. 243) , , (Untestable Test Code;
. , HardtoTest Code, . 251).

.

. 521

522

22



(.. , , ..), .
( ) , "
.
. "
. ,
.


(Automated Teardown) ,
,
. ( , .)
(Unrepeatable Test), 
(Interacting Tests), , ,
.
(Automated Teardown) ,
.
, , .


(Automated Teardown) .
, "
. ,
.

:
(Automated Fixture Teardown)

(Creation Method, . 441). , "
, "
.
:

(Automated Teardown) "


.

, , . 
(Persistent Fresh Fixture) "
(Automated Teardown) tearDown
(Testcase Class, . 401). ,
setUp .
(Shared Fixture, . 350) tearDown

. 522

523

(Test Method, . 378).


(Suite Fixture Setup, . 465) (
xUnit) (Setup
Decorator, . 471).
: "
. . ", "
( )
, (Automated Teardown). "
, , , .
Command.
(Automated Teardown) "
, (Testcase Superclass, . 646), "
(Testcase Class).
(Test Helper, . 651), "
(Testcase Class). (Test
Helper), ,
(Object Mother).
( ) , 
(Automated Teardown) .
(Test Method),
(Self"Checking Test, . 81)!
( , ) "
 (Delta Assertion, . 505) , "
.

: (Automated Exercise Teardown)


, ,
. "
(Object Factory; . , Dependency
Lookup, . 692), , "
. "
.


(Creation Method) "
. .
try/finally, (In"line Teardown,
. 527) .
public void testGetFlightsByOrigin_NoInboundFlight_SMRTD()
throws Exception {
//
BigDecimal outboundAirport = createTestAirport("1OF");
BigDecimal inboundAirport = null;
FlightDto expFlightDto = null;
try {
inboundAirport = createTestAirport("1IF");

. 523

524

22

expFlightDto = createTestFlight(outboundAirport, inboundAirport);


//
List flightsAtDestination1 =
facade.getFlightsByOriginAirport(inboundAirport);
//
assertEquals(0,flightsAtDestination1.size());
} finally {
try {
facade.removeFlight(expFlightDto.getFlightNumber());
} finally {
try {
facade.removeAirport(inboundAirport);
} finally {
facade.removeAirport(outboundAirport);
}
}
}
}

try/
finally finally .


(Automated Teardown) . ,
(Testcase Class).
, (Inline Teardown).
(Automated Teardown) 
(Testcase Class) (
) . 
, .
(Creation Method).
, (Extract
Method) $
(Creation Method), .
(Automated Teardown)
tearDown. $
(Testcase Class), (Testcase Superclass),
(Testcase Class).
(Testcase Superclass) , 
(Extract Class)
(Pull up method) ( ),
(Automated Teardown).

: (Automated Teardown)
,
.

. 524

525

public void testGetFlightsByOriginAirport_OneOutboundFlight()


throws Exception {
//
BigDecimal outboundAirport = createTestAirport("1OF");
BigDecimal inboundAirport = createTestAirport("1IF");
FlightDto expectedFlightDto =
createTestFlight( outboundAirport, inboundAirport);
//
List flightsAtOrigin =
facade.getFlightsByOriginAirport(outboundAirport);
//
assertOnly1FlightInDtoList("Flights at origin",
expectedFlightDto,
flightsAtOrigin);
}

! (Creation Method) 
.
private List allAirportIds;
private List allFlights;
protected void setUp() throws Exception {
allAirportIds = new ArrayList();
allFlights = new ArrayList();
}
private BigDecimal createTestAirport(String airportName)
throws FlightBookingException {
BigDecimal newAirportId = facade.createAirport(
airportName, " Airport" + airportName,
"City" + airportName);
allAirportIds.add(newAirportId);
return newAirportId;
}

(Automated Teardown).
(Testcase Class)
tearDown. , 
.
(Testcase Superclass),
(Testcase Class), 
, .
protected void tearDown() throws Exception {
removeObjects(allAirportIds, "Airport");
removeObjects(allFlights, "Flight");
}
public void removeObjects(List objectsToDelete, String type) {
Iterator i = objectsToDelete.iterator();
while (i.hasNext()) {
try {
BigDecimal id = (BigDecimal) i.next();
if ("Airport"==type) {
facade.removeAirport(id);
} else {
facade.removeFlight(id);
}

. 525

526

22

} catch (Exception e) {
// ,
}
}
}

(Shared Fixture) tearDown


(, @afterClass [TestFixtureTearDown]) (Setup Decorator).

: (Automated Exercise Teardown)


, 
. 
(Object Factory). .
ResourceTracker tracker;
public void setUp() {
tracker = new ResourceTracker();
ObjectFactory.addObserver(tracker);
}
public void tearDown() {
tracker.cleanup();
ObjectFactory.removeObserver(tracker);
}

, (Automated
Teardown) cleanup ResourceTracker.

. 526

527

(In/line Teardown)
?
(Test Method)
.

test_method_1
test_method_2

test_method_n
tearDown



. (Fresh Fixture,
. 344). , 
, 
.
,
.
(Inline Teardown), 
, .



, . 
(Test Method, . 378) 
, 
. ,
.

. 527

528

22


, 
, (Test
Method). ,
(Inline Teardown). 
(Unrepeatable Test) (Slow Tests, . 289)
.

(Tests as Documentation, . 79). 
$
(High Test Maintenance Cost, . 300), 
. ,
( 
, ). $
(Automated Teardown, . 521) (Implicit Teardown,
. 533),
(Testcase Class per Fixture, . 639) (Testcase Class, . 401)
.
, (Inline Teardown) 
(Implicit Teardown). 
(Inline Teardown)
(Test Method), tearDown.
(Inline Teardown) ,
. 
(GarbageCollected Teardown, . 518),
,
.


(Inline Teardown) 
, 
( ). 
, .
(Inline Teardown)
,
.
/ , 
. Java
try finally.

: (Teardown Guard Clause)


, 
, .
 .

. 528

529

: (Delegated Teardown)
(Test Method)
(Test Utility Method, . 610). 
, 

. 
(Implicit Teardown).

: (Naive In/line Teardown)


,
try/finally ,
. (Resource Leakage),  
(Erratic Test).


(airport) .
,
(GarbageCollected Teardown) .
, . 
(Distinct Generated Value), 
(Unrepeatable Test), 
.
public void testGetFlightsByOriginAirport_NoFlights_ntd()
throws Exception {
//
BigDecimal outboundAirport = createTestAirport("1OF");
//
List flightsAtDestination1 =
facade.getFlightsByOriginAirport(outboundAirport);
//
assertEquals(0,flightsAtDestination1.size());
}

: (Naive In/line Teardown)



airport.
public void testGetFlightsByOriginAirport_NoFlights()
throws Exception {
//
BigDecimal outboundAirport = createTestAirport("1OF");
//
List flightsAtDestination1 =
facade.getFlightsByOriginAirport(outboundAirport);
//
assertEquals(0,flightsAtDestination1.size());
facade.removeAirport(outboundAirport);
}

. 529

530

22

, ,
, 
. ,
, . , 
.



, tearDown. 
, 
. 
try/finally .

: (In/line Teardown)
Java try/finally 
, 
.
public void testGetFlightsByOriginAirport_NoFlights_td()
throws Exception {
//
BigDecimal outboundAirport = createTestAirport("1OF");
try {
//
List flightsAtDestination1 =
facade.getFlightsByOriginAirport(outboundAirport);
//
assertEquals(0,flightsAtDestination1.size());
} finally {
facade.removeAirport(outboundAirport);
}
}

try, 
 finally.
(Inline Teardown). catch
(Expected Exception Test).

: (Teardown Guard Clause)


(Teardown Guard
Clause), airport.
public void testGetFlightsByOriginAirport_NoFlights_TDGC()
throws Exception {
//
BigDecimal outboundAirport = createTestAirport("1OF");
try {
//

. 530

531

List flightsAtDestination1 =
facade.getFlightsByOriginAirport(outboundAirport);
//
assertEquals(0,flightsAtDestination1.size());
} finally {
if (outboundAirport!=null) {
facade.removeAirport(outboundAirport);
}
}
}

: (Java)
,
. 
,
Java, .
public void testGetFlightsByOrigin_NoInboundFlight_SMRTD()
throws Exception {
//
BigDecimal outboundAirport = createTestAirport("1OF");
BigDecimal inboundAirport = null;
FlightDto expFlightDto = null;
try {
inboundAirport = createTestAirport("1IF");
expFlightDto = createTestFlight(outboundAirport, inboundAirport);
//
List flightsAtDestination1 =
facade.getFlightsByOriginAirport(inboundAirport);
//
assertEquals(0,flightsAtDestination1.size());
} finally {
try {
facade.removeFlight(expFlightDto.getFlightNumber());
} finally {
try {
facade.removeAirport(inboundAirport);
} finally {
facade.removeAirport(outboundAirport);
}
}
}
}

, 
.
.
(Automated Teardown).

: (Delegated Teardown)
(Test Method),
, .

. 531

532

22

public void testGetFlightsByOrigin_NoInboundFlight_DTD()


throws Exception {
//
BigDecimal outboundAirport = createTestAirport("1OF");
BigDecimal inboundAirport = null;
FlightDto expectedFlightDto = null;
try {
inboundAirport = createTestAirport("1IF");
expectedFlightDto =
createTestFlight( outboundAirport, inboundAirport);
//
List flightsAtDestination1 =
facade.getFlightsByOriginAirport(inboundAirport);
//
assertEquals(0,flightsAtDestination1.size());
} finally {
teardownFlightAndAirports(outboundAirport,
inboundAirport,
expectedFlightDto);
}
}
private void teardownFlightAndAirports(
BigDecimal firstAirport,
BigDecimal secondAirport,
FlightDto flightDto)
throws FlightBookingException {
try {
facade.removeFlight(flightDto.getFlightNumber() );
} finally {
try {
facade.removeAirport(secondAirport);
} finally {
facade.removeAirport(firstAirport);
}
}
}

,
flightDto. ,  
teardownFlightAndAirports flightDto,
Airport. ,
. 
(Automated Teardown) 
!

. 532

533

(Implicit Teardown)
?

(Test Automation Framework)
tearDown
(Test Method).

:
(Hooked
Teardown), (FrameworkInvoked Teardown),
(Teardown Method)

test_method_1
test_method_2

test_method_n
tearDown



. (Fresh Fixture,
. 344). , 
, 
.
(GarbageCollected Teardown, . 518)
, 
tearDown, 
(Test Automation Framework, . 332) 
(Test Method, . 378).



(FourPhase Test, . 387), .. 
. xUnit 
(Implicit Teardown), tearDown (Testcase
Object, . 410) (Test Method).

. 533

534

22

tearDown . 
, . ,
xUnit tearDown , setUp 
.


(Implicit Teardown) , 

.
(Unrepeatable Test)
(Slow Tests, . 289), 
.

,
(GarbageCollected Teardown) . 
, ,
(Inline Teardown, . 527).
, 
(Automated Teardown, . 521).


tearDown
, (Inline Teardown).
tearDown .

(Test
Method) .

(Test Method) (Testcase Class, . 401) 


(.. , Implicit Setup, 
, Inline Setup, . 434, ,
Delegated Setup, . 437),
.

: (Teardown Guard Clause)


,
(Conditional Test Logic, . 243) 
( if) .
. tearDown .
tearDown setUp, 

(Test Method).

. 534

535



. , 
. ( )
.
public void testGetFlightsByOrigin_NoInboundFlight_SMRTD()
throws Exception {
//
BigDecimal outboundAirport = createTestAirport("1OF");
BigDecimal inboundAirport = null;
FlightDto expFlightDto = null;
try {
inboundAirport = createTestAirport("1IF");
expFlightDto = createTestFlight(outboundAirport, inboundAirport);
//
List flightsAtDestination1 =
facade.getFlightsByOriginAirport(inboundAirport);
//
assertEquals(0,flightsAtDestination1.size());
} finally {
try {
facade.removeFlight(expFlightDto.getFlightNumber());
} finally {
try {
facade.removeAirport(inboundAirport);
} finally {
facade.removeAirport(outboundAirport);
}
}
}
}

(Test Code Dupli


cation, . 254), $
(Implicit Teardown).


.
(Extract Method)
tearDown. , 
.
, , 
(Teardown Guard Clause). ,
try/finally 
, .

. 535

536

22

: (Implicit Teardown)
tearDown. , .
BigDecimal outboundAirport;
BigDecimal inboundAirport;
FlightDto expFlightDto;
public void testGetFlightsByAirport_NoInboundFlights_NIT()
throws Exception {
//
outboundAirport = createTestAirport("1OF");
inboundAirport = createTestAirport("1IF");
expFlightDto = createTestFlight( outboundAirport, inboundAirport);
//
List flightsAtDestination1 =
facade.getFlightsByOriginAirport(inboundAirport);
//
assertEquals(0,flightsAtDestination1.size());
}
protected void tearDown() throws Exception {
try {
facade.removeFlight(expFlightDto.getFlightNumber() );
} finally {
try {
facade.removeAirport(inboundAirport);
} finally {
facade.removeAirport(outboundAirport);
}
}
}

,
try/finally. ,
(Expected Exception Test). , (Teardown
Guard Clause) , try/finally
. 
, tearDown 
.

. 536

23

23


:
(Test Double)............................................................... 538

(Test Stub) ................................................................... 544
(Test Spy) .......................................................................... 552
(Mock Object)............................................................. 558
(Fake Object) ............................................................. 565

(Configurable Test Double) ............... 571
(HardCoded Test Double) .............. 581
(TestSpecific Subclass) ............................. 591

. 537

538

23

(Test Double)
:
(Imposter)

,
, , ?
?
,
, /
.

, , 
. 
, 
 
.
.
( 
) , (Test
Double). (Test Double) , 
. 
, !


 ,
, . 
, , , 
.

. 538

539

. ,
, .
( !)
 (Test
Double).
(Test Double). 
.
(Test Double) ,
, .
(Test Double) 
, .
, 
. (Test Double)
, .


(Test Double)
.

(Untested Requirement)  

, $
(Behavior Verification, . 489).

(Untested Code) 
,
.

(Slow Tests, . 289)


( ).

$
(Test Double). ,
, , 
. 
, 
. , 
, ,
! (Test
Double) (Fragile Test, . 277)
(Overspecified Software).
(Test Double). 
. 23.1. 
.

(Test Double). , 
.

. 539

540

23

. 23.1. (Test Double). $ (Dummy Object)


. (Test Stub)
. (Test Spy) (Mock Object)
. (Fake Object)

: (Test Stub)
(Test Stub, . 544) ,
,
. 
, . 
(Test Stub) ,
. (Responder) 
, (Saboteur) .

. 
(Temporary Test Stub).

: (Test Spy)
(Test Stub)  (Test
Spy), 
. (Test Stub), (Test
Spy) .

. , (Test Spy) 
(Test Stub) . (Test Spy) 
, (Mock Object, . 558),
.

: (Mock Object)
(Mock Object)
.
(Mock Object) (Test
Stub), ,
. , $
(Mock Object)  , (Test
Stub) : .

. 540

541

: (Fake Object)
(Fake Object, . 565)
, 
. (Fake Object)
, ,
. (Fake Object) 
, 
.
(Fake Object) , 
,
 .
. 351

. 
50 . 
6 11.

:  (Dummy Object)

. , , 
 (Dummy Object), 
null, Object (PseudoObject;
. , HardCoded Test Double, . 581).
 (Dummy Object) (Test Double), 
(Literal Value, . 718),
(Derived Value, . 722) (Generated Value, . 726).

: (Procedural Test Stub)


(Test Double), 
, , 
(Procedural Test Stub),
 (Test Stub). 
(Procedural Test Stub) ,
. 
, .
(Test Logic in Production, . 257).


(Test Double) 
(. 23.2).

. 541


?

(Test Double)
?

542

23

, (Test Double) 
()?

. (Test
Double) (Configurable
Test Double).
(Test Double) 
(.. , Test Stub,
, Mock Object),
(HardCoded Test Double) (Configurable Test Double)
.

. 23.2. (Test Double) .


(Test Stub), (Test Spy) (Mock Object)
. $ (Dummy Object)
, (Fake Object) ,

: (Unconfigurable Test Double)


$ (Dummy Object), (Fake Object)
( ).  ,
. , (Fake
Object) , 
. , , 
; (Test Double) 
, .

: (Hard/Coded Test Double)


(Test Double) 
, (Test Double) 
( , Test Stub) 

. 542

543

( , Mock Object).
(HardCoded Test Double) .
, (Self Shunt),
(Testcase Class) (Test Double), $
(Anonymous Inner Test Double),
(Test Double) $
(Test Method, . 378), (Test Double),
(Test Double Class).
(Hard
Coded Test Double).

: (Configurable Test Double)


(Test
Double) , $
(Configurable Test Double). ,
xUnit
(Configurable Test Double).



(Test Double) .
(Test Double)
(substitutable dependency).
(Configurable Test Double) 
. .

: (Test Double)
(Test
Double), , 
. , 
.

. 543

544

23

(Test Stub)
:
(Stub)

,
?
,
.

.

( ),
, .
, ,
, 
(Test Stub).


, 
.
( ), $
(Untested Code) . 
(Test Stub),
. $
(Test Stub) .
.

. 544

545


(Test Stub)
(Untested Code),
. (Test Stub) 
, 
,
. , (Test Stub) 
,
.
,
, (Mock Object,
. 558) (Test Spy, . 552). , 
(Test Double, . 538) ,
.

: (Responder)
(Test Stub), 
, 
(Responder). (Responder) 
, 
,
. $
(Simple Success Test).

: (Saboteur)
(Test Stub), 
, (Saboteur). 
 ,
. ,
.
(Simple Success Test)
(Expected Exception Test)
.

: (Temporary Test Stub)



. (Test Stub) 
. 
. 

. .
(Mock
Object), 
. , (Mock Object) 
, .

. 545

546

23

: (Procedural Test Stub)


(Test Stub), 
. , 
( ).
if testing then (
, Test Logic in Production, . 257).

: (Entity Chain Snipping)


(Entity Chain Snipping)
(Responder), 
(Test Stub). , 
(, 
); .


(Test Stub) , 
, .
, $
(Test Stub). :
, 
. , ,
. , ,
(Test Stub)
(Overspecified Software).
(Test Stub) 
.

: (Hard/Coded Test Stub)


.
(Test Stub) 
.
(HardCoded Test Double, . 581).
: (Configurable Test Stub)
,
(Configurable Test Stub). 
. xUnit 
(Configurable Test
Double, . 571), (Configurable Test Stub).


,
HTML . , 
, !

. 546

547

public void testDisplayCurrentTime_AtMidnight() {


//
TimeDisplay sut = new TimeDisplay();
//
String result = sut.getCurrentTimeAsHtmlFragment();
//
String expectedTimeString =
"<span class=\"tinyBoldText\">Midnight</span>";
assertEquals( expectedTimeString, result);
}

, 
.
public void testDisplayCurrentTime_whenever() {
//
TimeDisplay sut = new TimeDisplay();
//
String result = sut.getCurrentTimeAsHtmlFragment();
//
Calendar time = new DefaultTimeProvider().getTime();
StringBuffer expectedTime = new StringBuffer();
expectedTime.append("<span class=\"tinyBoldText\">");
if ((time.get(Calendar.HOUR_OF_DAY) == 0)
&& (time.get(Calendar.MINUTE) <= 1)) {
expectedTime.append( "Midnight");
} else if ((time.get(Calendar.HOUR_OF_DAY) == 12)
&& (time.get(Calendar.MINUTE) == 0)) { //
expectedTime.append("N3oon");
} else {
SimpleDateFormat fr = new SimpleDateFormat("h:mm a");
expectedTime.append(fr.format(time.getTime()));
}
expectedTime.append("</span>");
assertEquals(expectedTime, result);
}

(Flexible Test) . ,
. (
, 
?) ,
. ?



.
(Replace Dependency with Test Double, . 740) 
( TimeProvider) 
, (Test Stub), 
. ,
.

. 547

548

23

: (Responder)

. $
(Responder) 
. , 
, .
public void testDisplayCurrentTime_AtMidnight()
throws Exception {
//
//

TimeProviderTestStub tpStub = new TimeProviderTestStub();
tpStub.setHours(0);
tpStub.setMinutes(0);
//

TimeDisplay sut = new TimeDisplay();
//

sut.setTimeProvider(tpStub);
//
String result = sut.getCurrentTimeAsHtmlFragment();
//
String expectedTimeString =
"<span class=\"tinyBoldText\">Midnight</span>";
assertEquals("Midnight", expectedTimeString, result);
}

$
(Test Stub).
private Calendar myTime = new GregorianCalendar();
/**
* TimeProviderTestStub
* 'hours' 24-
*
(, 10 -- 10 AM, 12 -- , 22 -- 10 PM, 0 -- )
* 'minutes'
*
(, 0 -- , 1 - 1 )
*/
public TimeProviderTestStub(int hours, int minutes) {
setTime(hours, minutes);
}
public void setTime(int hours, int minutes) {
setHours(hours);
setMinutes(minutes);
}
//
public void setHours(int hours) {
// 0 - ; 12 -
myTime.set(Calendar.HOUR_OF_DAY, hours);
}
public void setMinutes(int minutes) {
myTime.set(Calendar.MINUTE, minutes);
}
// ,
public Calendar getTime() {
// @return -
return myTime;
}

. 548

549

: (Responder)
, $
(Configurable Test Double), JMock.
public void testDisplayCurrentTime_AtMidnight_JM()
throws Exception {
//
TimeDisplay sut = new TimeDisplay();
//
Mock tpStub = mock(TimeProvider.class);
Calendar midnight = makeTime(0,0);
tpStub.stubs().method("getTime").
withNoArguments().
will(returnValue(midnight));
//
sut.setTimeProvider((TimeProvider) tpStub);
//
String result = sut.getCurrentTimeAsHtmlFragment();
//
String expectedTimeString =
"<span class=\"tinyBoldText\">Midnight</span>";
assertEquals("Midnight", expectedTimeString, result);
}

(Test Stub),
JMock . , 
(Test Utility Method, . 610), 
makeTime Calendar.
getTime.

: (Saboteur)
(Anonymous Inner Class)
(Saboteur)

.
public void testDisplayCurrentTime_exception()
throws Exception {
//
//

TimeProvider testStub = new TimeProvider()
{ //
public Calendar getTime() throws TimeProviderEx {
throw new TimeProviderEx("Sample");
}
};
//

TimeDisplay sut = new TimeDisplay();
sut.setTimeProvider(testStub);
//
String result = sut.getCurrentTimeAsHtmlFragment();
//

. 549

550

23

String expectedTimeString =
"<span class=\"error\">Invalid Time</span>";
assertEquals("Exception", expectedTimeString, result);
}

$
(Inner Test Double). , 
. 
(Simple Success Test) $
(Expected Exception Test),
.

. .

: (Entity Chain Snipping)


Invoice, 
Customer. Customer Address, ,
, City. , 
. , 
Invoice Customer,
Address get_zone Customer.
public void testInvoice_addLineItem_noECS() {
final int QUANTITY = 1;
Product product = new Product(getUniqueNumberAsString(),
getUniqueNumber());
State state = new State("West Dakota", "WD");
City city = new City("Centreville", state);
Address address = new Address("123 Blake St.", city, "12345");
Customer customer= new Customer(getUniqueNumberAsString(),
getUniqueNumberAsString(),
address);
Invoice inv = new Invoice(customer);
//
inv.addItemQuantity(product, QUANTITY);
//
List lineItems = inv.getLineItems();
assertEquals("number of items", lineItems.size(), 1);
LineItem actual = (LineItem)lineItems.get(0);
LineItem expItem = new LineItem(inv, product, QUANTITY);
assertLineItemsEqual("",expItem, actual);
}

Invoice,
zone,
Customer. ( Customer,
zone.) ,
.
, (Test Stub) 
Customer. , 
 (Entity Chain Snipping)!

. 550

551

public void testInvoice_addLineItem_ECS() {


final int QUANTITY = 1;
Product product = new Product(getUniqueNumberAsString(),
getUniqueNumber());
Mock customerStub = mock(ICustomer.class);
customerStub.stubs().method("getZone").will(returnValue(ZONE_3));
Invoice inv = new Invoice((ICustomer)customerStub.proxy());
//
inv.addItemQuantity(product, QUANTITY);
//
List lineItems = inv.getLineItems();
assertEquals("number of items", lineItems.size(), 1);
LineItem actual = (LineItem)lineItems.get(0);
LineItem expItem = new LineItem(inv, product, QUANTITY);
assertLineItemsEqual("", expItem, actual);
}

customerStub Customer
JMock. getZone
ZONE_3. , Invoice.
,
. , ,
Invoice get_zone
Customer Address .



xUnit (Test Stub), 
. ,
(Test Stub) $
(Mock Object). ,
.

(Test Stub) [UTwHCM].
.
. ,
(Responder), Virtual Clock. $
(Test Stub) [GOF] . 
. ,
(HardCoded Test Stub)
(Configurable Test Stub).

. 551

552

23

(Test Spy)
:
(Spy),
(Recording
Test Stub)

(Behavior
Verification)?

?

(Test Double).

.

( ), 
, . 
, , ,
.
(Test Spy)
(Behavior Verification, . 489) 
, 
.


(Test Spy) 
, .
(Test Spy) .
, 
. ,
, .

. 552

553


(Test Spy)
(Untested Requirement) 
. (Test Spy)

, (Assertion Method, . 553)
, 
. (Test Spy) , 
(Test Method, . 378) , 
.
(Test Spy) .

,
.

,
(Mock Object, . 558) 
.

(
, ) 
(Mock Object), 
(Assertion Method).


(Test Runner, . 405).
, 
,
, . ( 
, 
, .)

,
(Mock Object).
(Untested Code)
(Test Stub, . 544).
(Mock Object) (Test Spy) 
.
, (Assertion Message,
. 398) , 
, (Mock Object)
.
(Assertion Method) ,
(Test Method). ,
,
(Test Spy) (Mock Object).

. 553

554

23

, (Test Double, . 538) ,


.


(Test Spy)
(HardCoded Test Double, . 581) $
(Configurable Test Double, . 571).
,
. (Test Spy)
.
(Test Spy)
(Test Method). , 
, (Test Spy). 
.

: (Retrieval Interface)
(Test Spy) $
(Retrieval Interface), .
(Test Method) (Test Spy) 
. 
$
(Test Method) (Retrieval Interface)
(Assertion Method).

: (Self Shunt)
(Test Spy) (Testcase Class,
. 401)  (Self
Shunt). (Test Method) ,
(Testcase Object, . 410), 
. 
(Testcase Object), 
, (Test Method). (Test Spy)
. (Self Shunt)
(Mock Object), (Test Spy). 
(Testcase Class)
( ), , 
, .
:
(Loopback)

: (Inner Test Double)


(Test Spy)
(HardCoded Test Double) /
(anonymous inner class) (block closure)
(Test Method). 
, (Test
Method). , (Self Shunt).

. 554

555

: (Indirect Output Registry)



, (Test Method). ,
(Test Spy) Registry.



, ,  

, , .
public void testRemoveFlight() throws Exception {
//
FlightDto expectedFlightDto = createARegisteredFlight();
FlightManagementFacade facade = new FlightManagementFacadeImpl();
//
facade.removeFlight(expectedFlightDto.getFlightNumber());
//
assertFalse("flight should not exist after being removed",
facade.flightExists(expectedFlightDto.
getFlightNumber()));
}



(Replace De
pendency with Test Double, . 740). 
(Test Spy),
. , 

(Test Spy), $
(Retrieval Interface).

: (Test Spy)
(Test Spy)
logSpy. facade.setAuditLog(logSpy)
(Test Spy) (Setter Injection). getDate, getActionCode (Retrieval Interface)
.
public void testRemoveFlightLogging_recordingTestStub()
throws Exception {
//
FlightDto expectedFlightDto = createAnUnregFlight();
FlightManagementFacade facade = new FlightManagementFacadeImpl();
//

AuditLogSpy logSpy = new AuditLogSpy();
facade.setAuditLog(logSpy);

. 555

556

23

//
facade.removeFlight(expectedFlightDto.getFlightNumber());
//
assertFalse("flight still exists after being removed",
facade.flightExists(expectedFlightDto.
getFlightNumber()));
assertEquals("number of calls", 1,
logSpy.getNumberOfCalls());
assertEquals("action code",
Helper.REMOVE_FLIGHT_ACTION_CODE,
logSpy.getActionCode());
assertEquals("date", helper.getTodaysDateWithoutTime(),
logSpy.getDate());
assertEquals("user", Helper.TEST_USER_NAME,
logSpy.getUser());
assertEquals("detail",
expectedFlightDto.getFlightNumber(),
logSpy.getDetail());
}

(Test Spy).
public class AuditLogSpy implements AuditLog {
// ,
//
private Date date;
private String user;
private String actionCode;
private Object detail;
private int numberOfCalls = 0;
// AuditLog
public void logMessage(Date date,
String user,
String actionCode,
Object detail) {
this.date = date;
this.user = user;
this.actionCode = actionCode;
this.detail = detail;
numberOfCalls++;
}
//
public int getNumberOfCalls() {
return numberOfCalls;
}
public Date getDate() {
return date;
}
public String getUser() {
return user;
}
public String getActionCode() {
return actionCode;
}
public Object getDetail() {
return detail;
}
}

. 556

557

, (Retrieval Interface)
, .
(Hard
Coded Test Double).

. 557

558

23

(Mock Object)
(Behavior Verification)
?
,
?
, ,
,
.

( ), , 
. 
, 1.
(Mock Object) 
(Behavior Verification, . 489) (Test Code Duplication,
. 254) .
(Test Double, . 538).


(Mock Object),
, , .
(Mock Object) 
, ,
1


, . , 
. 
, .

. 558

559

( ), . 
(Mock Object) ,
. 
(Mock Object) 
(Equality Assertion)
, .
!


(Mock Object)
(Behavior Verification), $
(Untested Requirement), 
. 

. (Mock Object) (State Verification, . 484)
, (Test
Stub, . 544) (Fake Object, . 565). 
(Mock Object),
(Test
Stub), (Mock Object).
(Mock Object)

. (Mock Object) , 
(Test
Runner). ,
, .
(Test Spy, . 552).
(Mock Object) ( 
) equals 
.
, (Mock Object)
equals , . $
(Equality Pollution). (Mock Object)
, $
(Equality Assertion).
(Mock Object) (,
, ). (Mock Object)
, , 
(Mock Object).
(Mock Object) .


, (Mock Object), 
, 
.

. 559

560

23

. ,
(Test Spy).
(Mock Object)
(FourPhase Test, . 387) . ,
,
( ).
:

(Mock Object);

(Mock Object); $
(HardCoded Test Double, . 581) ;

(Mock Object) .

(Mock Object), 
.

(FourPhase Test)
(Mock Object),
.
, 
(Mock Object).


(Mock Object),
xUnit, (Confi
gurable Mock Object, . 571), 
, , . ( 
(Mock Object) 
.)
(Test Double).

(HardCoded Test Double), (Inner Test Double).

, (Mock Object)
(Test Double) . 
. 

. 560

561

(Dependency Injection,
. 684).
(Dependency Lookup, . 692).

(Mock Object)
( ) . 
, .
, ,
(Mock Object) . ,
(Mock Object) .
.
,
(Mock Object) ,
. 
.
(Test Stub),
.


, , (Mock
Object) . (Mock Object)
,
. ,
(Mock Object)? (Mock Object)
, 
. , .
(Mock Object)
tearDown (
MockObjectTestCase).

.



, ,  
, 
, , .
public void testRemoveFlight() throws Exception {
//
FlightDto expectedFlightDto = createARegisteredFlight();
FlightManagementFacade facade = new FlightManagementFacadeImpl();
//
facade.removeFlight(expectedFlightDto.getFlightNumber());
//

. 561

562

23

assertFalse("flight should not exist after being removed",


facade.flightExists( expectedFlightDto.
getFlightNumber()));
}



(Replace
Dependency with Test Double, . 740). 
(Mock Object), 
, ,
.
(
).

: (Mock Object)
(Mock Object)
mockLog. setExpectedLogMessage 
. facade.setAuditLog(mockLog)
(Mock Object) (Setter Injection).
, verify() , logMessage().
public void testRemoveFlight_Mock() throws Exception {
//
FlightDto expectedFlightDto = createAnonRegFlight();
//
ConfigurableMockAuditLog mockLog =
new ConfigurableMockAuditLog();
mockLog.setExpectedLogMessage(
helper.getTodaysDateWithoutTime(),
Helper.TEST_USER_NAME,
Helper.REMOVE_FLIGHT_ACTION_CODE,
expectedFlightDto.getFlightNumber());
mockLog.setExpectedNumberCalls(1);
//
FlightManagementFacade facade = new FlightManagementFacadeImpl();
facade.setAuditLog(mockLog);
//
facade.removeFlight(expectedFlightDto.getFlightNumber());
//
assertFalse("flight still exists after being removed",
facade.flightExists( expectedFlightDto.
getFlightNumber()));
mockLog.verify();
}


(Mock Object). logMessage.
public void logMessage(Date actualDate,
String actualUser,

. 562

563

String actualActionCode,
Object actualDetail) {
actualNumberCalls++;
Assert.assertEquals("date", expectedDate, actualDate);
Assert.assertEquals("user", expectedUser, actualUser);
Assert.assertEquals("action code",
expectedActionCode,
actualActionCode);
Assert.assertEquals("detail", expectedDetail,actualDetail);
}

(Assertion Method) .
JUnit ,
(Mock Object) TestCase, ,
Assert. xUnit
(Assertion Method). , NUnit 
Assert, (Test
Method, . 378) , ,
(Assertion Method). Test::Unit, xUnit Ruby, 
(mixin). .

: (Mock Object)
(Mock
Object). xUnit 
. , 
JMock.
public void testRemoveFlight_JMock() throws Exception {
//
FlightDto expectedFlightDto = createAnonRegFlight();
FlightManagementFacade facade = new FlightManagementFacadeImpl(
//
Mock mockLog = mock(AuditLog.class);
mockLog.expects(once()).method("logMessage")
.with(eq(helper.getTodaysDateWithoutTime()),
eq(Helper.TEST_USER_NAME),
eq(Helper.REMOVE_FLIGHT_ACTION_CODE),
eq(expectedFlightDto.getFlightNumber()));
//
facade.setAuditLog((AuditLog) mockLog.proxy());
//
facade.removeFlight(expectedFlightDto.getFlightNumber());
//
assertFalse("flight still exists after being removed",
facade.flightExists(expectedFlightDto.
getFlightNumber()));
// verify() JMock
}

(Configuration In
terface), JMock
. , JMock ,

. 563

564

23

. eq
equals.



xUnit , (Mock Object), 
. , $
(Mock Object) (Test Stub),
(Fake Object). 
.

. 564

565

(Fake Object)
,
?

:
(Dummy)

,
, .

. 
, 

.
(Fake Object) 
, , 
.



, , .

. 
, 
,
. ,
.
(Fake Object)
(Test Double, . 538) (Test Stub, . 544), 

. 565

566

23


. (Test Stub)
, (Fake Object) 
: . (
, Fake Object)

. (Fake
Object) (Test Stub) (Mock Object, . 558),
.
(Fake Object),
, 
, (Fake Object)
(Back Door Manipulation, . 359). 
, (Data Loader) (Back Door
Setup), (Over
specified Software), $
(Fake Object) .
(Fake Object) .


(Fake Object) , 
,
, ,
(Test Stub)
(Mock Object). (Fake Object) ,
, $
(Mock Object).
(Fake Object) $
(Overspecified Software), 
. 
, 
.

, (Mock Object)
(Test Stub).
, 
(Fake Object).

: (Fake Database)
(Fake Database)
(Fake Object) 
, .

, , 
.

. 566

567

: (In/Memory Database)
(Fake Object)
, , 
. (InMemory Database)
( ), 
, (Fake Database).

: Web/ (Fake Web Service)


, ,
Web, 
, Web 
. Web
.

: (Fake Service Layer)



(Data Sensitivity) (Behavior Sensitivity),
(service layer) (Fake
Object), . 
,
.


(Fake Object) :

(Fake Object);

(Fake Object).

(Fake Object)
(Fake Object) .
(Fake Object) ,
,
, . 
, 
, (
).
, (Fake
Object) , 
. 
(Fake Object)
. , 
(Fake Object). ( 
50
. 351.)

. 567

568

23

(Fake Object)
, (Fake Object)
.
.
(Dependency Injection,
. 684).
(Dependency Lookup, . 692). 
(Fake Database), 
. (Dependency Injection)
.



. ( ),

, ( ).
( ). ,
.
.
public void testReadWrite() throws Exception{
//
FlightMngtFacade facade = new FlightMgmtFacadeImpl();
BigDecimal yyc = facade.createAirport("YYC", "Calgary", "Calgary");
BigDecimal lax = facade.createAirport("LAX", "LAX Intl", "LA");
facade.createFlight(yyc, lax);
//
List flights = facade.getFlightsByOriginAirport(yyc);
//
assertEquals("# of flights", 1, flights.size());
Flight flight = (Flight) flights.get(0);
assertEquals("origin",
yyc, flight.getOrigin().getCode());
}

createAirport (service facade), ,


, . 
.
public BigDecimal createAirport(String airportCode,
String name,
String nearbyCity)
throws FlightBookingException{
TransactionManager.beginTransaction();
Airport airport = dataAccess.
createAirport(airportCode, name, nearbyCity);
logMessage("Wrong Action Code", airport.getCode());//bug
TransactionManager.commitTransaction();
return airport.getId();
}
public List getFlightsByOriginAirport(
BigDecimal originAirportId)

. 568

569

throws FlightBookingException {
if (originAirportId == null)
throw new InvalidArgumentException(
"Origin Airport Id has not been provided",
"originAirportId", null);
Airport origin = dataAccess.getAirportByPrimaryKey(originAirportId);
List flights = dataAccess.getFlightsByOriginAirport(origin);
return flights;
}

dataAccess.createAirport, dataAccess.createFlight TransactionManager.commitTransaction . dataAccess.getAirportByPrimaryKey dataAccess.getFlightsByOriginAirport


.


(Fake Object)
(Mock Object). , 
(Replace Dependency with
Test Double, . 740) $
(Fake Object); 
(). 
, , (Extract Method).
,
.

(Fake Object) ; 
.

: (Fake Database)
(Fake Object),
, .. (Fake Database) ,
. , 
.
public void testReadWrite_inMemory() throws Exception{
//
FlightMgmtFacadeImpl facade = new FlightMgmtFacadeImpl();
facade.setDao(new InMemoryDatabase());
BigDecimal yyc = facade.createAirport("YYC", "Calgary", "Calgary");
BigDecimal lax = facade.createAirport("LAX", "LAX Intl", "LA");
facade.createFlight(yyc, lax);
//
List flights = facade.getFlightsByOriginAirport(yyc);
//
assertEquals("# of flights", 1, flights.size());
Flight flight = (Flight) flights.get(0);
assertEquals("origin",
yyc, flight.getOrigin().getCode());
}

. 569

570

23

(Fake Database).
public class InMemoryDatabase implements FlightDao{
private List airports = new Vector();
public Airport createAirport(String airportCode,
String name, String nearbyCity)
throws DataException, InvalidArgumentException {
assertParamtersAreValid(airportCode, name, nearbyCity);
assertAirportDoesntExist(airportCode);
Airport result = new Airport(getNextAirportId(),
airportCode, name, createCity(nearbyCity));
airports.add(result);
return result;
}
public Airport getAirportByPrimaryKey(BigDecimal airportId)
throws DataException, InvalidArgumentException {
assertAirportNotNull(airportId);
Airport result = null;
Iterator i = airports.iterator();
while (i.hasNext()) {
Airport airport = (Airport) i.next();
if (airport.getId().equals(airportId)) {
return airport;
}
}
throw new DataException("Airport not found:"+airportId);
}

, (Fake
Database) , 
.
public void setDao(FlightDao) {
dataAccess = dao;
}


. 351
 50
. ,
.

. 570

571

(Configurable Test Double)



(Test Double),
?

(Test Double),

.
,

:

(Configurable Mock
Object), (Configurable Test
Spy),
(Configurable Test Stub)


.
(Test Double, . 538) 
.
(Test Double)  .
(Configurable Test Double) $
(Test Code Duplication, . 254)
(Test Double) . 
.


(Test Double) , 
.
, 
(Test Double). 
(Test Double) 

. 571

572

23


.


(Configurable Test Double)
, , 
(Test Double) 
(Test Code Duplication) (Obscure Test, . 230)
( (Test Double) 
). 
, (HardCoded Test
Double, . 581), 
(Configurable Test Double) .


(Test Double) , 
/ 
. (Configurable Test Stub,
. 571) (Configurable Test Spy, . 571) 
. (Con
figurable Mock Object, . 571)
( ).
(Configurable
Test Double).
:
1) ;
2) .
. 
(Configuration
Interface), 
.
, (Configurable Test Double)
. (Configuration Mode) 

(Confi
gurable Test Double) . 
(Configurable Test Double) ( 
).
(Configurable Test
Double) .
. 
: , 
. ,

. 572

573

. 
http://
xprogramming.com. ,
(Test Double) , .

: (Configuration Interface)
(Configuration Interface) , 
(Configurable Test Double)
.
. 
(Configurable Test Double),
, $
(Configuration Interface).
. 
, MockMaker, 
.
(Configuration Interface). , JMock, 
,
(Expected Behavior Specification),
(Configurable Test Double) . 
.

: (Configuration Mode)
$
(Test Double) (Configuration Mode),
(Configurable Test Double) 
. : 
(Test Method, . 378)
? , 
, .
(Configuration Mode) 

, . (
,
.) , 
: 
(Configuration Mode),  .

: (Hand/Built Test Double)


(HandBuilt Test Double) 
.
(HardCoded Test Double) $
(HandBuilt Test Double), (Confi
gurable Test Double) .
(HandBuilt Test Double)

. 573

574

23

, , 
.
. ,
. 

.

:
(Statically Generated Test Double)
$
(Statically Generated Test Double) . 
.
. , 

(Statically Generated Test Double). 
, 
.
(Statically Gen
erated Test Double)
(HandBuilt Test Double), ..
(Configurable Test Double).
. ,
.
? $
(Statically Generated Test Double) 
? 

,
. , 
(Statically Generated Test Double)
, 
.

:
(Dynamically Generated Test Double)
$
(Configurable Test Double) 
. 
, 
. (Configurable Test Double) 

. ,
.
, .

. 574

575

(Mock
Object), . 
(Test Stub), 
.
, 
. , 
(Mock Object), $
(Retrieval Interface; . , Test Spy).


, (HardCoded
Test Double) .
public void testDisplayCurrentTime_AtMidnight_HCM()
throws Exception {
//
//

TimeProvider testStub = new MidnightTimeProvider();
//

TimeDisplay sut = new TimeDisplay();
//

sut.setTimeProvider(testStub);
//
String result = sut.getCurrentTimeAsHtmlFragment();
//
String expectedTimeString =
"<span class=\"tinyBoldText\">Midnight</span>";
assertEquals("Midnight", expectedTimeString, result);
}

,
(HardCoded Test Double). , 
, (Mystery Guest).
class MidnightTimeProvider implements TimeProvider {
public Calendar getTime() {
Calendar myTime = new GregorianCalendar();
myTime.set(Calendar.HOUR_OF_DAY, 0);
myTime.set(Calendar.MINUTE, 0);
return myTime;
}
}

(Obscure Test)
(Self Shunt), (HardCoded Test Double)
.
public class SelfShuntExample extends TestCase
implements TimeProvider {
public void testDisplayCurrentTime_AtMidnight() throws Exception {
//
TimeDisplay sut = new TimeDisplay();
//
sut.setTimeProvider(this); //

. 575

576

23

//
String result = sut.getCurrentTimeAsHtmlFragment();
//
String expectedTimeString =
"<span class=\"tinyBoldText\">Midnight</span>";
assertEquals("Midnight", expectedTimeString, result);
}
public Calendar getTime() {
Calendar myTime = new GregorianCalendar();
myTime.set(Calendar.MINUTE, 0);
myTime.set(Calendar.HOUR_OF_DAY, 0);
return myTime;
}
}

, (Test Double) 
(Testcase Class, . 401), , $
(Test Code Duplication).


, (HardCoded Test
Double),
(Configurable Test Double) . 
, ,
(Configurable Test Double). 
, (HardCoded Test
Double). ,
(Test Method) .
(HardCoded Test Double) $
(Configurable Test Double) , ,
. (

.) 
.
(Configurable Test
Double). 
(Configurable Test
Double) (Configuration Interface) 
(Configuration Mode).
(Configurable Test Double)
(Introduce field) , 
.

: (Configuration Interface)

, $
(Configuration Interface) (Setter
Injection).

. 576

577

public void testDisplayCurrentTime_AtMidnight()


throws Exception {
//
//
TimeProviderTestStub tpStub = new TimeProviderTestStub();
tpStub.setHours(0);
tpStub.setMinutes(0);
//
TimeDisplay sut = new TimeDisplay();
//

sut.setTimeProvider(tpStub);
//
String result = sut.getCurrentTimeAsHtmlFragment();
//
String expectedTimeString =
"<span class=\"tinyBoldText\">Midnight</span>";
assertEquals("Midnight", expectedTimeString, result);
}

(Configurable Test Double)


.
class TimeProviderTestStub implements TimeProvider {
// (Configuration Interface)
public void setHours(int hours) {
// 0 -- ; 12 --
myTime.set(Calendar.HOUR_OF_DAY, hours);
}
public void setMinutes(int minutes) {
myTime.set(Calendar.MINUTE, minutes);
}
//
public Calendar getTime() {
// @return
return myTime;
}
}

: (Configuration Interface)

, , 
, JMock. JMock
(Mock Object) 
. ,
JMock.
public void testDisplayCurrentTime_AtMidnight_JM()
throws Exception {
//
TimeDisplay sut = new TimeDisplay();
//
Mock tpStub = mock(TimeProvider.class);
Calendar midnight = makeTime(0,0);
tpStub.stubs().method("getTime").

. 577

578

23

withNoArguments().
will(returnValue(midnight));
//
sut.setTimeProvider((TimeProvider) tpStub);
//
String result = sut.getCurrentTimeAsHtmlFragment();
//
String expectedTimeString =
"<span class=\"tinyBoldText\">Midnight</span>";
assertEquals("Midnight", expectedTimeString, result);
}


(Testcase Class), 
. 
(Test Utility Method, . 610). 
(Mock Object)
.
public void testRemoveFlight_JMock() throws Exception {
//
FlightDto expectedFlightDto = createAnonRegFlight();
FlightManagementFacade facade = new FlightManagementFacadeImpl();
//
Mock mockLog = mock(AuditLog.class);
mockLog.expects(once()).method("logMessage")
.with(eq(helper.getTodaysDateWithoutTime()),
eq(Helper.TEST_USER_NAME),
eq(Helper.REMOVE_FLIGHT_ACTION_CODE),
eq(expectedFlightDto.getFlightNumber()));
//
facade.setAuditLog((AuditLog) mockLog.proxy());
//
facade.removeFlight(expectedFlightDto.getFlightNumber());
//
assertFalse("flight still exists after being removed",
facade.flightExists(expectedFlightDto.
getFlightNumber()));
// verify() JMock
}

(Expected Behavior Specification) 


, expects, once method, ,
(Configurable Test Double)
. JMock 
(, 
), $
(Configurable Test Double).

: (Configuration Mode)

(Mock Object) (Configuration Mode).

. 578

579

public void testRemoveFlight_ModalMock() throws Exception {


//
FlightDto expectedFlightDto = createAnonRegFlight();
// ( )
ModalMockAuditLog mockLog = new ModalMockAuditLog();
mockLog.logMessage(Helper.getTodaysDateWithoutTime(),
Helper.TEST_USER_NAME,
Helper.REMOVE_FLIGHT_ACTION_CODE,
expectedFlightDto.getFlightNumber());
mockLog.enterPlaybackMode();
//
FlightManagementFacade facade = new FlightManagementFacadeImpl();
facade.setAuditLog(mockLog);
//
facade.removeFlight(expectedFlightDto.getFlightNumber());
//
assertFalse("flight still exists after being removed",
facade.flightExists(expectedFlightDto.
getFlightNumber()));
mockLog.verify();
}

(Confi
gurable Test Double) . ,
, .
enterPlaybackMode, (Configurable Test Double)

.
(Configurable
Test Double).
private int mode = record;
public void enterPlaybackMode() {
mode = playback;
}
public void logMessage(Date date,
String user,
String action,
Object detail) {
if (mode == record) {
Assert.assertEquals("Only supports 1 expected call",
0, expectedNumberCalls);
expectedNumberCalls = 1;
expectedDate = date;
expectedUser = user;
expectedCode = action;
expectedDetail = detail;
} else {
Assert.assertEquals("Date", expectedDate, date);
Assert.assertEquals("User", expectedUser, user);
Assert.assertEquals("Action", expectedCode, action);
Assert.assertEquals("Detail", expectedDetail, detail);
}
}

. 579

580

23

if ( ).
(Configurable Test
Double) ,
(Guard Assertion, . 510)
. then 
,
(Equality Assertion) else.

. 580

581

(Hard/Coded Test Double)


(Test Double)
?
(Test Double)
/
.

:

(Hard-Coded Mock
Object), (Hard-Coded Test
Stub),
(Hard-Coded Test Spy)

(Test Double,
. 538) (Fully Automated
Tests, . 81). (Test Double) 
. .
(Test Double) 
, 
(Test Double).


(Test Double) 
. , (Test Double)
, return. 
, , 
.


(HardCoded Test Double)

(Test Double). (HardCoded Test

. 581

582

23

Double) (Test Stub, . 544), (Test Spy,


. 552) (Mock Object, . 558). 
, .
(HardCoded Test Double) 
, , $
(Configurable Test Double, . 571)
. , 

. (Test Double),
(HardCoded Test Double)
(Test Code Duplication, . 254),
(Configurable Test Double).


(HardCoded Test Double) 
(HandBuilt Test Double),
(HardCoded Test Double) 
. ,
, .
/
, . ,
.
,
, 
. 
(HardCoded
Test Double) .
(Hard
Coded Test Double). .

: (Test Double Class)


(HardCoded Test Double)
, (Testcase Class). 
(HardCoded Test Dou
ble) (Testcase Class), $
(Obscure Test), 
(, ,
). (Test Double Class) 
, .

(Test Double Class)
. ,
.1
1

. 582

583

: (Test Double Subclass)


(HardCoded Test Double)
, 
, . ,
, 
. ,
, (Overspecified
Software). (Test Double Subclass)
(, 
), , , .

: (Self Shunt)

:
(Testcase Class) (Loopback),
(Testcase Object, . 410) $ (Testcase
Class as Test Double)
(Test Double).
(Self Shunt).
(Self Shunt)
(Test Stub), (Test Spy) (Mock Object).
. 
(Testcase Class)
. 
(Testcase Class) , 
.
(Self Shunt) $
(HardCoded Test Double),
(Testcase Class). (Test Method, . 378)
(HardCoded Test Double), $
(Inner Test Double)
.

: (Inner Test Double)


(HardCoded
Test Double)
(Test Method).
(Test Double)
(Testcase Class) (Test Method),
(Test Double).
Java,

, .
(Inner Test Double)
(HardCoded Test Double), 
(Test Method).
(Inner Test Double) ,

. 583

584

23

(Self Shunt), $
(Test Method). ,
, .

: (Pseudo/Object)
(HardCoded
Test Double) , 
. , Java
C#, , 
, . 
,
.

, 
. (HardCoded Test
Double) 
, .
, (PseudoObject)
.


, 
HTML . , 
!
public void testDisplayCurrentTime_AtMidnight() {
//
TimeDisplay sut = new TimeDisplay();
//
String result = sut.getCurrentTimeAsHtmlFragment();
//
String expectedTimeString =
"<span class=\"tinyBoldText\">Midnight</span>";
assertEquals( expectedTimeString, result);
}



(HardCoded Test Double)2.

(Test Double) (Test Method). , 
, ,
2

(Configurable Test Double) 


(HardCoded Test Double) ,
(Test Double)
( ) .

. 584

585

(Test Double)
(Dependency Injection, . 684). 
(Replace
Dependency with Test Double, . 740).

: (Test Double Class)


, $
(HardCoded Test Double),
.
public void testDisplayCurrentTime_AtMidnight_HCM()
throws Exception {
//
//
TimeProvider testStub = new MidnightTimeProvider();
//

TimeDisplay sut = new TimeDisplay();
//
sut.setTimeProvider(testStub);
//
String result = sut.getCurrentTimeAsHtmlFragment();
//
String expectedTimeString =
"<span class=\"tinyBoldText\">Midnight</span>";
assertEquals("Midnight", expectedTimeString, result);
}

,
(HardCoded Test Double). , 
(Obscure Test).
class MidnightTimeProvider implements TimeProvider {
public Calendar getTime() {
Calendar myTime = new GregorianCalendar();
myTime.set(Calendar.HOUR_OF_DAY, 0);
myTime.set(Calendar.MINUTE, 0);
return myTime;
}
}


(Test Double Class) ,
(Testcase Class) ( ), 
 . , (Test
Method) (Test Double Class), 
(Mystery Guest).

: (Self Shunt) ()
,
(Self Shunt).

. 585

586

23

public class SelfShuntExample extends TestCase


implements TimeProvider {
public void testDisplayCurrentTime_AtMidnight() throws Exception {
//
TimeDisplay sut = new TimeDisplay();
//
sut.setTimeProvider(this); //
//
String result = sut.getCurrentTimeAsHtmlFragment();
//
String expectedTimeString =
"<span class=\"tinyBoldText\">Midnight</span>";
assertEquals("Midnight", expectedTimeString, result);
}
public Calendar getTime() {
Calendar myTime = new GregorianCalendar();
myTime.set(Calendar.MINUTE, 0);
myTime.set(Calendar.HOUR_OF_DAY, 0);
return myTime;
}
}

, (Test Method), $
(HardCoded Test Double), getTime, 
, . $
(HardCoded Test Double) $
(Setter Injection).
, implements TimeProvider
(Testcase Class). sut.setTimeProvider(this)
. .

: (Inner Test Double)


JUnit, $
(Inner Test Double)
(anonymous inner class).
public void testDisplayCurrentTime_AtMidnight_AIM() throws Exception {
//
//
TimeProvider testStub = new TimeProvider() {
//
public Calendar getTime() {
Calendar myTime = new GregorianCalendar();
myTime.set(Calendar.MINUTE, 0);
myTime.set(Calendar.HOUR_OF_DAY, 0);
return myTime;
}
};
//
TimeDisplay sut = new TimeDisplay();
//
sut.setTimeProvider(testStub);

. 586

587

//
String result = sut.getCurrentTimeAsHtmlFragment();
//
String expectedTimeString =
"<span class=\"tinyBoldText\">Midnight</span>";
assertEquals("Midnight", expectedTimeString, result);
}

new
(HardCoded Test Double) (TimeProvider). gettime
$
(Test Method).

: (Inner Test Double),



, 
. 
.
(PseudoObject).
/**
*
*
**/
public class PseudoTimeProvider implements ComplexTimeProvider {
public Calendar getTime() throws TimeProviderEx {
throw new PseudoClassException();
}
public Calendar getTimeDifference(Calendar baseTime,
Calendar otherTime)
throws TimeProviderEx {
throw new PseudoClassException();
}
public Calendar getTime(String timeZone) throws TimeProviderEx {
throw new PseudoClassException();
}
}

, ,
getTime
( ).
public void testDisplayCurrentTime_AtMidnight_PS() throws Exception {
//
//

TimeProvider testStub = new PseudoTimeProvider()
{ //
public Calendar getTime(String timeZone) {
Calendar myTime = new GregorianCalendar();
myTime.set(Calendar.MINUTE, 0);

. 587

588

23

myTime.set(Calendar.HOUR_OF_DAY, 0);
return myTime;
}
};
//

TimeDisplay sut = new TimeDisplay();
//

sut.setTimeProvider(testStub);
//
String result = sut.getCurrentTimeAsHtmlFragment();
//
String expectedTimeString =
"<span class=\"tinyBoldText\">Midnight</span>";
assertEquals("Midnight", expectedTimeString, result);
}


. , 
, .
com..PseudoClassEx: Unexpected call to unsupported method.
at com..PseudoTimeProvider.getTime(PseudoTimeProvider.java:22)
at com..TimeDisplay.getCurrentTimeAsHtmlFragment(TimeDisplay.java:64)
at com..TimeDisplayTestSolution.
testDisplayCurrentTime_AtMidnight_PS(
TimeDisplayTestSolution.java:247)

?

, .  ,
. .
, ,
. .
, , Pat
tern Languages of Programs (PLoP) (http://www.hillside.net/conferences/plop).

. (Buffalo Mountain).
(Architect Also Implements).
.
,
. ,
.
, .
,
. .
, . 
, .
(Self Shunt). 
, 
. .

. 588

589

, .
,
, , .
(Self Shunt)  .


 , 
. . 

(, ).
. 
setUp .
(Test Method, . 378) ,
. 
(Shared Setup Method), (pattern language)
(Implicit Setup, . 449). ?
. ,
(Shared Setup Method)
(Shared Fixture, . 350). ( 
, 
.) , (Implicit
Setup) (Inline Setup, . 432)
(Delegated Setup, . 437). , (Inline Setup), 
(Delegated Setup) (Implicit Setup) ,
(Inline Setup), (Delegated Setup)
(Shared Setup Method). 
, .



, (Test Stub,
. 544) (Mock Object, . 558).
.
 (Put a mock in it)
( !), ? (mock)

(Test Stub) (Fake
Database) 50 . (, 50!

. 351.) ,

(Mock Object), (Expected Behavior).
(mock) (Mock
Object)  ,  
. , (Test Double,
. 538) ( 
, Mock Object).

. 589

590

23


, ,
:
http://www1.bell-labs.com/user/cope/Patterns/Process/
section29.html
:
http://www1.bell-labs.com/user/cope/Patterns/Process/
section16.html
,
(http://alistair.cockburn.us).
. ?
, 
.
.


(Self Shunt) 
([TDDAPG], [TDDBE], [UTwJ], [PUT] [JuPG]).
:
http://www.objectmentor.com/resources/articles/SelfShunPtrn.pdf

(Shunt) :
http://http://c2.com/cgi/wiki?ShuntPattern

, Lookback. 
,
?.
(PseudoObject) PseudoClasses: Very
Simple and Lightweight Mock Objectlike Classes for UnitTesting, :
http://www.devx.com/Java/Article/22599/1954?pf=true

. 590

591

(Test/Specific Subclass)
,

?

:
(Test-Specific Extension)


,
.

SU
T

Method Under
T est

Internal Method

Setup

Exercise

Verify

T e st /

S p e c if ic

S ubc l a s s

Overridden
Self Ca ll

Internal Me thod

Teardown

,
, ,
.
(TestSpecific Subclass) ,
.



, 
.
,

.
(TestSpecific Subclass) ,
,
.
12

1
2

. 591

592

23


(TestSpecific Subclass) 
, ,
(Test
Logic in Production, . 257). (TestSpecific Subclass) 
, ,
. (Test
Specific Subclass) :
, $
(Fragile Test, . 277).

: (State/Exposing Subclass)
(State Verification, . 484) 
( ) 
, (Assertion Method, . 390).
. ,
,
(Obscure Test), .

: (Behavior/Exposing Subclass)
, 
, 
.
, (TestSpecific Subclass) 
.

: (Behavior/Modifying Subclass)

, . 
, ( )
.

: (Test Double Subclass)


$
(Test Double, . 538) 
(Test Double)
.
(Test Double),

, .. , 
. ( ,
Ruby, Python, Perl JavaScript, .) 
, ,
:
(Subclassed Test Double)

. 592

593

(Test Double)
(Configurable Test Double, . 571), .
(BehaviorModifying Subclass) $
(Test Double Subclass)
( ), .

: (Substituted Singleton)

(Test Double Subclass). 
(Test
Double), 
(Dependency Injection,
. 684) (Dependency Lookup, . 692).

:

(Subclassed
Singleton),
(Substitutable Singleton)


(TestSpecific Subclass)
.

. ,
, .
.

.
. , 
, Java, C# C++. 
.

(Test Double), ,
.
(, Smalltalk,
Ruby, JavaScript ) $
(TestSpecific Subclass) 
. , ,
(Test Logic in Production).


, ,

. , 
, public ( 
) 
.
, Java private protected, (TestSpecific
Subclass). .

. 593

594

23


, 
. , ,
. .
, . 
. , 
,
(Test Double Subclass).
 ,

. ,
,
(, ). , 
(transaction
script) [PEAA].
(Extract Method), 
.


, .
,
Web.
TimeProvider, , 
.
public void testDisplayCurrentTime_AtMidnight() throws Exception {
//
TimeDisplay theTimeDisplay = new TimeDisplay();
//
String actualTimeString =
theTimeDisplay.getCurrentTimeAsHtmlFragment();
//
String expectedTimeString =
"<span class=\"tinyBoldText\">Midnight</span>";
assertEquals("Midnight",
expectedTimeString,
actualTimeString);
}
public void testDisplayCurrentTime_AtOneMinuteAfterMidnight()
throws Exception {
//
TimeDisplay actualTimeDisplay = new TimeDisplay();
//
String actualTimeString =
actualTimeDisplay.getCurrentTimeAsHtmlFragment();
//
String expectedTimeString =
"<span class=\"tinyBoldText\">12:01 AM</span>";

. 594

595

assertEquals("12:01 AM",
expectedTimeString,
actualTimeString);
}


! .
public String getCurrentTimeAsHtmlFragment() {
Calendar timeProvider;
try {
timeProvider = getTime();
} catch (Exception e) {
return e.getMessage();
}
// ..
}
protected Calendar getTime() {
return TimeProvider.getInstance().getTime();
}

.
public class TimeProvider {
protected static TimeProvider soleInstance = null;
protected TimeProvider() {};
public static TimeProvider getInstance() {
if (soleInstance==null) soleInstance = new TimeProvider();
return soleInstance;
}
public Calendar getTime() {
return Calendar.getInstance();
}
}



(TestSpecific Subclass) .
(TestSpecific Subclass) 


.
, (TestSpecific Subclass) 
, $
(Replace Dependency with Test Double, . 740), 
.

(TestSpecific Subclass) (
) .

. 595

596

23

: (Behavior/Modifying Subclass)
(Test Stub)
getTime 
TimeProvider, 
(Subclassed Test Double)3.
( ).
public void testDisplayCurrentTime_AtMidnight() {
//
TimeDisplayTestStubSubclass tss = new TimeDisplayTestStubSubclass();
TimeDisplay sut = tss;
// (Test Double)
tss.setHours(0);
tss.setMinutes(0);
//
String result = sut.getCurrentTimeAsHtmlFragment();
//
String expectedTimeString =
"<span class=\"tinyBoldText\">Midnight</span>";
assertEquals( expectedTimeString, result );
}

(TestSpecific
Subclass) , . 
(Configu
ration Interface) 4.
(TestSpecific Subclass) sut.
, .
(Mystery Guest), 
$
(Test Stub, . 544).
$
(TestSpecific Subclass).
public class TimeDisplayTestStubSubclass extends TimeDisplay {
private int hours;
private int minutes;
//
protected Calendar getTime() {
Calendar myTime = new GregorianCalendar();
myTime.set(Calendar.HOUR_OF_DAY, this.hours);
myTime.set(Calendar.MINUTE, this.minutes);
return myTime;
}
/*
3

, getTime , protected. 
(private) .
4 (HardCoded Test Double,
. 581), (TestSpecific Sub
class) .
getTime.

. 596

597

*
*/
public void setHours(int hours) {
this.hours = hours;
}
public void setMinutes(int minutes) {
this.minutes = minutes;
}
}

 ,
.

: (Behavior/Modifying Subclass)

, getTime private5, static, final
sealed6 .. $
(TestSpecific Subclass).
(Nondeterministic Test)?

,
(Test Double Subclass). ,
soleInstance. (Introduce local
extension) ( )
(TestSpecific Subclass). 
.
public void testDisplayCurrentTime_AtMidnight() {
TimeDisplay sut = new TimeDisplay();
//
TimeProviderTestSingleton timeProvideSingleton =
TimeProviderTestSingleton.overrideSoleInstance();
timeProvideSingleton.setTime(0,0);
//
String actualTimeString = sut.getCurrentTimeAsHtmlFragment();
//
String expectedTimeString =
"<span class=\"tinyBoldText\">Midnight</span>";
assertEquals( expectedTimeString, actualTimeString );
}

, ,
, .
public class TimeProviderTestSingleton extends TimeProvider {
private Calendar myTime = new GregorianCalendar();
private TimeProviderTestSingleton() {};
//
static TimeProviderTestSingleton overrideSoleInstance() {
5
6

. 597

private .
.

598

23

// ,
// !
soleInstance = new TimeProviderTestSingleton();
return (TimeProviderTestSingleton) soleInstance;
}
//
public void setTime(int hours, int minutes) {
myTime.set(Calendar.HOUR_OF_DAY, hours);
myTime.set(Calendar.MINUTE, minutes);
}
// ,
public Calendar getTime() {
return myTime;
}
}

(Test Double) 
, .

: (Behavior/Exposing Subclass)
, getTime.
getTime , 
TimeDisplay, .
TimeDisplay ,
TimeDisplay. ,
.

(BehaviorExposing Subclass).
(TestSpecific Subclass) public, 
.
public class TimeDisplayBehaviorExposingTss extends TimeDisplay {
public Calendar callGetTime() {
return super.getTime();
}
}

,
(BehaviorExposing Subclass).
public void testGetTime_default() {
//
TimeDisplayBehaviorExposingTss tsSut =
new TimeDisplayBehaviorExposingTss();
//
// :
//
Calendar time = sut.getTime();
//
Calendar time = tsSut.callGetTime();
//
assertEquals( defaultTime, time );
}

. 598

599

:
(Behavior/Modifying Subclass)
, , 
assertEquals
. , equals 
false, .
protected void setUp() throws Exception {
oneOutboundFlight = findOneOutboundFlightDto();
}
public void testGetFlights_OneFlight() throws Exception {
//
List flights = facade.getFlightsByOriginAirport(
oneOutboundFlight.getOriginAirportId());
//
assertEquals("Flights at origin - number of flights: ",
1,
flights.size());
FlightDto actualFlightDto = (FlightDto)flights.get(0);
assertEquals("Flight DTOs at origin",
oneOutboundFlight,
actualFlightDto);
}

(Custom Assertion,
. 495).
(TestSpecific Subclass) , 
. (TestSpecific
Subclass) (Expected Object)
.
private FlightDtoTss oneOutboundFlight;
private FlightDtoTss findOneOutboundFlightDto() {
FlightDto realDto = helper.findOneOutboundFlightDto();
return new FlightDtoTss(realDto) ;
}

, (TestSpecific Subclass) 
,
.
public class FlightDtoTss extends FlightDto {
public FlightDtoTss(FlightDto realDto) {
this.destAirportId = realDto.getDestinationAirportId();
this.equipmentType = realDto.getEquipmentType();
this.flightNumber = realDto.getFlightNumber();
this.originAirportId = realDto.getOriginAirportId();
}
public boolean equals(Object obj) {
FlightDto otherDto = (FlightDto) obj;
if (otherDto == null) return false;
if (otherDto.getDestAirportId()!= this.destAirportId)

. 599

600

23

return false;
if (otherDto.getOriginAirportId()!= this.originAirportId)
return false;
if (otherDto.getFlightNumber()!= this.flightNumber)
return false;
if (otherDto.getEquipmentType() != this.equipmentType )
return false;
return true;
}
}


(TestSpecific Subclass),
. 
. .
, 
toString .
assertEquals, equals false. 
, , .

: (State/Exposing Subclass)
, , Flight
.
protected void setUp() throws Exception {
super.setUp();
scheduledFlight = createScheduledFlight();
}
Flight createScheduledFlight() throws InvalidRequestException{
Flight newFlight = new Flight();
newFlight.schedule();
return newFlight;
}
public void testDeschedule_shouldEndUpInUnscheduleState()
throws Exception {
scheduledFlight.deschedule();
assertTrue("isUnsched", scheduledFlight.isUnscheduled());
}

,
schedule Flight.
public class Flight{
protected FlightState currentState = new UnscheduledState();
/**
* Flight <code>unscheduled</code>
* <code>scheduled</code>.
* @throws InvalidRequestException
*

*/
public void schedule() throws InvalidRequestException{
currentState.schedule();
}
}

. 600

601

Flight State, schedule 


State, currentState.
schedule currentState, . 
, (State
Exposing Subclass),
, , .
public class FlightTss extends Flight {
public void becomeScheduled() {
currentState = new ScheduledState();
}
}

becomeScheduled (TestSpecific
Subclass),
. ,
(Creation Method, . 441).
Flight createScheduledFlight() throws InvalidRequestException{
FlightTss newFlight = new FlightTss();
newFlight.becomeScheduled();
return newFlight;
}

, Flight,
(TestSpecific Subclass) 
.

. 601

. 602

24

24


:
(Named Test Suite) ....................................... 604

(Test Utility Method) ................................ 610
(Parameterized Test)......................................... 618

(Testcase Class per Class) ........................ 627
(Testcase Class per Feature).................. 633

(Testcase Class per Fixture).......................................................................... 639

(Testcase Superclass) ...................................................... 646
(Test Helper).............................................. 651

. 603

604

24

(Named Test Suite)


?
, /
, .

testMethod_1

testMethod_n

.
. 
, 
, 
.
(Named Test Suite)
.



(Test Suite Factory) .
(Test Suite
Object, . 414), (Testcase Object, . 410).


,
.
.
xUnit (Test Selection),
, $
(Subset Suite).

. 604

605

: (AllTests Suite)
.
(AllTests Suite)
( ) 
( ). 
(AllTests Suite)
,
, , .

: (Subset Suite)
 (Slow
Tests, . 289). , ,
, .
(Named Test Suite) (Named
Test Suite) , , 
, (Subset Suite).

. , Web
Web
, , Web
( ).

: (Single Test Suite)


(Subset Suite)
(Single Test Suite),
(Testcase Object), (Test Method,
. 378). $
(Test Tree Explorer), ,
(Test Method) (Setup
Decorator, . 471).
(Testcase Class) .


.
,
(Test Enumeration),  $
(Test Discovery, . 420). , 
(Test Selection, . 429)
. xUnit (AllTests
Suite) . , NUnit, $
(Test Suite Object) .
(Test Enumeration)
(Named Test Suite) 
(AllTests Suite) .

. 605

606

24

(AllTests Suite) (Suite of Suites) (Testcase


Class) (Named Test Suite);
(AllTests Suite) 
, (Named Test Suite)
.


(Named Test
Suite) .

(Named Test Suite).

: (AllTests Suite)
(AllTests Suite) 
. 
(, Java)
( , Test Suite Factory),
AllTests. suite (Test Suite Factory)
(Named Test Suite) 
(, Java). ,
(Named Test Suite) $
(Named Test Suite) .
,
xUnit.
public class AllTests {
public static Test suite() {
TestSuite suite = new TestSuite("Test for allJunitTests");
//$JUnit-BEGIN$
suite.addTestSuite(
com.clrstream.camug.example.test.InvoiceTest.class);
suite.addTest(com.clrstream.ex7.test.AllTests.suite());
suite.addTest(com.clrstream.ex8.test.AllTests.suite());
suite.addTestSuite(
com.xunitpatterns.guardassertion.Example.class);
//$JUnit-END$
return suite;
}
}

,
(Named Test Suite) (Test Suite
Object), (Testcase Class). JUnit
. xUnit
.
, ,
JUnit-start JUnit-end. ( 
Eclipse) , 
(Test Discovery).

. 606

607

: (Special/Purpose Suite)
, (A, B C), 
. , 
. . 
, 
, .
(A, B C) 
:

, ;

, .

12 (
).
(A, B C)
(Named Test Suite):

AllDbTests ( , Testcase Class,


);

AllInMemoryTests ( , Testcase Class, 


);

AllTests ( AllDbTests AllInMemoryTests).


(Named Test Suite) :

AllDbTests ( AllDbTests
A, B C);

AllInMemoryTests ( AllInMemoryTests A, B C);

AllTests ( AllTests
A, B C; , AllTests Suite).

(Testcase Class)
(Named Test Suite), 
(,
).

: (Single Test Suite)


, ,
. 
(Test Tree Explorer).
, , 
, 
(Test Discovery).

. 607

608

24

public class LostTests extends TestCase {


public LostTests(String name) {
super(name);
}
public void xtestOne() throws Exception {
fail("test not implemented");
}
/*
public void testTwo() throws Exception {
fail("test not implemented");
}
*/
public void testSeventeen() throws Exception {
assertTrue(true);
}
}

,
$
(Lost Test). (Single Test Suite)
( ) (Testcase
Class). , xUnit
(Testcase Class) . 
, 
. 
(Test Method) . (Testcase
Object) (Test Suite Object). $
(Pluggable behavior).

(Test Suite Factory) suite,
(Testcase Class),
(Test Method).
suite (Test Suite Object),
(Testcase Object), 
(Testcase Class).
public class MyTest extends TestCase {
public static Test suite() {
return new LostTests("testSeventeen");
}
}

(Single Test Suite)



suite.
(Single Test Suite) . 
, (Test Tree Explorer)
. ( !)

. 608

609

: (Smoke Test Suite)


(smoke test suite)
(SpecialPuprose Suite)
(Single Test Suite). 
(Test Suite Object).
public class SmokeTestSuite extends TestCase {
public static Test suite() {
TestSuite mySuite = new TestSuite("Smoke Tests");
mySuite.addTest(new LostTests("testSeventeen"));
mySuite.addTest(new SampleTests("testOne"));
mySuite.addTest(new FlightManagementFacadeTest(
"testGetFlightsByOriginAirports_TwoOutboundFlights"));
//
return mySuite;
}
}

, 
.

. 609

610

24

(Test Utility Method)


(Test Code Duplication)?

.

SU T


.
. 
, (Test Code Duplication,
. 254) .
(Test Utility Method).



. (Test Util
ity Method)  . ,
,
(Test Utility Method). 
. , 
.


(Test Utility Method)
,

. 610

611

. , (Test Utility Method)


. , 
(SelfChecking Test)
. (Test Method) ,
(Test Utility
Method) .

(Test Utility Method) , 
. 

.
(Test Utility Method).
.
, .

: (Creation Method)
(Creation Method, . 441) 
, . 
. (Creation
Method) , .

: (Attachment Method)
(Attachment Method)
(Creation Method) 
, .

: (Finder Method)
(Shared Fixture,
. 350) , .
, 
.
(Finder Method)
(Shared Fixture), 
. $
(Fragile Fixture) (High
Test Maintenance Cost, . 300). (Finder Method)
(Shared Fixture),

(Immutable Shared Fixture). , (Finder Method) 
(Obscure Test, . 230) 
,

, . 
.

. 611

612

24

(Finder Method)
, (..
, ). 
(Finder Method), 
(Array Hash) ,
(Finder Method) . , (Finder
Method)
, ( 
).
,
(Finder Method) (Test
Helper, . 651).
(Finder Method) (Shared
Fixture) : ( 
, ),
.

. 
, 
, . 
,
, .
(Shared Fixture)
( 
, Test Method).

: (SUT Encapsulation Method)



(Test Utility Method) 

. ?
, , 
, .
(Creation Method) (Custom Assertion, . 495)
(SUT Encapsula
tion Method), . 
. ,
( ) ,
, .
,
(SUT Encapsulation Method) .
:

(SUT API Encapsulation)

: (Custom Assertion)
(Custom Assertion) 
,
.

. 612

613

. (Custom Assertion) 
; 
.

: (Verification Method)
(Verification Method) 
. .
(Custom Assertion) (Verification Method) 
.

: (Parameterized Test)
(Test Utility Method)
(Parameterized Test, . 618).
, .
,
(Parameterized Test) (FourPhase Test, . 387).

: (Cleanup Method)
(Cleanup Method)1 
, .

, (Automated Teardown, . 521).


(Test Util
ity Method) ,
. 
.
,
(Obscure Test) (HigherLevel
Language, . 95). , (Test Utility Method)
.
( ). 
.

(Test Utility Method), 
, .

.
(Test Util
ity Method) . . 
1

 teardown method, 
, (Implicit Teardown, . 533).

. 613

614

24

(Test Utility Method)


(Testcase Class, . 401), . $
(Test Utility Method) ,
. .
(Test Utility Method), 
, . 
/ , $
(Test Utility Method)
(Testcase Superclass, . 646), 
. / ,
, ,
(Test Helper), 
.
() 
(Test Helper).

: (Test Utility Test)



(Test Utility Method) . 
,
(Custom Assertion Test).


,
.
public void testAddItemQuantity_severalQuantity_v1(){
Address billingAddress = null;
Address shippingAddress = null;
Customer customer = null;
Product product = null;
Invoice invoice = null;
try {
//

billingAddress = new Address("1222 1st St SW",
"Calgary", "Alberta",
"T2N 2V2", "Canada");
shippingAddress = new Address("1333 1st St SW",
"Calgary", "Alberta",
"T2N 2V2", "Canada");
customer = new Customer(99, "John", "Doe",
new BigDecimal("30"),
billingAddress,
shippingAddress);
product = new Product(88, "SomeWidget",
new BigDecimal("19.99"));
invoice = new Invoice(customer );
//
invoice.addItemQuantity(product, 5);
//

. 614

615

List lineItems = invoice.getLineItems();


if (lineItems.size() == 1) {
LineItem actItem = (LineItem) lineItems.get(0);
assertEquals("inv", invoice, actItem.getInv());
assertEquals("prod", product, actItem.getProd());
assertEquals("quant", 5, actItem.getQuantity());
assertEquals("discount",
new BigDecimal("30"),
actItem.getPercentDiscount());
assertEquals("unit price",
new BigDecimal("19.99"),
actItem.getUnitPrice());
assertEquals("extended",
new BigDecimal("69.96"),
actItem.getExtendedPrice());
} else {
assertTrue("Invoice should have 1 item", false);
}
} finally {
//
deleteObject(invoice);
deleteObject(product);
deleteObject(customer);
deleteObject(billingAddress);
deleteObject(shippingAddress);
}
}

, , $
(Obscure Test) (HardCoded Test Data).


(Test Utility Method) 
. 
(Extract Method). 
,
(Pull up method)
(Move method).

: (Test Utility Method)


. , 
. (Test
Utility Method).
public void testAddItemQuantity_severalQuantity_v13(){
final int QUANTITY = 5;
final BigDecimal CUSTOMER_DISCOUNT = new BigDecimal("30");
//
Customer customer =
findActiveCustomerWithDiscount(CUSTOMER_DISCOUNT);
Product product = findCurrentProductWith3DigitPrice( );
Invoice invoice = createInvoice(customer);

. 615

616

24

//
invoice.addItemQuantity(product, QUANTITY);
//
final BigDecimal BASE_PRICE = product.getUnitPrice().
multiply(new BigDecimal(QUANTITY));
final BigDecimal EXTENDED_PRICE =
BASE_PRICE.subtract(BASE_PRICE.multiply(
CUSTOMER_DISCOUNT.movePointLeft(2)));
LineItem expected =
createLineItem(QUANTITY, CUSTOMER_DISCOUNT,
EXTENDED_PRICE, product, invoice);
assertContainsExactlyOneLineItem(invoice, expected);
}

. Customer Product (Finder Method),


(Immutable Shared Fixture).
, .
protected Customer findActiveCustomerWithDiscount(
BigDecimal percentDiscount) {
return CustomerHome.findCustomerById(
ACTIVE_CUSTOMER_WITH_30PC_DISCOUNT_ID);
}

(Creation Method) Invoice,


LineItem.
protected Invoice createInvoice(Customer customer) {
Invoice newInvoice = new Invoice(customer);
registerTestObject(newInvoice);
return newInvoice;
}
List testObjects;
protected void registerTestObject(Object testObject) {
testObjects.add(testObject);
}

(Inline Teardown, . 528), 


(Automated Tear
down), tearDown.
private void deleteTestObjects() {
Iterator i = testObjects.iterator();
while (i.hasNext()) {
try {
deleteObject(i.next());
} catch (RuntimeException e) {
// ;
//
}
}
}
public void tearDown() {
deleteTestObjects();
}

. 616

617

, (Custom Assertion), 
Invoice LineItem.
void assertContainsExactlyOneLineItem( Invoice invoice,
LineItem expected) {
List lineItems = invoice.getLineItems();
assertEquals("number of items", lineItems.size(), 1);
LineItem actItem = (LineItem)lineItems.get(0);
assertLineItemsEqual("",expected, actItem);
}

. 617

618

24

(Parameterized Test)
(Test Code Duplication),
?

,
.

 
, 
. , 
, , 
. .
,
, 
.
(Parameterized Test)
(Test Method, . 378).1


, .
(FourPhase
Test, . 387), .. , , 
, 

. 618

619

(Parameterized Test). 
. , 
.

. 

(Test Utility Method, . 610), ,
. (Test Method)
(Parameterized Test) , 
.


(Parameterized Test) ,
(Test Code Duplication, . 254)
, .
, (Parameterized Test),
. ,
(Parameterized Test) (Obscure Test,
. 230). (Testcase Class, . 401) 
. , (Parameterized Test) 
(Data
Driven Test, . 322). (Parametrized Test)
(DataDriven Test), 
.

, (Verification Method).
,
(Custom Assertion).


(Parameterized Test) , 
. ,
.
test. ,
. xUnit, 
(Test Discovery, . 420), (Testcase Ob
ject, . 410) , test,
.
(Parameterized Test) , test. 
xUnit (MbUnit) (Parameterized Test)
(Test Automation Framework, . 332).
.
DDSteps JUnit.

(SelfChecking Test, . 81) (Parameterized Test).

. 619

620

24

( 
) . 
, (Custom Assertion), 
.
, (Test Double),
2.

: (Tabular Test)


(Parameterized Test)  (Tabular Test).
(Parameterized Test),
(Test Method). 
, (Eager Test), 
. , ,
, (Defect Lo
calization, . 78) .
:
( ), $
(Testcase Object).
(Incremental Tabular Test).
(Tabular Test) 
. xUnit
: MbUnit
[RowTest], (Parameterized Test),
[Row(x,y,...)] . ,
xUnit. ( !)
:
(Row Test)

: (Incremental Tabular Test)


(Incremental Tabular Test)
,
.
(Interacting Tests), 
(Chained Tests, . 477);
(Test Method). (Test Method) 
DoFixture Fit, 
3.
2

,
(Test Double) . , ,
. $
(Parameterized Test), 
. ; ,
.)
3  (Test Method) 
xUnit.

. 620

621

: (Loop/Driven Test)

, (Parameterized Test)
, . , 
. 

( ) (Calculated Value)
(Production Logic in Test).
(LoopDriven Test) ,
(Tabular Test), (Test
Method), , (Testcase Object).


runit (Ruby Unit), 
Web, Ruby 
. (Simple Success Test) 
: 
XML, HTML, , 
XML, HTML 
HTML.
def test_extref
#
sourceXml = "<extref id='abc'/>"
expectedHtml = "<a href='abc.html'>abc</a>"
mockFile = MockFile.new
@handler = setupHandler(sourceXml, mockFile)
#
@handler.printBodyContents
#
assert_equals_html(expectedHtml, mockFile.output,
"extref: html output")
end
def testTestterm_normal
sourceXml = "<testterm id='abc'/>"
expectedHtml = "<a href='abc.html'>abc</a>"
mockFile = MockFile.new
@handler = setupHandler(sourceXml, mockFile)
@handler.printBodyContents
assert_equals_html(expectedHtml, mockFile.output,
"testterm: html output")
end
def testTestterm_plural
sourceXml ="<testterms id='abc'/>"
expectedHtml = "<a href='abc.html'>abcs</a>"
mockFile = MockFile.new
@handler = setupHandler(sourceXml, mockFile)
@handler.printBodyContents
assert_equals_html(expectedHtml, mockFile.output,
"testterms: html output")
end

. 621

622

24

setupHandler,
(Test Code Duplication) .
20 ( 
), .


(Parameterized Test) 
(Custom Assertion). 

(Extract Method). ,
$
(Parameterized Test).

: (Parameterized Test)
: 
, 
. (Parameterized Test).
def test_extref
sourceXml = "<extref id='abc' />"
expectedHtml = "<a href='abc.html'>abc</a>"
generateAndVerifyHtml(sourceXml,expectedHtml,"<extref>")
end
def test_testterm_normal
sourceXml = "<testterm id='abc'/>"
expectedHtml = "<a href='abc.html'>abc</a>"
generateAndVerifyHtml(sourceXml,expectedHtml,"<testterm>")
end
def test_testterm_plural
sourceXml = "<testterms id='abc'/>"
expectedHtml = "<a href='abc.html'>abcs</a>"
generateAndVerifyHtml(sourceXml,expectedHtml,"<plural>")
end

, (Paramete
rized Test).
def generateAndVerifyHtml(sourceXml, expectedHtml,
message, &block)
mockFile = MockFile.new
sourceXml.delete!("\t")
@handler = setupHandler(sourceXml, mockFile)
block.call unless block == nil
@handler.printBodyContents
actual_html = mockFile.output
assert_equal_html(expectedHtml,
actual_html,
message + "html output")
actual_html
end

. 622

623

(Parameterized Test)
(Verification Method)  (Four
Phase Test) ( ),
(Verification Method) 
. , ,
(GarbageCollected Teardown, . 518).

: (Independent Tabular Test)


,
(Independent Tabular Test).
def test_a_href_Generation
row("extref","abc","abc.html","abc")
row("testterm" ,'abc',"abc.html","abc")
row("testterms",'abc',"abc.html","abcs")
end
def row(tag, id, expected_href_id, expected_a_contents)
sourceXml = "<" + tag + " id='" + id + "'/>"
expectedHtml = "<a href='" + expected_href_id + "'>"
+ expected_a_contents + "</a>"
msg = "<" + tag + "> "
generateAndVerifyHtml(sourceXml, expectedHtml, msg)
end

, ?
(Inline temp) 
sourceXml expectedHtml
generateAndVerifyHtml (Test Method) 
. 
( 
).
HTML XML row.
row MbUnit, 
, test_element.
, (Test Runner, . 406) 
.
(Test Method), ,
, .
(Interacting Tests), generateAndVerify 
.
.

: (Incremental Tabular Test)


(Tabular Test) $
(Test Method), (Testcase
Object). . 
, .

. 623

624

24

public class TabularTest extends TestCase {


private Order order = new Order();
private static final double tolerance = 0.001;
public void testGetTotal() {
assertEquals("initial", 0.00, order.getTotal(), tolerance);
testAddItemAndGetTotal("first", 1, 3.00, 3.00);
testAddItemAndGetTotal("second",3, 5.00, 18.00);
// ..
}
private void testAddItemAndGetTotal(String msg,
int lineItemQuantity,
double lineItemPrice,
double expectedTotal) {
//
LineItem item = new LineItem(lineItemQuantity,
lineItemPrice);
//
order.addItem(item);
//
assertEquals(msg,expectedTotal,order.getTotal(),tolerance);
}
}

, (Incremental
Tabular Test) .

: (Tabular Test)
(MbUnit)
MbUnit, 
[RowTest]
(Parameterized Test) [Row(x,y,...)]
.
[RowTest()]
[Row(1,2,3)]
[Row(2,3,5)]
[Row(3,4,8)]
[Row(4,5,9)]
public void tAdd(Int32 x, Int32 y, Int32 expectedSum)
{
Int32 Sum;
Sum = this.Subject.Add(x,y);
Assert.AreEqual(expectedSum, Sum);
}

[Row(x,y,...)], 
.
(Defect Localization), .

.

. 624

625

: (Loop/Driven Test) ( )

.
public void testMultipleValueSets() {
//
Calculator sut = new Calculator();
TestValues[] testValues = {
new TestValues(1,2,3),
new TestValues(2,3,5),
new TestValues(3,4,8), // !
new TestValues(4,5,9)
};
for (int i = 0; i < testValues.length; i++) {
TestValues values = testValues[i];
//
int actual = sut.calculate(values.a, values.b);
//
assertEquals(message(i), values.expectedSum, actual);
}
}
private String message(int i) {
return "Row "+ String.valueOf(i);
}


.
(Production Logic in Test).

: (Loop/Driven Test)
(Calculated Values)
.
public void testCombinationsOfInputValues() {
//
Calculator sut = new Calculator();
int expected; //
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
//
int actual = sut.calculate( i, j );
//
if (i==3 & j==4) //
expected = 8;
else
expected = i+j;
assertEquals(message(i,j), expected, actual);
}
}
}
private String message(int i, int j) {
return "Cell( " + String.valueOf(i)+ ","
+ String.valueOf(j) + ")";
}

. 625

626

24

, (Production
Logic in Test), .


[RowTest] [Row()]
MbUnit. www.ddsteps.org 
DDSteps JUnit. ,
(DataDriven Test), 
(Parameterized Test).
(Tabular Test)
:
http://clintshank.javadevelopersjournal.com/tabulartests.htm

. 626

627

(Testcase Class per Class)


(Test Method) (Testcase Class)?
(Test Method)
(Testcase Class).

testMethod_A_1
testMethod_A_2

feature_1

feature_2

testMethod_B_1
testMethod_B_2

(Test Method, . 378)


(Testcase Class, . 401). 
.
, 
.
(Testcase Class per Class)
.


(Testcase Class) ,
. (Testcase Class)
(Test Method), .


(Testcase Class per Class)
(Test
Method) .
,

. 627

628

24

(Testcase Class) . 
(Testcase
Class per Fixture, . 639), 
, (Testcase Class per Feature, . 633),
. :
!


(Testcase Class) :

Test.
( ) (), 
. 
,
(Test Method) .

. 
(Test Method) , 
(Implicit Setup, . 449) 
(Inline Setup, . 434) (Delegated Setup,
. 437). 
(Test Method)
(Obscure Test, . 230). (Inline Setup),
(Delegated Setup) (Creation Method,
. 441) .

: (Testcase Class per Class)


(Testcase Class per Class)
(Test Method) Flight,
(Unscheduled, Scheduled AwaitingApproval) 
(schedule, requestApproval, deSchedule approve).
, .
public class FlightStateTest extends TestCase {
public void testRequestApproval_FromScheduledState() throws Exception {
Flight flight = FlightTestHelper.getAnonymousFlightInScheduledState();
try {
flight.requestApproval();
fail("not allowed in scheduled state");
} catch (InvalidRequestException e) {
assertEquals("InvalidRequestException.getRequest()",
"requestApproval",
e.getRequest());
assertTrue("isScheduled()", flight.isScheduled());
}
}
public void testRequestApproval_FromUnsheduledState()
throws Exception {

. 628

Flight flight = FlightTestHelper.


getAnonymousFlightInUnscheduledState();
flight.requestApproval();
assertTrue("isAwaitingApproval()",
flight.isAwaitingApproval());
}
public void testRequestApproval_FromAwaitingApprovalState()
throws Exception {
Flight flight = FlightTestHelper.
getAnonymousFlightInAwaitingApprovalState();
try {
flight.requestApproval();
fail("not allowed in awaitingApproval state");
} catch (InvalidRequestException e) {
assertEquals("InvalidRequestException.getRequest()",
"requestApproval",
e.getRequest());
assertTrue("isAwaitingApproval()",
flight.isAwaitingApproval());
}
}
public void testSchedule_FromUnscheduledState()
throws Exception {
Flight flight = FlightTestHelper.
getAnonymousFlightInUnscheduledState();
flight.schedule();
assertTrue("isScheduled()", flight.isScheduled());
}
public void testSchedule_FromScheduledState()
throws Exception {
Flight flight = FlightTestHelper.
getAnonymousFlightInScheduledState();
try {
flight.schedule();
fail("not allowed in scheduled state");
} catch (InvalidRequestException e) {
assertEquals("InvalidRequestException.getRequest()",
"schedule",
e.getRequest());
assertTrue("isScheduled()", flight.isScheduled());
}
}
public void testSchedule_FromAwaitingApprovalState()
throws Exception {
Flight flight = FlightTestHelper.
getAnonymousFlightInAwaitingApprovalState();
try {
flight.schedule();
fail("not allowed in scheduled state");
} catch (InvalidRequestException e) {
assertEquals("InvalidRequestException.getRequest()",
"schedule",
e.getRequest());
assertTrue("isAwaitingApproval()",
flight.isAwaitingApproval());
}
}
public void testDeschedule_FromScheduledState()

. 629

629

630

24

throws Exception {
Flight flight = FlightTestHelper.
getAnonymousFlightInScheduledState();
flight.deschedule();
assertTrue("isUnscheduled()", flight.isUnscheduled());
}
public void testDeschedule_FromUnscheduledState()
throws Exception {
Flight flight = FlightTestHelper.
getAnonymousFlightInUnscheduledState();
try {
flight.deschedule();
fail("not allowed in unscheduled state");
} catch (InvalidRequestException e) {
assertEquals("InvalidRequestException.getRequest()",
"deschedule",
e.getRequest());
assertTrue("isUnscheduled()", flight.isUnscheduled());
}
}
public void testDeschedule_FromAwaitingApprovalState()
throws Exception {
Flight flight = FlightTestHelper.
getAnonymousFlightInAwaitingApprovalState();
try {
flight.deschedule();
fail("not allowed in awaitingApproval state");
} catch (InvalidRequestException e) {
assertEquals("InvalidRequestException.getRequest()",
"deschedule",
e.getRequest());
assertTrue("isAwaitingApproval()",
flight.isAwaitingApproval());
}
}
public void testApprove_FromScheduledState()
throws Exception {
Flight flight = FlightTestHelper.
getAnonymousFlightInScheduledState();
try {
flight.approve("Fred");
fail("not allowed in scheduled state");
} catch (InvalidRequestException e) {
assertEquals("InvalidRequestException.getRequest()",
"approve",
e.getRequest());
assertTrue("isScheduled()", flight.isScheduled());
}
}
public void testApprove_FromUnsheduledState()
throws Exception {
Flight flight = FlightTestHelper.
getAnonymousFlightInUnscheduledState();
try {
flight.approve("Fred");
fail("not allowed in unscheduled state");
} catch (InvalidRequestException e) {
assertEquals("InvalidRequestException.getRequest()",

. 630

631

"approve",
e.getRequest());
assertTrue("isUnscheduled()", flight.isUnscheduled());
}
}
public void testApprove_FromAwaitingApprovalState()
throws Exception {
Flight flight = FlightTestHelper.
getAnonymousFlightInAwaitingApprovalState();
flight.approve("Fred");
assertTrue("isScheduled()", flight.isScheduled());
}
public void testApprove_NullArgument() throws Exception {
Flight flight = FlightTestHelper.
getAnonymousFlightInAwaitingApprovalState();
try {
flight.approve(null);
fail("Failed to catch no approver");
} catch (InvalidArgumentException e) {
assertEquals("e.getArgumentName()",
"approverName", e.getArgumentName());
assertNull("e.getArgumentValue()",
e.getArgumentValue());
assertTrue("isAwaitingApproval()",
flight.isAwaitingApproval());
}
}
public void testApprove_InvalidApprover() throws Exception {
Flight flight = FlightTestHelper.
getAnonymousFlightInAwaitingApprovalState();
try {
flight.approve("John");
fail("Failed to validate approver");
} catch (InvalidArgumentException e) {
assertEquals("e.getArgumentName()",
"approverName",
e.getArgumentName());
assertEquals("e.getArgumentValue()",
"John",
e.getArgumentValue());
assertTrue("isAwaitingApproval()",
flight.isAwaitingApproval());
}
}
}

(Fresh Fixture, . 344) 


(Delegated Setup). 
.
(Test Method) .
.
, , (Test Method),
(. 24.1).

. 631

632

24

. 24.1. (Testcase Class per Class)


Package Explorer Eclipse. ,
(Test Method)

. 632

633

(Testcase Class per Feature)


(Test Method) (Testcase Class)?
(Test Method) (Testcase Class)
.
Feature1

testMethod_A
testMethod_B

Feature2

feature_1

feature_2

testMethod_A
testMethod_B

(Test Method, . 378) 


(Testcase Class, . 401).
. ,
.
(Testcase Class per Fea
ture) (Testcase Class) 
(Test Method).


(Test Method) (Testcase Class) 
.
(Testcase Class)
.


(Testcase Class per Feature) 
(Test Method), 
. , 

. 633

634

24

(Test Method) 
, . 
(Testcase
Class per Fixture, . 639). , 
 . 
(Testcase Class per Class, . 627).
, , ,
,
. (Testcase Class per
Class) .

: (Testcase Class per Method)


, ,
. (Test Method)
,
(Testcase Class per Method).

: (Testcase Class per Feature)


,
,
. , set get Java Bean
() . (data access
object) . 
,
.

:
(Testcase Class per User Story)
( 
) (Test Method) 
(Testcase Class).
, ,
. $
(Testcase Class per User Story)
( ) (Testcase Class per Feature)
(Testcase Class per Method) 
.


(Testcase Class) 
, .
(Test Method)
. 
, (Test Method) (Testcase Class).

. 634

635

$
(Testcase Class) .
, (Testcase Class)
, .
(Test Enumeration, . 425) (Testcase Class)
(AllTests Suite).


(Testcase Class
per Class) (Test Method)
Flight, (Unscheduled, Scheduled AwaitingApproval)
(schedule, requestApproval, deSchedule approve).
,
. ( . 
.)
public class FlightStateTest extends TestCase {
public void testRequestApproval_FromScheduledState()
throws Exception {
Flight flight = FlightTestHelper.
getAnonymousFlightInScheduledState();
try {
flight.requestApproval();
fail("not allowed in scheduled state");
} catch (InvalidRequestException e) {
assertEquals("InvalidRequestException.getRequest()",
"requestApproval",
e.getRequest());
assertTrue("isScheduled()", flight.isScheduled());
}
}
public void testRequestApproval_FromUnsheduledState()
throws Exception {
Flight flight = FlightTestHelper.
getAnonymousFlightInUnscheduledState();
flight.requestApproval();
assertTrue("isAwaitingApproval()",
flight.isAwaitingApproval());
}
public void testRequestApproval_FromAwaitingApprovalState()
throws Exception {
Flight flight = FlightTestHelper.
getAnonymousFlightInAwaitingApprovalState();
try {
flight.requestApproval();
fail("not allowed in awaitingApproval state");
} catch (InvalidRequestException e) {
assertEquals("InvalidRequestException.getRequest()",
"requestApproval",
e.getRequest());
assertTrue("isAwaitingApproval()",
flight.isAwaitingApproval());
}
}

. 635

636

24

public void testSchedule_FromUnscheduledState()


throws Exception {
Flight flight = FlightTestHelper.
getAnonymousFlightInUnscheduledState();
flight.schedule();
assertTrue("isScheduled()", flight.isScheduled());
}
public void testSchedule_FromScheduledState()
throws Exception {
//
//
}
}

(Delegated Setup, . 437)


(Fresh Fixture, . 344), 
.
(Test Method) .
(Test Method) (Testcase Class) 
, , 
(Testcase Class per Feature).


(Testcase Class) 
(Test Method)
(Testcase Class per Feature). 
(Test Method),
. (Testcase Class) ,
, .
(Extract Class) [Ref] (Testcase Class)
, .
(Move Method) ( )
(Test Method)
.
,
. 
. (Testcase Class) 
, . 
(Testcase Class per Feature) 
. (Test Method)
(Rename Method) [Ref], 
.
,
(Testcase Class).
( ) .
,
.

(Testcase Class) ( ).

. 636

637

(Test Method),
. $
(Test Method),
(Testcase Class).
(Testcase Class) 
, . (Test
Method), . 
(Testcase Class) .

: (Testcase Class per Feature)



(Testcase Class per Feature).
public class TestScheduleFlight extends TestCase {
public void testUnscheduled_shouldEndUpInScheduled()
throws Exception {
Flight flight = FlightTestHelper.
getAnonymousFlightInUnscheduledState();
flight.schedule();
assertTrue("isScheduled()", flight.isScheduled());
}
public void testScheduledState_shouldThrowInvalidRequestEx()
throws Exception {
Flight flight = FlightTestHelper.
getAnonymousFlightInScheduledState();
try {
flight.schedule();
fail("not allowed in scheduled state");
} catch (InvalidRequestException e) {
assertEquals("InvalidRequestException.getRequest()",
"schedule",
e.getRequest());
assertTrue("isScheduled()", flight.isScheduled());
}
}
public void testAwaitingApproval_shouldThrowInvalidRequestEx()
throws Exception {
Flight flight = FlightTestHelper.
getAnonymousFlightInAwaitingApprovalState();
try {
flight.schedule();
fail("not allowed in scheduled state");
} catch (InvalidRequestException e) {
assertEquals("InvalidRequestException.getRequest()",
"schedule",
e.getRequest());
assertTrue("isAwaitingApproval()",
flight.isAwaitingApproval());
}
}
}

. 637

638

24

.
( ),
, (. 24.2)
(Tests as Documentation, . 79).

. 24.2. (Testcase Class per Feature)


Package Explorer Eclipse. ,
,

. 638

639


(Testcase Class per Fixture)
(Test Method) (Testcase Class)?
(Test Method) (Testcase Class)
.
Fixture A
setUp

testMethod_1
testMethod_2

FixtureB

feature_1

feature_2

setUp
testMethod_1
testMethod_2

(Test Method, . 378)


(Testcase Class, . 401).
.
, !
.
(Testcase Class per Fix!
ture) (Implicit Setup, . 449),
(Test Automation
Framework, . 332).


(Test Method) (Testcase Class) !
.
(Implicit Setup),
setUp .
!
.

. 639

640

24


(Testcase Class per Fix
ture) (Test Method), 
, 
. ,
(Testcase
Class per Fixture) ,
, .
(Testcase Class per Feature, . 633)
(Testcase Class per Class, . 627).
, 
. 
(Testcase Class) 
, . 
(Testcase
Class per Fixture)
(Missing Unit Test) .
(Testcase Class per Fix
ture) (behaviordriven de
velopment). ,
. , 
,
(Tests as Documentation, . 79).


setUp,
(Test Automation Framework, . 332), 
.
, $
(Shared Fixture, . 350) (Erratic Test, . 267),
. ( 
. 411 xUnit,
.)
(Testcase Class) ,
. 
, 
.

(Testcase Class per Fixture)
(Testcase Class). 
, . 
, .
(Test Enumeration, . 425) 
(AllTests Suite),
,
(Testcase Class per Fixture).

. 640

641


(Testcase Class).
, ,
. , , 
. 
(Testcase Class per Feature)
(Extract Class) 
, 
.


(Test Method)
(Testcase Class per Class).
Flight, (Unscheduled, Scheduled AwaitingApproval)
(schedule, requestApproval, deSchedule approve).
,
. ( .
, (Testcase
Class per Class).)
public class FlightStateTest extends TestCase {
public void testRequestApproval_FromScheduledState()
throws Exception {
Flight flight = FlightTestHelper.
getAnonymousFlightInScheduledState();
try {
flight.requestApproval();
fail("not allowed in scheduled state");
} catch (InvalidRequestException e) {
assertEquals("InvalidRequestException.getRequest()",
"requestApproval",
e.getRequest());
assertTrue("isScheduled()", flight.isScheduled());
}
}
public void testRequestApproval_FromUnsheduledState()
throws Exception {
Flight flight = FlightTestHelper.
getAnonymousFlightInUnscheduledState();
flight.requestApproval();
assertTrue("isAwaitingApproval()",
flight.isAwaitingApproval());
}
public void testRequestApproval_FromAwaitingApprovalState()
throws Exception {
Flight flight = FlightTestHelper.
getAnonymousFlightInAwaitingApprovalState();
try {
flight.requestApproval();
fail("not allowed in awaitingApproval state");
} catch (InvalidRequestException e) {
assertEquals("InvalidRequestException.getRequest()",

. 641

642

24

"requestApproval",
e.getRequest());
assertTrue("isAwaitingApproval()",
flight.isAwaitingApproval());
}
}
public void testSchedule_FromUnscheduledState()
throws Exception {
Flight flight = FlightTestHelper.
getAnonymousFlightInUnscheduledState();
flight.schedule();
assertTrue("isScheduled()", flight.isScheduled());
}
public void testSchedule_FromScheduledState()
throws Exception {
//
//
}
}

(Delegated Setup, . 437)


(Fresh Fixture, . 344),
. 
(Test Method) 
. (Test Method) $
(Testcase Class) (
, ),

(Testcase Class per Fixture).


(Test Code Duplication, . 254) 
(Test
Method),
(Testcase Class per Fixture). 

(Test Method) .
(Testcase Class) , .
(Extract Class) $
(Testcase Class), 
.
(Test Method) (Move method) 
.
,
.
. (Testcase Class) 
, . 

(Testcase Class per Fixture) . $
(Test Method)

. 642

643

setUp,
(Implicit Setup). , $
(Test Method) .
(Rename
Method), (Test Method) 
. ,
.
( 
), .
.
( ) 
(Testcase Class) , 
(Test Method) ,
(Testcase Class).

:
(Testcase Class per Fixture)

(Testcase Class per Fixture).
( (Testcase Class). 
.)
public class TestScheduledFlight extends TestCase {
Flight scheduledFlight;
protected void setUp() throws Exception {
super.setUp();
scheduledFlight = createScheduledFlight();
}
Flight createScheduledFlight() throws InvalidRequestException{
Flight newFlight = new Flight();
newFlight.schedule();
return newFlight;
}
public void testDeschedule_shouldEndUpInUnscheduleState()
throws Exception {
scheduledFlight.deschedule();
assertTrue("isUnsched", scheduledFlight.isUnscheduled());
}
public void testRequestApproval_shouldThrowInvalidRequestEx(){
try {
scheduledFlight.requestApproval();
fail("not allowed in scheduled state");
} catch (InvalidRequestException e) {
assertEquals("InvalidRequestException.getRequest()",
"requestApproval", e.getRequest());
assertTrue("isScheduled()",
scheduledFlight.isScheduled());
}
}
public void testSchedule_shouldThrowInvalidRequestEx() {
try {

. 643

644

24

scheduledFlight.schedule();
fail("not allowed in scheduled state");
} catch (InvalidRequestException e) {
assertEquals("InvalidRequestException.getRequest()",
"schedule", e.getRequest());
assertTrue("isScheduled()",
scheduledFlight.isScheduled());
}
}
public void testApprove_shouldThrowInvalidRequestEx()
throws Exception {
try {
scheduledFlight.approve("Fred");
fail("not allowed in scheduled state");
} catch (InvalidRequestException e) {
assertEquals("InvalidRequestException.getRequest()",
"approve", e.getRequest());
assertTrue("isScheduled()",
scheduledFlight.isScheduled());
}
}
}

, (Test Method)! 
, $
(Tests as Documentation).
, ( ), 
( ) (
), (. 24.3).
, , Flight awaitingApproval, approve.
, ,
(, approve 
Flight ).

. 644

645

. 24.3. ,
(Testcase Class per Fixture) Package Explorer Eclipse.
, ,

. 645

646

24

(Testcase Superclass)
:
(Abstract
Testcase), (Abstract Test
Fixture),
(Testcase Baseclass)


(Test Utility Method)?


(Testcase Superclass).

testMethod_1

testMethod_n


.
.
(Test Utility Method,
. 610). ?
(Test Utility Method)
(Testcase Superclass).


(Test Utility
Method) , 
(Testcase Class, . 401).
(, Java protected).

( ) , .
,
(Testcase Class).

. 646

647


(Testcase Superclass) , 
(Test Utility Method) 
(Testcase Class) ,
, .
, 
, () 
(Test Utility Method)
, (Testcase Superclass).
(Testcase Superclass)
(Test Helper, . 651) .
(Test Utility Method),
(Test Utility Method) , .
, $
(Test Utility Method) $
(Testcase Superclass),
. (Test Utility Method) /
, , 
, (Test Helper) 
.

: (Test Helper Mixin)


(Test Helper Mixin) 
. $
(Test Helper), (Test
Helper Mixin), .
(Test Helper Object),
,
. (Testcase Superclass),
self.


xUnit, (Testcase Class) $
(Testcase Superclass),
(Test Automation Framework, . 332), 
(Testcase Superclass). , 
(Test Method, . 378),
.
(Testcase Superclass) 
. (Test
Utility Method) . 
 ,
.  
, , (Testcase Class).

. 647

648

24

, 
(, protected
Java).


(Test Utility Method),
(Testcase Class).
public class TestRefactoringExample extends TestCase {
public void testAddOneLineItem_quantity1() {
Invoice inv = createAnonInvoice();
LineItem expItem = new LineItem(inv, product, QUANTITY);
//
inv.addItemQuantity(product, QUANTITY);
//
assertInvoiceContainsOnlyThisLineItem(inv, expItem);
}
void assertInvoiceContainsOnlyThisLineItem(
Invoice inv,
LineItem expItem) {
List lineItems = inv.getLineItems();
assertEquals("number of items", lineItems.size(), 1);
LineItem actual = (LineItem)lineItems.get(0);
assertLineItemsEqual("",expItem, actual);
}
}

(Test Utility Method) 


.


(Test Utility Method)
, (Testcase Superclass)
(Pull Up Method).
(Testcase Class), 
. (Test Utility Method) 
, (Pull Up
Field) $
(Test Utility Method). (Test Method)
,
(, default protected
Java).

: (Testcase Superclass)
(Testcase Class),
. , .

. 648

649

public class TestRefactoringExample extends OurTestCase {


public void testAddItemQuantity_severalQuantity_v12(){
//
Customer cust = createACustomer(new BigDecimal("30"));
Product prod = createAProduct(new BigDecimal("19.99"));
Invoice invoice = createInvoice(cust);
//
invoice.addItemQuantity(prod, 5);
//
LineItem expected = new LineItem(invoice, prod, 5,
new BigDecimal("30"), new BigDecimal("69.96"));
assertContainsExactlyOneLineItem(invoice, expected);
}
}

, ,
.
public class OurTestCase extends TestCase {
void assertContainsExactlyOneLineItem(Invoice invoice,
LineItem expected) {
List lineItems = invoice.getLineItems();
assertEquals("number of items", lineItems.size(), 1);
LineItem actItem = (LineItem)lineItems.get(0);
assertLineItemsEqual("",expected, actItem);
}
}

: (Test Helper Mixin)


, Ruby
Test::Unit.
def test_extref
#
sourceXml = "<extref id='abc'/>"
expectedHtml = "<a href='abc.html'>abc</a>"
mockFile = MockFile.new
@handler = setupHandler(sourceXml, mockFile)
#
@handler.printBodyContents
#
assert_equals_html(expectedHtml, mockFile.output,
"extref: html output")
end
def testTestterm_normal
sourceXml = "<testterm id='abc'/>"
expectedHtml = "<a href='abc.html'>abc</a>"
mockFile = MockFile.new
@handler = setupHandler(sourceXml, mockFile)
@handler.printBodyContents
assert_equals_html(expectedHtml, mockFile.output,
"testterm: html output")
end
def testTestterm_plural

. 649

650

24

sourceXml ="<testterms id='abc'/>"


expectedHtml = "<a href='abc.html'>abcs</a>"
mockFile = MockFile.new
@handler = setupHandler(sourceXml, mockFile)
@handler.printBodyContents
assert_equals_html(expectedHtml, mockFile.output,
"testterms: html output")
end


(Test Code Duplication, . 254). 
(Extract Method)
(Test Utility Method).
(Test Helper Mixin). 
(Testcase Class),
, . , 
.
class CrossrefHandlerTest < Test::Unit::TestCase
include HandlerTest
def test_extref
sourceXml = "<extref id='abc' />"
expectedHtml = "<a href='abc.html'>abc</a>"
generateAndVerifyHtml(sourceXml,expectedHtml,"<extref>")
end

. 
, Ruby module,
class.
module HandlerTest
def generateAndVerifyHtml(sourceXml, expectedHtml,
message, &block)
mockFile = MockFile.new
sourceXml.delete!("\t")
@handler = setupHandler(sourceXml, mockFile )
block.call unless block == nil
@handler.printBodyContents
actual_html = mockFile.output
assert_equal_html(expectedHtml,
actual_html,
message + "html output")
actual_html
end

. 650

651

(Test Helper)
(Test Utility Method)?
,
(Test Utility Method),
.


testMethod_1

testMethod_n


.
. 
(Test Utility
Method, . 610). ?
$
(Test Helper).


,
(Test Utility Method), (Testcase Class, . 401). 
, , 
.


(Test Helper) 
(Testcase Class),
( )
(Testcase Superclass, . 646), , 
. : , 
(, Visual
Basic 5 6), ,
(Test Utility Method) 
, (Testcase Superclass).

. 651

652

24

(Test Helper)
(Testcase Superclass) . $
(Test Utility Method), (Test
Utility Method) , . 
,
(Test Utility Method) (Testcase Super
class), . $
(Test Utility Method) / ,
, , 
(Test Helper)
. 
(Test
Helper) () .

: (Test Fixture Registry)


,
. 
. (
(Singleton), ,
. .)
(Test Fixture Registry)
. $
(Test Helper) 
(Test Fixture Registry)
(Test Runner, . 405), (Test
Run War). (Test Fixture
Registry) (Database Sandbox, . 658).
(Test Fixture Registry)
(Setup Decorator, . 471)
(Lazy Setup, . 460). (Suite
Fixture Setup, . 465) ,
(Testcase Class) . 
.

: (Object Mother)
(Object Mother) 
, , 
. (Object Mother) 
(Test Helper), 
(Creation Method, . 441) (Attach
ment Method), 
. (Object Mother) 
(Creation Method), 
, 
(
, Named State Reaching Method). ,

. 652

653

(Object Mother) , 
(Automated Teardown).
(Object Mother)
,
(, , Automated Teardown).


(Test Helper) 
. .

: (Test Helper Class)


(Test Utility Method) 
,
,

, , ClassName.methodName.
,
, , $
(Shared Fixture, . 350) (, , 
). (Test
Fixture Registry).

: (Test Helper Object)


 ,
.
(Test Helper) 
. 
. ,
(Test Helper) 
(Shared Fix
ture). , (Test Helper)
(Mock Object, . 558), 
$
(Mock Object).


(Test Utility Method),
(Testcase Class).
public class TestUtilityExample extends TestCase {
public void testAddOneLineItem_quantity1() {
Invoice inv = createAnonInvoice();
LineItem expItem = new LineItem(inv, product, QUANTITY);
//
inv.addItemQuantity(product, QUANTITY);

. 653

654

24

//
assertInvoiceContainsOnlyThisLineItem(inv, expItem);
}
void assertInvoiceContainsOnlyThisLineItem(
Invoice inv,
LineItem expItem) {
List lineItems = inv.getLineItems();
assertEquals("number of items", lineItems.size(), 1);
LineItem actual = (LineItem)lineItems.get(0);
assertLineItemsEqual("",expItem, actual);
}
}

(Test Utility Method) 


.


(Test Utility Method) 
,
(Test Helper).
(Move Method). 
$
(Test Utility Method).

(Move Method).

: (Test Helper)
(Test
Utility Method) (Test Helper).
, .
public class TestUtilityExample extends TestCase {
public void testAddOneLineItem_quantity1_staticHelper() {
Invoice inv = createAnonInvoice();
LineItem expItem = new LineItem(inv, product, QUANTITY);
//
inv.addItemQuantity(product, QUANTITY);
//
TestHelper.assertContainsExactlyOneLineItem(inv, expItem);
}
}

: (Test Helper)
(Test Utility Method)
(Test Helper) . 
, (,
, Test Helper).

. 654

public class TestUtilityExample extends TestCase {


public void testAddOneLineItem_quantity1_instanceHelper() {
Invoice inv = createAnonInvoice();
LineItem expItem = new LineItem(inv, product, QUANTITY);
//
inv.addItemQuantity(product, QUANTITY);
//
TestHelper helper = new TestHelper();
helper.assertInvContainsExactlyOneLineItem(inv, expItem);
}
}

. 655

655

. 656

25

25


:
(Database Sandbox) .................................... 658
(Stored Procedure Test)................................... 662
(Table Truncation Teardown) ......................... 668
(Transaction Rollback Teardown)............... 675

. 657

658

25

(Database Sandbox)
,
?
.
1


.
. , $
(Erratic Test, . 267),
. , 
. ,

.
(Database Sandbox)
.


, 
. , ,
, . 

,
.

. 658

659


(Database Sandbox)
,
. , 
(Shared Fixture, . 350).
(Database Sandbox), (Test
Run War) .

. (Database Sandbox) $
(Unrepeatable Test) (Interacting
Tests), ( );
.


,
. 
,
.
(Database Sandbox) 
. 
. 
.
, 
.

: (Dedicated Database Sandbox)



. 
.
MySQL Personal Oracle.
,
,
.
(Dedicated Database Sandbox) 
, 
,
.

: (DB/Schema per Test/Runner)



,
.

$

. 659

660

25

(Immutable Shared Fixture), ,



. ,
( , ,
, Dedicated Data
base Sandbox). , , 
. 
.

: (Database Partitioning Scheme)



(Database Sandbox). 
, ,
.

, . 
, (Database
Partitioning Scheme) . ,
(Interacting Tests)
(Test Runner), .. 
, CustomerNumber,
. .
(Database Sand
box), (Interacting Tests)
(Shared Fixture). ,
(Unrepeatable Test), 
(Distinct Generated Value).


Product
(Literal Value), , 
. Product .
public void testProductPrice_HCV() {
//

Product product =
new Product( 88,
// ID
"Widget",
//
new BigDecimal("19.99")); //
//
//
...
}

,
(Test Run War) 
Product .
Product
(Test Runner).

. 660

661


(Dedicated Database Sandbox)
. 
, (Test
Runner, . 405) . 
,
.
.
(Database
Partitioning Scheme), (Literal Value) 
getUnique, 
(Test Runner).

: (Database Partitioning Scheme)


, (Database
Partitioning Scheme) . 
getUniqueString , MAC
.
public void testProductPrice_DPS() {
//
Product product =
new Product(getUniqueInt(),
// ID
getUniqueString(getMacAddress()), //
new BigDecimal("19.99"));
//
//
//
...
}
static int counter = 0;
int getUniqueInt() {
counter++;
return counter;
}
BigDecimal getUniqueBigDecimal() {
return new BigDecimal(getUniqueInt());
}
String getUniqueString(String baseName) {
return baseName.concat(String.valueOf( getUniqueInt()));
}


(Test Run War).

. 661

662

25

(Stored Procedure Test)


?

(Fully Automated Tests).
Application

En
vironment
Testcase

Class

Stored

Procedure

Pro xy

testMethod_1
testMethod_1
testMethod_2
testMethod_2

Testcase
Class

testMethod_1
testMethod_1
testMethod_2
testMethod_2

Database

Stored

Procedure

, 
, 
.
(Stored Procedure Test)
, .



. 
.


(Stored Procedure Test) 
, .
. 
,
. (Stored Procedure
Test) ,
(
(Indirect Testing)  , Obscure Test, . 230). ,

. 662

663

(Stored Procedure Test) 


, , ,
. , , 
, 
.



(Stored Procedure Test).
1. ,
,
.
2. ,
,
(Remote Proxy).
. , 

, 
.
,
( ) (
, ). 
/
( , Back Door Manipulation, . 359) 
( ).

:
(In/Database Stored Procedure Test)
xUnit 
,
.
,
.. , ,
, 
. , . ,
[SCM].
(Stored Procedure
Test) ,
, , 
. , 
, .

.
, (.. ).

. 663

664

25

(InDatabase Stored Procedure


Test) ( ) 
, . ,

(Overspecified Software). ,

. (,
).
.
,
. , Oracle
PL/SQL Java, JUnit 
, PL/SQL.
Microsoft SQL Server C#, 
NUnit, C#, ,
TransactSQL.

: (Remoted Stored Procedure Test)


(Remoted Stored Procedure Test)
, 
. (Remote
Proxy), . 
(Service Facade) Com
mand (, JdbcOdbcCallableStatement Java).
(Remoted Stored Procedure Test) 
,
.
, , 
( 
, ). 
xUnit ,
(, DbUnit  Java NDBUnit  
.NET).
, 
.
(Remoted Stored Procedure Test) 
.

JUNIT

,
, .
Java PL/SQL
.
JUnit.

. 664

665


,
. utPLSQL .

xUnit: JUnit. JDBC 
, 
PreparedStatement.

. JUnit 
. 
, .
.
, .
.
, . 
:
.
PL/SQL JUnit!

,
/ . , $
(Remoted Stored Procedure Test)
,
(,  
). $
(Remoted Stored Procedure Test) 
. ,
JUnit . 664.

(Remoted Stored Procedure Test) ,
. $
(Subset Suite), .

(Slow Tests, . 289).
(Remoted Stored Procedure Test)
(
).
(Remoted Stored Procedure Test),
(Test Automation
Framework, . 332), .
, ,
.

. 665

666

25


,
PL/SQL.
CREATE OR REPLACE PROCEDURE calc_secs_between (
date1 IN DATE,
date2 IN DATE,
secs OUT NUMBER
)
IS
BEGIN
secs := (date2 - date1) * 24 * 60 * 60;
END;
/

, 
utPLSQL.  
( , ?), 
.


,
. .
: $
(InDatabase Stored Procedure Test) (Remoted
Stored Procedure Test).

:
(In/Database Stored Procedure Test)
utPLSQL, 
xUnit PL/SQL.
, .
CREATE OR REPLACE PACKAGE BODY ut_calc_secs_between
IS
PROCEDURE ut_setup
IS
BEGIN
NULL;
END;
PROCEDURE ut_teardown
IS
BEGIN
NULL;
END;
- ...
PROCEDURE ut_CALC_SECS_BETWEEN
IS
secs PLS_INTEGER;
BEGIN

. 666

667

CALC_SECS_BETWEEN (
DATE1 => SYSDATE
'
DATE2 => SYSDATE
'
SECS => secs
);
utAssert.eq (
'Same dates',
secs,
0
);
END ut_CALC_SECS_BETWEEN;
END ut_calc_secs_between;
/

xUnit. ,
 
. (
utPLSQL. .)

: (Remoted Stored Procedure Test)



(Remote Proxy) 
.
.
JUnit ,
,
PL/SQL.
public class StoredProcedureTest extends TestCase {
public void testCalcSecsBetween_SameTime() {
//
TimeCalculatorProxy SUT = new TimeCalculatorProxy();
Calendar cal = new GregorianCalendar();
long now = cal.getTimeInMillis();
//
long timeDifference = SUT.calc_secs_between(now,now);
//
assertEquals(0, timeDifference);
}
}


JdbcOdbcCallableStatement (Service Facade).
, , Java. ,
$
(Expected Exception Test).

. 667

668

25

(Table Truncation Teardown)


,
?
,
.

Data


. , 
,

.
, , .
,
. , 
, 
. (Complex Teardown) 
(Conditional Test Logic) , , 
(Untestable Test Code).
, , 
, TRUNCATE 
.


, 
TRUNCATE. 
(, ).

. 668

669


(Table Truncation Teardown) 
(Persistent Fresh Fixture)
, . 
. (Transaction
Rollback Teardown, . 675). (Table Truncation
Teardown) $
(Shared Fixture, . 350), 
. , (Transaction Rollback Teardown)
(Shared Fixture)
. , 
.
(Table Truncation Teardown) 
.
, 
(Database Sandbox, . 658) (Test Runner,
. 405). (Table Truncation Teardown) 
(Database Partitioning Scheme) 
. 
(DBSchema per TestRunner), 
(Immutable
Shared Fixture) .
(Fresh
Fixture) (Database Sandbox) $
(Immutable Shared Fixture).
, 
(Automated Teardown, . 521),
, . (Automated
Teardown) ,
. , , 
$ (Delta Assertion, . 505).


?,
(Table Truncation Teardown) .

, .. ?


(objectrelation mapping  ORM)?

(, Oracle) TRUNCATE
.
. DELETE * FROM tablename. TRUNCATE DELETE
(Inline Teardown, . 527) (Test Method) 

. 669

670

25

(Implicit Teardown, . 533) tearDown. 


(Lazy Teardown), 
, 
.

(Table Truncation Teardown),
ON DELETE CASCADE Oracle. Oracle
ON DELETE CASCADE 
, .
, 
. ,
. , : 
, . 
: TRUNCATE.
, TRUNCATE
,
(Test Utility Method, . 610).

TRUNCATE, 
/ . ,
.
 , Toplink,
(N)Hibernate EJB 3.0, , ,
, . 
, NHibernate ClearAllCaches
TransactionManager.

: (Lazy Teardown)
$
(Shared Fixture).
. ,
; .
(Table Truncation Teardown) ,
.
.


$
(Guaranteed Inline Teardown).
[Test]
public void TestGetFlightsByOrigin_NoInboundFlights()
{
//
long OutboundAirport = CreateTestAirport("1OF");
long InboundAirport = CreateTestAirport("1IF");

. 670

671

FlightDto ExpFlightDto = null;


try
{
ExpFlightDto =
CreateTestFlight(OutboundAirport, InboundAirport);
//
IList FlightsAtDestination1 =
Facade.GetFlightsByOriginAirport(InboundAirport);
//
Assert.AreEqual(0, FlightsAtDestination1.Count);
}
finally
{
Facade.RemoveFlight(ExpFlightDto.FlightNumber);
Facade.RemoveAirport(OutboundAirport);
Facade.RemoveAirport(InboundAirport);
}
}

! ( 
, (Inline Teardown).)
.


(Inline Teardown) 
, $
(Table Truncation Teardown) 
. (, 
.
, (Table Truncation Teardown) .)

finally clearDatabase.
.

:
(Table Truncation Teardown)
.
public void TestGetFlightsByOrigin_NoInboundFlight_TTTD()
{
//
long OutboundAirport = CreateTestAirport("1OF");
long InboundAirport = 0;
FlightDto ExpectedFlightDto = null;
try
{
InboundAirport = CreateTestAirport("1IF");
ExpectedFlightDto =
CreateTestFlight(OutboundAirport,InboundAirport);
//
IList FlightsAtDestination1 =

. 671

672

25

Facade.GetFlightsByOriginAirport(InboundAirport);
//
Assert.AreEqual(0,FlightsAtDestination1.Count);
}
finally
{
CleanDatabase();
}
}


(Delegated Teardown).
(Implicit Teardown) tearDown. try/catch 
cleanDatabase, ,
cleanDatabase.

: (Lazy Teardown)
,
(Lazy Teardown).
[Test]
public void TestGetFlightsByOrigin_NoInboundFlight_LTD()
{
// ""
CleanDatabase();
//
long OutboundAirport = CreateTestAirport("1OF");
long InboundAirport = 0;
FlightDto ExpectedFlightDto = null;
InboundAirport = CreateTestAirport("1IF");
ExpectedFlightDto =
CreateTestFlight(OutboundAirport, InboundAirport);
//
IList FlightsAtDestination1 =
Facade.GetFlightsByOriginAirport(InboundAirport);
//
Assert.AreEqual(0,FlightsAtDestination1.Count);
}

cleanDatabase (Test Method), 


.
.
, , 
.
try/finally, .

: (Table Truncation Teardown)


SQL
cleanDatabase 
SQL.

. 672

673

public static void CleanDatabase() {


string[] tablesToTruncate =
new string[] {"Airport","City","Airline_Cd","Flight"};
IDbConnection conn = getCurrentConnection();
IDbTransaction txn = conn.BeginTransaction();
try {
foreach (string eachTableToTruncate in tablesToTruncate)
{
TruncateTable(txn, eachTableToTruncate);
}
txn.Commit();
conn.Close();
} catch (Exception e) {
txn.Rollback();
} finally {
conn.Close();
}
}
private static void TruncateTable(IDbTransaction txn,
string tableName)
{
const string C_DELETE_SQL = "DELETE FROM {0}";
IDbCommand cmd = txn.Connection.CreateCommand();
cmd.Transaction = txn;
cmd.CommandText = string.Format(C_DELETE_SQL, tableName);
cmd.ExecuteNonQuery();
}

SQL Server 
TruncateTable, Delete *
from.... , TRUNCATE
.

: (Table Truncation Teardown)


/
cleanDatabase NHibernate
 .
public static void CleanDatabase() {
ISession session =
TransactionManager.Instance.CurrentSession;
TransactionManager.Instance.BeginTransaction();
try {
// ,
//
session.Delete("from Airport");
session.Delete("from City");
session.Flush();
TransactionManager.Instance.Commit();
} catch (Exception e) {
Console.Write(e);
throw e;

. 673

674

25

} finally {
TransactionManager.Instance.CloseSession();
}
}

 ,
.
.
City Airport (), (
) , Flight, 
. .

. 674

675

(Transaction Rollback Teardown)


,
?

.

Data


. ,

, 
. 
, ,
.
, 
. , 
, 
. (Complex Teardown)
(Conditional Test Logic) , ,
(Untestable Test Code).
, 
, 
.


, ,
.
. 
, .

. 675

676

25


(Transaction Rollback Teardown)
(Fresh Fixture, . 344), 
. 
. (Transaction Rollback Teardown)
.
, , 

(Humble Transaction Controller), .. 
. 

(Transaction Rollback Teardown) . 
$
(Transaction Rollback Teardown)
(Humble Transaction Controller).
(Transaction Rollback Tear
down) ,
. 
.
. , ,
(Table Truncation Teardown, . 668).
,
: 50 (, 50!) ,
. $
(InMemory Database) , 
(Slow Tests, . 289).
,
(Fake Database) .

. 
.


,
(Transaction Rollback
Teardown). .
TheServerSide
(Transaction Rollback Tear$
down), . , $
. $
, . ,
. AbstractTransactionalDataourcepringontextTests Spring, $
.

. 676

677

$
. , .
1. .
,
. ( $
setUp() ) .
2. , $ . $
,
, .
, .
3.
. ,
. $
,
. ,
DDL, . $$$$
.
4. , $
.
PL/SQL. . $
, $
.

. , ,
Spring
Spring. , ,
.
.
: ,
. ,
.


xUnit $
(Transaction Rollback Teardown). 
. 
. 

. , 

. ,
(Subcutaneous Test) (Service Facade), 
.

(Humble Transaction Controller).
, 

. 677

678

25

. 
(Poor Mans Humble Object).
, , ,
.
(TestSpecific Sub
class, . 591). ,
(Extract Testable Component) 
, .

. , 
.  
, Toplink, (N)Hibernate EJB 3.0, 
,
, (
). , EJB 3.0
EntityManager.flush, 
.



(Guaranteed Inline Teardown) .
public void testGetFlightsByOriginAirport_NoInboundFlights()
throws Exception {
//
BigDecimal outboundAirport = createTestAirport("1OF");
BigDecimal inboundAirport = createTestAirport("1IF");
FlightDto expFlightDto = null;
try {
expFlightDto = createTestFlight(outboundAirport, inboundAirport);
//
List flightsAtDestination1 =
facade.getFlightsByOriginAirport(inboundAirport);
//
assertEquals(0, flightsAtDestination1.size());
} finally {
facade.removeFlight(expFlightDto.getFlightNumber());
facade.removeAirport(outboundAirport);
facade.removeAirport(inboundAirport);
}
}

! ( 
, (Inline Teardown).)
.


(Inline Teardown) 
, (Transaction Rollback Tear

. 678

679

down) .
finally
abortTransaction. , beginTransaction
(Creation
Method, . 441), .
(Service Facade).

:
.
public void testGetFlightsByOrigin_NoInboundFlight_TRBTD()
throws Exception {
//
TransactionManager.beginTransaction();
BigDecimal outboundAirport = createTestAirport("1OF");
BigDecimal inboundAirport = null;
FlightDto expectedFlightDto = null;
try {
inboundAirport = createTestAirport("1IF");
expectedFlightDto =
createTestFlight(outboundAirport, inboundAirport);
//
List flightsAtDestination1 =
facade.getFlightsByOriginAirport(inboundAirport);
//
assertEquals(0,flightsAtDestination1.size());
} finally {
TransactionManager.abortTransaction();
}
}

finally 
abortTransaction. finally ,
(Inline Teardown). 
TransactionManager
tearDown.
(Transaction Rollback Teardown) 
,
(Creation Method), .
, getFlightsFromAirport 
, , 
.
private BigDecimal createTestAirport(String airportName)
throws FlightBookingException {
BigDecimal newAirportId =
facade._createAirport(airportName,
"Airport" + airportName,
"City" + airportName);
return newAirportId;
}

. 679

680

25

( $
, Poor Mans Humble Object).
public BigDecimal createAirport(String airportCode,
String name,
String nearbyCity)
throws FlightBookingException{
TransactionManager.beginTransaction();
BigDecimal airportId = _createAirport(airportCode, name, nearbyCity);
TransactionManager.commitTransaction();
return airportId;
}
//
BigDecimal _createAirport(String airportCode,
String name,
String nearbyCity)
throws DataException, InvalidArgumentException {
Airport airport =
dataAccess.createAirport(airportCode,name,nearbyCity);
logMessage("CreateFlight", airport.getCode());
return airport.getId();
}

(, getFlightsFromAirport) 
, ,
.

:
,
. 
 Domain Model. $
(Transaction Rollback Teardown)
(
, transaction script).
.NET.
[TestFixture]
public class TransactionRollbackTearDownTest
{
private SqlConnection _Connection;
private SqlTransaction _Transaction;
public TransactionRollbackTearDownTest()
{
}
[SetUp]
public void Setup()
{
string dbConnectionString = ConfigurationSettings.
AppSettings.Get("DbConnectionString");
_Connection = new SqlConnection(dbConnectionString);
_Connection.Open();
_Transaction = _Connection.BeginTransaction();
}

. 680

681

[TearDown]
public void TearDown()
{
_Transaction.Rollback();
_Connection.Close();
// NUnit " "
_Transaction = null;
_Connection = null;
}
[Test]
public void AnNUnitTest()
{
const string C_INSERT_SQL =
"INSERT INTO Invoice(Amount, Tax, CustomerId)" +
" VALUES({0}, {1}, {2})";
SqlCommand cmd = _Connection.CreateCommand();
cmd.Transaction = _Transaction;
cmd.CommandText = string.Format(
C_INSERT_SQL,
new object[] {"100.00", "7.00", 2001});
//
cmd.ExecuteNonQuery();
//
// ..
}
}
}


(Implicit Setup, . 449).
(Test Method, . 378) (Implicit Tear
down, . 533) . 
null, NUnit, 
xUnit, (Testcase Object, . 410)
(Test Method).
. 411.

. 681

. 682

26

26



:
(Dependency Injection) ........................................... 684
(Dependency Lookup)................................................ 692
(Humble Object) .................................................... 700
(Test Hook) .................................................................. 713

. 683

684

26

(Dependency Injection)

?
.

, ,
.
. ,
.
(Dependency Injection)
.



,
. 
, ..

. 
, ().



(Test Double, . 538) .
(static binding)  .. 

. (dinamic binding) 

. (Dependency Injection)

. 684

685


. 
, 
(Test Double).
, 
( ,
( )),
(Test Double). 
(Dependency Lookup, . 692), 
(Test Double).
, 
(Test Double),
(TestSpecific Subclass, . 591).


(Dependency Injection)
. , (Test
Double) .
,
(Test Double) . ,
(Test Double).



(Test Double) , 
. , (Test Double) 
( )
( ).
(Test Double) 
(Extract Interface) 
(Test Double).


$
(Test Double), 
. 
.

. 685

(Parameter Injection).
.

(Constructor Injection). 
.

(Setter Injection). 
 
.

686

26

(Dependency Injection)
. /
(inversion of control)
. 
(Dependency Injection) 
.

: (Parameter Injection)
(Parameter Injection)
(Dependency Injection),
.
. ( ) 
. 
, 
. 
, .
(Dependency Injection)
.
(Parameter Injection) $
(Mock Object, . 558) [ET].
, 
.
(Parameter Injection) 
, .

, .

: (Constructor Injection)
(Constructor Injection), (Setter
Injection)
( ) .
(Constructor Injection) . 
, 
, 
.
(Test Double), 
.
(Dependency Injection)

. (Constructor Injection) 
, , 
. , 
, (HardtoTest Code, . 251),

(Humble Executable). 
, .

. 686

687

: (Setter Injection)
(Constructor Injection), 
(), 
. 
. 
(Test Double),
.
, 

.
(Setter Injection) , 
, .
(Constructor Injection). 
,
,
(lazy initialization). 
.


,
(TestSpecific Subclass).
,
,
(Dependency Injection). $
(Humble Object) 
( )
(Test Double).
/ /
(aspectoriented programming)
(Dependency Injection) . ,
(Test Double)
.


.
public void testDisplayCurrentTime_AtMidnight() {
//
TimeDisplay sut = new TimeDisplay();
//
String result = sut.getCurrentTimeAsHtmlFragment();
//
String expectedTimeString =
"<span class=\"tinyBoldText\">Midnight</span>";
assertEquals(expectedTimeString, result);
}

. 687

688

26

,
, . 
DefaultTimeProvider. ,
, .
public String getCurrentTimeAsHtmlFragment() {
Calendar currentTime;
try {
currentTime = new DefaultTimeProvider().getTime();
} catch (Exception e) {
return e.getMessage();
}
// ..
}


,
(Test Double) .
. 
.


$
(Replace Dependency with Test Double, . 740). 
(Setter Injection) ,

. , 
(Introduce parameter). 
(Extract Method) 
, ,
(Adapter), .

: (Parameter Injection)
, (Parameter
Injection).
public void testDisplayCurrentTime_AtMidnight_PI() {
//
//
TimeProvider tpStub = new MidnightTimeProvider();
//
TimeDisplay sut = new TimeDisplay();
//
String result = sut.getCurrentTimeAsHtmlFragment(tpStub);
//
String expectedTimeString =
"<span class=\"tinyBoldText\">Midnight</span>";
assertEquals("Midnight", expectedTimeString, result);
}

. 688

689

. 
,
.
public String getCurrentTimeAsHtmlFragment(
TimeProvider timeProviderArg) {
Calendar currentTime;
try {
currentTime = timeProviderArg.getTime();
} catch (Exception e) {
return e.getMessage();
}
// ..
}

: (Constructor Injection)
, $
(Constructor Injection).
public void testDisplayCurrentTime_AtMidnight_CI()
throws Exception {
//
//
TimeProvider tpStub = new MidnightTimeProvider();
//
TimeDisplay sut = new TimeDisplay(tpStub);
//
String expectedTimeString =
"<span class=\"tinyBoldText\">12:01 AM</span>";
//
assertEquals("12:01 AM",
expectedTimeString,
sut.getCurrentTimeAsHtmlFragment());
}


(Constructor Injection),
(Introduce Field) ,
.
(Introduce Parameter) 

.
, ,

.
public class TimeDisplay {
private TimeProvider timeProvider;
public TimeDisplay() {
//
timeProvider = new DefaultTimeProvider();
}
public TimeDisplay(TimeProvider timeProvider) { //

. 689

690

26

this.timeProvider = timeProvider;
}


(Extract Method) $
(Move Method) (Object Factory). 
(Dependency Lookup).

: (Setter Injection)
, $
(Setter Injection).
public void testDisplayCurrentTime_AtMidnight_SI()
throws Exception {
//
//

TimeProvider tpStub = new MidnightTimeProvider();
//

TimeDisplay sut = new TimeDisplay();
//

sut.setTimeProvider(tpStub);
//
String result = sut.getCurrentTimeAsHtmlFragment();
//
String expectedTimeString =
"<span class=\"tinyBoldText\">Midnight</span>";
assertEquals("Midnight", expectedTimeString, result);
}

setTimeProvider $
(HardCoded Test Double, . 581). $
(Configurable Test Double, . 571), 
setTimeProvider.
(Setter
Injection)
(Setter Injection) , 
, .
, 
. 
.
public class TimeDisplay {
private TimeProvider timeProvider;
public TimeDisplay() {
timeProvider = new DefaultTimeProvider();
}
public void setTimeProvider(TimeProvider provider) {
this.timeProvider = provider;
}
public String getCurrentTimeAsHtmlFragment()
throws TimeProviderEx {
Calendar currentTime;

. 690

691

try {
currentTime = getTimeProvider().getTime();
} catch (Exception e) {
return e.getMessage();
}
// ..


. timeProvider 
.

. 691

692

26

(Dependency Lookup)
:
(Service Locator),
(Object
Factory),
(Component Broker), (Component Registry)

, ,
.
. ,
.
(Dependency Lookup) 
.


,
, ,
.
, . 

, 
.


(Dependency Lookup) 
,

. 692

693

(Test Double, . 538) . 


(Fake Database)
(InMemory Database) 
.
(Fake Database) (Service Facade) , 
. (Dependency
Lookup) (Setup Decorator, . 471) 
(Fake Database), 

. .
(Service Locator) 
. 

. ,
Web .
(Dependency Lookup) 
,
, .
,
(Dependency Injection, . 684), . ,
(Setup Decorator), 
(Fake Object). .
, 
(Fake Object) , (Service Locator) 
1.
(Dependency Lookup) 

(Dependency Injection). ,

. 

(aspectoriented programming)
,
.
(Test Hook, . 713) 

.

(Service Locator), (Object Factory), (Component
Broker) (Component Registry). 
( ),
. 
(Service Locator) 

1 , 
.

. 693

694

26

 (Object Factory).


(Component Broker).


(Test Double) 
. 
, 

. 
. ,
. 
, 
. 
.
(Test Double) ,
.
(Dependency Lookup) .

Singleton [GOF], Registry [PEAA]


Threadspecific storage [POSA2].


(Test Double).

(Dependency Lookup) , 
. 
(Service Locator)
(Object Factory). 
.
(Dependency Lookup) .


(Dependency Lookup) 
,
.
: Singleton, Registry ThreadSpecific Storage.2
(Component Broker)
( ), .. 
Singleton, Registry ThreadSpecific Storage. 
2

Single
ton. Registry . ThreadSpecific Storage
, 
; 
, .

. 694

695

,
(Substitutable Singleton), ,
Singleton.


$
(Test Double), (Com
onent Broker) (Test Double) . $
(Component Broker) 

(TestSpecific Subclass). , 
,
, 
(Component Broker) (Shared
Fixture, . 350).

. . ,
( 
).
(Slow Tests, . 289). , 
(Configurable Test Double), 
. ,
(Interacting Tests),
.
(Component Broker) 
, 
(Humble Object, . 700),
(Component Bro
ker). ,
.


.
public void testDisplayCurrentTime_AtMidnight() {
//
TimeDisplay sut = new TimeDisplay();
//
String result = sut.getCurrentTimeAsHtmlFragment();
//
String expectedTimeString =
"<span class=\"tinyBoldText\">Midnight</span>";
assertEquals(expectedTimeString, result);
}

,
.

. 695

696

26

(DefaultTimeProvider), 
.
public String getCurrentTimeAsHtmlFragment() {
Calendar currentTime;
try {
currentTime = new DefaultTimeProvider().getTime();
} catch (Exception e) {
return e.getMessage();
}
// ..
}


,
(Test Double). .
.



(Service Locator).
public String getCurrentTimeAsHtmlFragment() {
Calendar currentTime;
try {
TimeProvider timeProvider =
(TimeProvider) ServiceLocator.getInstance().
findService("Time");
currentTime = timeProvider.getTime();
} catch (Exception e) {
return e.getMessage();
}
// ..


( getInstance ).
(Service Locator). 
,
(Service Locator), 
. $
(TestSpecific Subclass), .

: (Configurable Registry)

(Service Locator), $
(Test Double).
public void testDisplayCurrentTime_AtMidnight_CSL() {
//
//

MidnightTimeProvider tpStub = new MidnightTimeProvider();

. 696

697

//

TimeDisplay sut = new TimeDisplay();
//

ServiceLocator.getInstance().registerServiceForName(tpStub, "Time");
//
String result = sut.getCurrentTimeAsHtmlFragment();
//
String expectedTimeString =
"<span class=\"tinyBoldText\">Midnight</span>";
assertEquals("Midnight", expectedTimeString, result);
}

.
(Configuration Interface) (Configurable Registry).
public class ServiceLocator {
protected ServiceLocator() {};
protected static ServiceLocator soleInstance = null;
public static ServiceLocator getInstance() {
if (soleInstance==null)
soleInstance = new ServiceLocator();
return soleInstance;
}
private HashMap providers = new HashMap();
public ServiceProvider findService(String serviceName) {
return (ServiceProvider) providers.get(serviceName);
}
//
public void registerServiceForName(ServiceProvider provider,
String serviceName) {
providers.put(serviceName, provider);
}
}


, (Test Double).
(Configurable Registry) $
(Test Double),
.

: (Substituted Singleton)

(Dependency Lookup). soleInstance
(Substituted Singleton).
, overrideSoleinstance (Test Stub, . 544) TimeProvider.
public void testDisplayCurrentTime_AtMidnight_TSS() {
//
//

MidnightTimeProvider tpStub = new MidnightTimeProvider();
//

. 697

698

26

TimeDisplay sut = new TimeDisplay();


//

//
,
//

ServiceLocatorTestSingleton.overrideSoleInstance(tpStub);
//
String result = sut.getCurrentTimeAsHtmlFragment();
//
String expectedTimeString =
"<span class=\"tinyBoldText\">Midnight</span>";
assertEquals("Midnight", expectedTimeString, result);
}

, ,
getInstance, (TestSpecific Sub
class). .
public class ServiceLocator {
protected ServiceLocator() {};
protected static ServiceLocator soleInstance = null;
public static ServiceLocator getInstance() {
if (soleInstance==null)
soleInstance = new ServiceLocator();
return soleInstance;
}
private HashMap providers = new HashMap();
public ServiceProvider findService(String serviceName) {
return (ServiceProvider) providers.get(serviceName);
}
}

soleInstance protected,
private, . 
, (Substituted Sin
gleton).
public class ServiceLocatorTestSingleton extends ServiceLocator {
private ServiceProvider tpStub;
private ServiceLocatorTestSingleton(TimeProvider newTpStub) {
this.tpStub = newTpStub;
};
//
static ServiceLocatorTestSingleton
overrideSoleInstance(TimeProvider tpStub) {
//
// soleInstance ,
//
soleInstance = new ServiceLocatorTestSingleton( tpStub);
return (ServiceLocatorTestSingleton) soleInstance;
}
//
public ServiceProvider findService(String serviceName) {
return tpStub; // ; serviceName
}
}

. 698

699

HashMap, 
tpStub, .


.
(Service Locator) (Component Broker) .
. ,
. ,
. (Dependency Injection)
;
(Dependency Lookup). 

? . 588.

. 699

700

26

(Humble Object)
, ?
,
.

,
.
(, , ) 
. ,
, ,
.
 ;
(, , Web) .
, 
. 
. 
(Production Bugs, . 303), $
(Untested Code) (Untested Requirement).
(Humble Object) 
.


, 
(synchronous test). 
, , 
.

. 700

701

. (Humble Object) 
. $
(Humble Object) 
.
, (Humble Object) 
. (Humble Object)
, .


(Humble Object) 
, 
.
.
. 
(Humble Object), , 
.

: (Humble Dialog)

. 
, 
 . 
/
.
,
. ,

. ,
, ,
. 
(Slow Tests, . 289) (Nondeterministic Test). 
(Humble Object)

.

: (Humble Executable)
. 
,
. ,
(, Windows .exe) ( Java
, Runnable). 
, 
.
(
/ , Neverfail Test).

. 701

702

26

(Humble Executable)
,
(Slow Test) $
(Nondeterministic Test). 
, .
, , 
. 
. 
(DLL) Windows, Java JAR,
(Service Facade), ,
.
(Humble Executable) 
. 
( , True Humble Object)
. (Humble Executable)
 / .
, 
, . ,
, 
, ,
. , $
(Humble Executable) 
.

: (Humble Transaction Controller)


. 
,

. (Shared Fix
ture, . 350)
(Erratic Test). (Humble Transaction Controller) 
, ,
. ,
, .
(Humble Transaction Controller)
(Extract Method).
, 
.
, , ( )
( ) . ( ) 
(Humble Object) .
,
(Poor Mans Humble Object).
(Humble Object),  
. ,
. , 

. 702

703

(Test Stub, . 544), 


. .
(Poor Mans Humble Object)
(Subclassed Test Double), 
, .

, .

,
(Humble Transaction Controller).
.

: (Humble Container Adapter)



(, EJB Session Bean).
(Humble Object)
$
(Humble Container Adapter) 
. 
, , 
, .


, 
(Humble Object). :
. 
. 

(Humble Object). , 
(Test Double, . 538).

: (Poor Mans Humble Object)



. 
(Extract Method) 
. , 
.
, . 
,
( / ) ,
, .
,
(Humble Object), ,
(Humble Object) (, , 
). 

. 703

704

26

(TestSpecific Subclass),
.
(Subclassed Humble
Object) (Poor Mans Humble Object)
(Test Spy, . 552) (Subclassed Test
Double) . ,
(Test Method, . 378).

: (True Humble Object)



(Humble Object)
. . 
.
, ,
. ,
, 
, , .
(Humble Object)
(Humble Object) 
, .
.
(True Humble Object)

(Extract Method) (Humble
Object) . $
(Extract Class) (
) . (),
. 

.
(True Humble Object) ( $
(Humble Object) ), 
$
(Lazy Mock Object) (Test Spy).
(Mock Object) ,
,
(Testcase Object, . 410), , 
.

, $
(Object Factory). 
. ,
, (Mock
Object) (Test Stub),
.

. 704

705

: (Subclassed Humble Object)


(Poor Mans Humble
Object) (True Humble Object) , 
, , 
. 
(Humble Ob
ject). ,
. 
.
1.
.
2. , .


(Humble Executable)
, 
. ,
, . 
, ,
. , 
, .
public class RequestHandlerThreadTest extends TestCase {
private static final int TWO_SECONDS = 3000;
public void testWasInitialized_Async()
throws InterruptedException {
//
RequestHandlerThread sut = new RequestHandlerThread();
//
sut.start();
//
Thread.sleep(TWO_SECONDS);
assertTrue(sut.initializedSuccessfully());
}
public void testHandleOneRequest_Async()
throws InterruptedException {
//
RequestHandlerThread sut = new RequestHandlerThread();
sut.start();
//
enqueRequest(makeSimpleRequest());
//
Thread.sleep(TWO_SECONDS);
assertEquals(1, sut.getNumberOfRequestsCompleted());
assertResponseEquals(makeSimpleResponse(), getResponse());
}
}

. 705

706

26

. 
(Defect Localization, . 78).
, ,
.
, 
.
 , ,
. . 
, 
. 
. 
.
public class RequestHandlerThread extends Thread {
private boolean _initializationCompleted = false;
private int _numberOfRequests = 0;
public void run() {
initializeThread();
processRequestsForever();
}
public boolean initializedSuccessfully() {
return _initializationCompleted;
}
void processRequestsForever() {
Request request = nextMessage();
do {
Response response = processOneRequest(request);
if (response != null) {
putMsgOntoOutputQueue(response);
}
request = nextMessage();
} while (request != null);
}
}

 processOneRequest.
. ,
_initializationCompleted.


(Poor Mans Humble Object) 
. ( ,
(Extract Method).) 
, (Introduce pa
rameter) (Introduce field), processOneRequest 
.
(True Humble Object) 
(Extract Class)
.
,

. 706

707

(Humble Object). (Extract


Method), (, initializeThread processOneRequest) 
. (Extract Class) 
( Strategy)
, .

. , ,
.

: (Poor Mans Humble Object)


(Poor
Mans Humble Object).
public void testWasInitialized_Sync()
throws InterruptedException {
//
RequestHandlerThread sut = new RequestHandlerThread();
//
sut.initializeThread();
//
assertTrue(sut.initializedSuccessfully());
}
public void testHandleOneRequest_Sync()
throws InterruptedException {
//
RequestHandlerThread sut = new RequestHandlerThread();
//
Response response = sut.processOneRequest(makeSimpleRequest());
//
assertEquals(1, sut.getNumberOfRequestsCompleted());
assertResponseEquals(makeSimpleResponse(), response);
}

initializeThread processOneRequest 
, . 
. , 
.

: (True Humble Executable)



(True Humble Executable).
public class HumbleRequestHandlerThread extends Thread
implements Runnable {
public RequestHandler requestHandler;
public HumbleRequestHandlerThread() {
super();
requestHandler = new RequestHandlerImpl();
}
public void run() {

. 707

708

26

requestHandler.initializeThread();
processRequestsForever();
}
public boolean initializedSuccessfully() {
return requestHandler.initializedSuccessfully();
}
public void processRequestsForever() {
Request request = nextMessage();
do {
Response response =
requestHandler.processOneRequest(request);
if (response != null) {
putMsgOntoOutputQueue(response);
}
request = nextMessage();
} while (request != null);
}

processOneRequest ,
. , 
. .
public void testNotInitialized_Sync()
throws InterruptedException {
// /
RequestHandler sut = new RequestHandlerImpl();
//
assertFalse("init", sut.initializedSuccessfully());
}
public void testWasInitialized_Sync()
throws InterruptedException {
//
RequestHandler sut = new RequestHandlerImpl();
//
sut.initializeThread();
//
assertTrue("init", sut.initializedSuccessfully());
}
public void testHandleOneRequest_Sync()
throws InterruptedException {
//
RequestHandler sut = new RequestHandlerImpl();
//
Response response = sut.processOneRequest(makeSimpleRequest());
//
assertEquals(1, sut.getNumberOfRequestsDone());
assertResponseEquals(makeSimpleResponse(), response);
}

, ,
. 
initializeThread processOneRequest
(Humble Object).
public void testLogicCalled_Sync()
throws InterruptedException {
//

. 708

709

RequestHandlerRecordingStub mockHandler =
new RequestHandlerRecordingStub();
HumbleRequestHandlerThread sut = new HumbleRequestHandlerThread();
//
sut.setHandler(mockHandler);
sut.start();
//
enqueRequest(makeSimpleRequest());
//
Thread.sleep(TWO_SECONDS);
assertTrue("init", mockHandler.initializedSuccessfully());
assertEquals(1, mockHandler.getNumberOfRequestsDone());
}

, 
. ,
(Test Double),
. ,
(, ), 
.
(Test Spy)
(Mock Object). (Mock
Object) , (Test Method), ,
(Test Automation Framework) ( 
 JUnit) . 

(Mock Object). (Test Method),

(Mock Object) , (Test Method).

(Humble Object) (Test Spy). ,
,
. .
public void testConstructor() {
//
HumbleRequestHandlerThread sut = new HumbleRequestHandlerThread();
//
String actualDelegateClass = sut.requestHandler.getClass().getName();
assertEquals(RequestHandlerImpl.class.getName(),
actualDelegateClass);
}

(Constructor Test) .

: (Humble Dialog)

(
) .
, ,
, , .

. 709

710

26

, 
, .
,
. 
,
. 
,
. ,
(Production Bugs), $
(Untested Requirement).
(Humble Dialog)
,
. 
( , Humble Dialog), . 
(Humble Dialog) 
(Mock Object),
( ). ,
(Humble Dialog) 
, $
(Humble Dialog) ( 
). (Humble
Dialog) , 
.
Visual Basic (.ctl),
. , 
TestDirector Mercury Interactive.
' , TestDirector
'
Public Sub ShowResultEx(TestSetKey As TdTestSetKey, _
TSTestKey As TdTestKey, _
ResultKey As TdResultKey)
Dim RpbFiles As OcsRpbFiles
Set RpbFiles = getTestResultFileNames(ResultKey)
ResultsFileName = RpbFiles.ActualResultFileName
ShowFileInBrowser ResultsFileName
End Sub
Function getTestResultFileNames(ResultKey As Variant) As OcsRpbFiles
On Error GoTo Error
Dim Attachments As Collection
Dim thisTest As Run
Dim RpbFiles As New OcsRpbFiles
Call EnsureConnectedToTd
Set Attachments = testManager.GetAllAttachmentsOfRunTest(ResultKey)
Call RpbFiles.LoadFromCollection(Attachments, "RunTest")
Set getTestResultFileNames = RpbFiles
Exit Function
Error:
' -
End Function

. 710

711

. , 
, .
,
.
(Extract Testable Com
ponent) ,
(Humble Dialog).
(Extract
Method) ( 
) .
(Extract Class) .
(Extract Class) $
(Move Method) (Move Field)
(Humble Dialog) .
$
(Humble Dialog).
' , TestDirector
'
Public Sub ShowResultEx(TestSetKey As TdTestSetKey, _
TSTestKey As TdTestKey, _
ResultKey As TdResultKey)
Dim RpbFiles As OcsRpbFiles
Call EnsureImplExists
Set RpbFiles = Implementation.getTestResultFileNames(ResultKey)
ResultsFileName = RpbFiles.ActualResultFileName
ShowFileInBrowser ResultsFileName
End Sub
Private Sub EnsureImplExists()
If Implementation Is Nothing Then
Set Implementation = New OcsScriptViewerImpl
End If
End Sub

OcsScriptViewerImpl, 
(Humble Object).
' ResultViewer:
Public Function getTestResultFileNames(ResultKey As Variant) As
OcsRpbFiles
On Error GoTo Error
Dim Attachments As Collection
Dim thisTest As Run
Dim RpbFiles As New OcsRpbFiles
Call EnsureConnectedToTd
Set Attachments = testManager.GetAllAttachmentsOfRunTest(ResultKey)
Call RpbFiles.LoadFromCollection(Attachments, "RunTest")
Set getTestResultFileNames = RpbFiles
Exit Function
Error:
' -
End Function

. 711

712

26

OcsScriptViewerImpl 
VbUnit. ,
.

: (Humble Transaction Controller)


, (Transaction Rollback Tear
down, . 675), ,
(Humble Transaction Controller).


(Humble Dialog) 
:
http://www.objectmentor.com/resources/articles/TheHumbleDialogBox.pdf

. 712

713

(Test Hook)

?
.

/
/
?

/
/
?

, ,
. 
. ,
.
(Test Hook) 
.




. testing, .


, 
(Dependency Injection, . 684)
(Dependency Lookup, . 692). (Test Hook) 
 (Untested
Code), (HardCoded Dependency).
(Test Hook)
(Test Double, . 538)
, 
.
(Test Hook)
.
(Test Hook),

. 713

714

26

(Safety Net) .
,
(Test Hook), .


(Test Hook) 
. , :

(Test Double) ;

(Test Double) ;

, .


,
.

(Test Hook) . ,

.


.
public void testDisplayCurrentTime_AtMidnight() {
//
TimeDisplay sut = new TimeDisplay();
//
String result = sut.getCurrentTimeAsHtmlFragment();
//
String expectedTimeString =
"<span class=\"tinyBoldText\">Midnight</span>";
assertEquals(expectedTimeString, result);
}

, 
, .
DefaultTimeProvider 
.
public String getCurrentTimeAsHtmlFragment() {
Calendar currentTime;
try {
currentTime = new DefaultTimeProvider().getTime();
} catch (Exception e) {
return e.getMessage();
}
// ..
}


, (Test

. 714

715

Double) . 
.
.


, , 
(Test Hook). 
if/then/else then.

:

(Test Hook).
public String getCurrentTimeAsHtmlFragment() {
Calendar theTime;
try {
if (TESTING) {
theTime = new GregorianCalendar();
theTime.set(Calendar.HOUR_OF_DAY, 0);
theTime.set(Calendar.MINUTE, 0);}
else {
theTime = new DefaultTimeProvider().getTime();
}
} catch (Exception e) {
return e.getMessage();
}
// ..

,
. 
. , 
, 
.

:
(Test Hook) , 
.
public Calendar getTime() throws TimeProviderEx {
Calendar theTime = new GregorianCalendar();
if (TESTING) {
theTime.set(Calendar.HOUR_OF_DAY, 0);
theTime.set(Calendar.MINUTE, 0);}
else {
//
}
return theTime;
};

,
.

. 715

. 716

27

27


:
(Literal Value)................................................................. 718
(Derived Value) .................................................... 722
(Generated Value).......................................... 726
 (Dummy Object) ............................................................ 730

. 717

718

27

(Literal Value)
:
(HardCoded Value), (Constant Value)

, ?

.

BigDecimal expectedTotal = new BigDecimal("99.95");


, 
. ( , 
 ) , 
.
(Literal Value) 
.




(Assertion Method, . 390).
, , 
(Literal Value).


(Literal Value) 
; , .
, (Literal Value) 
, , , 
(Obscure Test, . 230). (Literal Value) 
, . (,
,
(DataDriven Test, . 322).)
(Literal Value) 

. , 
, .
(Literal Value) ,

. (Literal Value) 

(Obscure Test).

, (Derived
Value, . 722) (Tests as Docu

. 718

719

mentation, . 79). ,
, (Generated Value, . 726).


(Literal Value) .
(
), 
 .
, . ,
, ,
, (Literal Value).

: (Symbolic Constant)
(Literal Value) 
(Test Method, . 378) ,
(Literal Value) (Symbolic
Constant). (Symbolic Constant) 
(Literal Value), 
(High Test Maintenance Cost, . 300).

: (SelfDescribing Value)
, ,
, , 
. 
, , 
. ,
, Joe Blow, 
.

: (Literal Value)
(Literal Value)
,
(Literal Value) . ,
(Literal Value) 
, .
public void testAddItemQuantity_1() throws Exception {
Product product = new Product("Widget", 19.95);
Invoice invoice = new Invoice();
//
invoice.addItemQuantity(product, 1);
//
List lineItems = invoice.getLineItems();
LineItem actualItem = (LineItem)lineItems.get(0);
assertEquals(new BigDecimal("19.95"),
actualItem.getExtendedPrice());
}

. 719

720

27

Product . 
extendedCost lineItem .
. 
.



(Replace Magic Number with Symbolic Constant)
(Test Code Duplication, . 254),
(Literal Value) 19.95.

: (Symbolic Constant)
(Literal
Value) (19.95) $
(Symbolic Constant), 
.
public void testAddItemQuantity_1s() throws Exception {
BigDecimal widgetPrice = new BigDecimal("19.95");
Product product = new Product("Widget", widgetPrice);
Invoice invoice = new Invoice();
//
invoice.addItemQuantity(product, 1);
//
List lineItems = invoice.getLineItems();
LineItem actualItem = (LineItem)lineItems.get(0);
assertEquals(widgetPrice, actualItem.getExtendedPrice());
}

: (Self/Describing Value)
(SelfDescribing Value)
, Product. 
. 
, .
public void testAddItemQuantity_1b() throws Exception {
BigDecimal widgetPrice = new BigDecimal("19.95");
Product product = new Product("Irrelevant product name",
widgetPrice);
Invoice invoice = new Invoice();
//
invoice.addItemQuantity(product, 1);
//
List lineItems = invoice.getLineItems();
LineItem actualItem = (LineItem)lineItems.get(0);
assertEquals(widgetPrice, actualItem.getExtendedPrice());
}

. 720

721

: (Distinct Value)
, .
(Distinct Value) SKU,
.
public void testAddItemQuantity_1c() throws Exception {
BigDecimal widgetPrice = new BigDecimal("19.95");
String name = "Product name";
String sku = "Product SKU";
Product product = new Product(name, sku, widgetPrice);
Invoice invoice = new Invoice();
//
invoice.addItemQuantity(product, 1);
//
List lineItems = invoice.getLineItems();
LineItem actualItem = (LineItem)lineItems.get(0);
assertEquals(name, actualItem.getName());
}

(SelfDescribing Value).

. 721

722

27

(Derived Value)


(Calculated Value)

, ?

.

BigDecimal expectedTotal = itemPrice.multiply(QUANTITY);


,
. ( , 
 ) , 
.

. (Tests as Documentation,
. 79), .


.
( ),
. , (De
rived Value)
.
(Derived Value)
. /
(),
(Testcase Object, . 410), 
(Test Method, . 378).


(Derived Value) ,

. (Derived Value) 
(, 
) . , 
(Literal Value,
. 718).
,
(Generated Value, . 726).
(Derived Value) 
( , Derived Input, $
, One Bad Attribute)
( , Derived Expectation).
.

. 722

723

: (Derived Input)
,
. ,
(Derived Input) 
. 
.
, MAXIMUM_ALLOWABLE_
TIME_DIFFERENCE.

: (One Bad Attribute)


(Derived Input) 
, . ,
,
.
. 
, 
.
, (Single Condition Test, . 99).
,
. 
(Creation Method, . 441), $
(Test Code Duplication, . 254).

: (Derived Expectation)

,
$
(Literal Value).
(Equality Assertion).


(Derived Value) .
(Literal Value)
.
public void testAddItemQuantity_2a() throws Exception {
BigDecimal widgetPrice = new BigDecimal("19.99");
Product product = new Product("Widget", widgetPrice);
Invoice invoice = new Invoice();
//
invoice.addItemQuantity(product, 5);
//
List lineItems = invoice.getLineItems();
LineItem actualItem = (LineItem)lineItems.get(0);
assertEquals(new BigDecimal("99.95"),
actualItem.getExtendedPrice());
}

. 723

724

27


, .


(Literal Value)
.

: (Derived Expectation)

. , 
, .
public void testAddItemQuantity_2b() throws Exception {
BigDecimal widgetPrice = new BigDecimal("19.99");
BigDecimal numberOfUnits = new BigDecimal("5");
Product product = new Product("Widget", widgetPrice);
Invoice invoice = new Invoice();
//
invoice.addItemQuantity(product, numberOfUnits);
//
List lineItems = invoice.getLineItems();
LineItem actualItem = (LineItem)lineItems.get(0);
BigDecimal totalPrice = widgetPrice.multiply(numberOfUnits);
assertEquals(totalPrice, actualItem.getExtendedPrice());
}

, 
, 
.

: (One Bad Attribute)


, , 
CustomerDto. ,
CustomerDto. 
CustomerDto (Test Method) 
.
public void testCreateCustomerFromDto_BadCredit() {
//
CustomerDto customerDto = new CustomerDto();
customerDto.firstName = "xxx";
customerDto.lastName = "yyy";
// ..
customerDto.address = createValidAddress();
customerDto.creditRating = CreditRating.JUNK;
//
try {
sut.createCustomerFromDto(customerDto);
fail("Expected an exception");
} catch (InvalidInputException e) {

. 724

725

assertEquals("Field", "Credit", e.field);


}
}
public void testCreateCustomerFromDto_NullAddress() {
//
CustomerDto customerDto = new CustomerDto();
customerDto.firstName = "xxx";
customerDto.lastName = "yyy";
// ..
customerDto.address = null;
customerDto.creditRating = CreditRating.AAA;
//
try {
sut.createCustomerFromDto(customerDto);
fail("Expected an exception");
} catch (InvalidInputException e) {
assertEquals("Field", "Address", e.field);
}
}

(Test
Code Duplication), .
: 
, 
.
(Creation Method) 
CustomerDto 
. $
(One Bad Attribute) ( ).
public void testCreateCustomerFromDto_BadCredit_OBA() {
CustomerDto customerDto = createValidCustomerDto();
customerDto.creditRating = CreditRating.JUNK;
try {
sut.createCustomerFromDto(customerDto);
fail("Expected an exception");
} catch (InvalidInputException e) {
assertEquals("Field", "Credit", e.field);
}
}
public void testCreateCustomerFromDto_NullAddress_OBA() {
CustomerDto customerDto = createValidCustomerDto();
customerDto.address = null;
try {
sut.createCustomerFromDto(customerDto);
fail("Expected an exception");
} catch (InvalidInputException e) {
assertEquals("Field", "Address", e.field);
}
}

. 725

726

27

(Generated Value)
, ?
.
BigDecimal uniqueCustomerNumber = getUniqueNumber();

,
(),
. 
. , . 
, , !
(Generated Value) $
(Creation Method, . 441)
.



. ,
, ,
.


(Generated Value) ,
. , 

(Literal Value, . 718), 
. 
, .
(Generated Value) $
(Unrepeatable Test) (Test Run War) 
. 
,
.
, .
, , 
 , . 
(Nondeterministic Test).
( ,  ),
,
.
(Generated Value),
, .
(Literal Value). 

. 726

727

(Derived Value,
. 722), .


. 
.

: (Distinct Generated Value)


, 
(Distinct Generated Value).
,
(, , , ). 
getUnique
. , ,

. , ,
(
, Java, 
). , 1, 
: 
, .

: (Random Generated Value)




. 
(Random Generated Value). 
, , 
. 
.
(Random Generated Value)
. 
, .
. ,
, .

: (Related Generated Value)



(Generated Value) (Derived Value) 

.
getUniqueInt ,
. 
(Related Generated Value) ,

. 727

728

27

.

generateNewUniqueRoot  getUniqueInt,
getUniqueString ..
(role
describing argument), ,
.
, .


$
(Literal Value).
public void testProductPrice_HCV() {
//
Product product =
new Product(88,
// ID
"Widget",
//
new BigDecimal("19.99")); //
//
//
...
}



(Distinct Generated Value), (Literal Value) 
getUnique.
.

: (Distinct Generated Value)


, $
(Distinct Generated Value). getUniqueString ,
(Widget Name).
public void testProductPrice_DVG() {
//
Product product =
new Product(getUniqueInt(),
// ID
getUniqueString("Widget"), //
getUniqueBigDecimal());
//
//
//
...
}
static int counter = 0;
int getUniqueInt() {
counter++;
return counter;
}
BigDecimal getUniqueBigDecimal() {

. 728

729

return new BigDecimal(getUniqueInt());


}
String getUniqueString(String baseName) {
return baseName.concat(String.valueOf(getUniqueInt()));
}

. 
,
.
, ,
,
.

: (Related Generated Value)


, 
, . 
setUp,
. 
(, getUniqueString)
.
public void testProductPrice_DRVG() {
//

Product product =
new Product(getUniqueInt(),
// ID
getUniqueString("Widget"), //
getUniqueBigDecimal());
//
//
//
...
}
static int counter = 0;
public void setUp() {
counter++;
}
int getUniqueInt() {
return counter;
}
String getUniqueString(String baseName) {
return baseName.concat(String.valueOf(getUniqueInt()));
}
BigDecimal getUniqueBigDecimal() {
return new BigDecimal(getUniqueInt());
}

,
,
.

. 729

730

27

 (Dummy Object)
:
(Dummy), (Dummy Parameter),
- (Dummy
Value),
(Placeholder), (Stub)

,


?

.

Invoice inv = new Invoice(new DummyCustomer());


. ,
. #
( )
. #
,
. #
.
(Dummy Object),
.


,
. #
. #
, . 
(Dummy Object) , #
.


 (Dummy Object) ,

. (Obscure Test, . 230), #
,
. , #
.

,
(Test Stub, . 544) (Mock Object, . 558).
, , #
(Fake Object, . 565), #
.

. 730

731

 , 
.
(Literal Value, . 718), (Generated Value, . 726)
(Derived Value, . 722).

: / (Dummy Argument)
$ (Dummy Argument) , 
,
1.

: (Dummy Attribute)
$ (Dummy Attribute) 
, 
,
.


$ (Dummy Object)
null . 
, Java ( , 
null). 
null , . 
null
.
(, Ruby, Perl Python) 
( ),
, String Object.
(SelfDescribing Value),
Dummy Customer.
(, Java, C# C++) $
(Dummy Object) . 
,
(, Interface Java), 
(Pseudo
Object). ,
(Test
Specific Subclass, . 591) .
1

Wikipedia. ,
, 
. ,
, ,
.

, .

. 731

732

27

(Mock Object) $
(Test Utility Method, . 610), $
(Dummy Object) .
String (SelfDescribing Value).
$ (Dummy Object) null,
Null Object [PLOPD3]. $ (Dummy Object)
, 
. , Null Object 
, . ,
!


Invoice, 
Customer. Customer Address, 
, , City. , 
.
Customer,
, ?
public void testInvoice_addLineItem_noECS() {
final int QUANTITY = 1;
Product product = new Product(getUniqueNumberAsString(),
getUniqueNumber());
State state = new State("West Dakota", "WD");
City city = new City("Centreville", state);
Address address = new Address("123 Blake St.", city, "12345");
Customer customer= new Customer(getUniqueNumberAsString(),
getUniqueNumberAsString(),
address);
Invoice inv = new Invoice(customer);
//
inv.addItemQuantity(product, QUANTITY);
//
List lineItems = inv.getLineItems();
assertEquals("number of items", lineItems.size(), 1);
LineItem actual = (LineItem)lineItems.get(0);
LineItem expItem = new LineItem(inv, product, QUANTITY);
assertLineItemsEqual("",expItem, actual);
}


. Address City?
, ,   .
!


, 
. , 
. Customer 

. 732

733

null.
, null. .
$
(Dummy Object). .
, Java C#,
. Customer 
(Extract Interface) [Ref], 
, DummyCustomer. ,
Customer
. 
(TestSpecific Subclass) Customer, 
.

: / (Dummy Value) /
(Dummy Object)
, $ (Dummy Object)
Customer. , 
!
public void testInvoice_addLineItem_DO() {
final int QUANTITY = 1;
Product product = new Product("Dummy Product Name",
getUniqueNumber());
Invoice inv = new Invoice(new DummyCustomer());
LineItem expItem = new LineItem(inv, product, QUANTITY);
//
inv.addItemQuantity(product, QUANTITY);
//
List lineItems = inv.getLineItems();
assertEquals("number of items", lineItems.size(), 1);
LineItem actual = (LineItem)lineItems.get(0);
assertLineItemsEqual("", expItem, actual);
}

$ (Dummy Object)
, . , 
(SelfDescribing Value). $
(Dummy Object) ,
,
(Generated Value). Customer , 
LineItem null .
Java, . 
ICustomer 
, . 
DummyCustomer , , 
.
, Invoice 
, $ (Dummy Object) .
DummyCustomer.

. 733

734

27

public class DummyCustomer implements ICustomer {


public DummyCustomer() {
// ; !
}
public int getZone() {
throw new RuntimeException("This should never be called!");
}
}

DummyCustomer, 
. , ,
. DummyCustomer (Pseudo
Object). null 
.
, $ (Dummy Object).


[UTwJ] $ (Dummy Object),
(Test Stub). 
. JMock NMock
$ (Dummy Object) 
(Mock Object).

. 734

IV

. 735

. 736


(Extract Testable Component)

,
, $
.

:
(Sprout
Class) [WEwLC]


,

, .


, 
. . ,

.
$
(Humble Object, . 700). 
, . 
.
Windows DLL
Java JAR, (Service Facade) [CJ2EPP] 
, . 
, 
, .

(Humble Object), .

,  
. ,
, . 
,

. 737

738

,
. , 
.


(Extract Interface)
(Extract Implementer), (Extract Test
able Component) .
(Extract Class).

(In/line Resource)

(Mystery Guest).

.
[RTC]:
$
. $
, , . $
.
.
, , $
(Eager Test; . , Assertion
Roulette, . 264). (Extract
Method) (Minimize Data, . 739).


, , 
.
, ,
.
(Prebuilt Fixture) . , .
 . ,
, .
,
(Prebuilt Fixture)
(Persistent Fresh Fixture; . , Fresh Fixture, . 344). 
.

(Test Stub, . 544), . 
, . 
, (Test Stub) .

. 738

739


. , 
, (Extract Test
able Component, . 737).
, .. 
. , (Humble Object,
. 700), , 
(Test Stub) (Mock Object, . 558).

(Make Resource Unique)



(Shared Fixture).
.
[RTC]:
.
, ,
.
( )
(
). ,
, ,
.



(Distinct Generated Value; . $
, Generated Value, . 726) . 
, .
(Interacting Tests; . , Erratic
Test, . 267) . 
(Automated Teardown, . 521).

(Minimize Data)
.
,
(Minimal Fixture).
[RTC]:
, $
. :

.

. 739

740


,
(Minimal Fixture, . 336).
(Tests as Documentation, . 79). !
(Test Method, . 378)
(Testcase Class, . 401).
(Test Method) 
(Testcase Class per Fixture, . 639) ,
(General Fixture; . , Obscure Test, . 230),
, !
. ,
.
(Test Method)
(Testcase Class per Feature, . 633) (Testcase
Class per Class, . 627), (Minimize Data) !
setUp, !
(Testcase Class) (Setup Decorator, . 471),
, . , !
(Shared Fixture, . 350) !
,
(Extract Method) (Creation
Method, . 441), .
(Creation Method) setUp
(Test Method), !
. !
, , .


(Replace Dependency with Test Double)
.
,
(Test Double).


.
(Dependency Injection, . 684) ,
(Dependency Lookup, . 692) !
. !

.
(Fake Object, . 565), (Test Stub, . 544), (Test Spy,
. 552) (Mock Object, . 558) !
(Test Double). !
11, .

. 740

741

(Test Stub) (Mock


Object) (HardCoded Test
Double, . 581) (Configurable Test Double, . 571).
11
. , 
(Mock Object) 
.
, , 
(Mock Object). ,
(Mock Object) verification. 

(Extract Interface). 
, .

(Setup External Resource)


,
(Mystery Guest).
,
.
[RTC]:
, ,
, , 
(
).


, ,
(Test Stub,
. 544) (Fake Object, . 565), 
. , : 
,
(Resource
Optimism; . , Erratic Test, . 267). , 
(Interacting Tests; . ,
Erratic Test) (Test Run War; . , Erratic
Test). , 
(Mystery Guest; . , Obscure
Test, . 230) (Resource Optimism).
(Setup External Resource) 
(Test Method, . 378),
setUp (Test Utility Method, . 610). 
, . 
, .

. 741

. 742

xUnit
(Mock Object), (Fake Object),
(Test Stub) / (Dummy Object)
?
, ?
, !
(Test Double, . 538)
.
. !
(
? . 588.)
, , 
, 
. 
, .



(Test Double).

. 743

(Test Dou
ble, . 538)


/

/

,
/

744

. 744


/

/

,
/

(Dummy
Object,
. 730)

, ,

(Test Stub,
. 544)





(Test 
Spy, . 552)

( 
)

(Mock Ob
ject, . 558)






( 
)

(Fake Ob
ject, . 565)

()

(
)





(Temporary
Test Stub;
. $
$
, Test
Stub)




Null,


,
new
Object()

xUnit

745



, .
Astels Beck

Feathers

Fowler

jMock

UTWJ

(Test
Double)
Dummy

Fake

Stub

Stub

(Test
Spy)
$ Mock

(Mock
Object)

. 745

Recipes

Stub

Dummy

Mock

Dummy

Mock

Mock

Mock

Mock

(Fake
Object)

Dummy

$
$
$

(Temporary
Test Stub)

Stub

OMG
CORBA
Stub

Pragmatic
Double
Standin

$ Stub

(Dummy
Object)
Fake

(Test
Stub)

OMG

Fake

Fake

Mock

Mock

Stub

Unit Testing with Java [UTwJ] Dummy Object


, (Fake Object) .

Pragmatic Unit Testing [PUT] Stub 


. 

746

. 
Null Object [PLOPD3].

Stub Mock Object 


. [MRNO] [MAS].

CORBA (Common Object Request Broker Architecture; 


Object Management Group) 
Stub Skeleton

, IDL. (
,
.)

, .

Astels

TestDriven Development: A Practical


Guide

[TDDAPG]

Prentice Hall

Beck

TestDriven Development: By Example

[TDDBE]

AddisonWesley

Feathers

Working Effectively with Legacy Code

[WEwLC]

Prentice Hall

Fowler

Mocks Arent Stubs

[MAS]

martinfowler.com

jMock

Mock Roles, Not Objects

[MRNO]

ACM (OOPSLA)

UTWJ

Unit Testing in Java

[UTwJ]

OMG

CORBA Object Management


Group

OMG

Pragmatic

Pragmatic Unit Testing in C# with NUnit [PUT]

Pragmatic Bookshelf

Recipes

JUnit Recipes

Manning

Morgan Kaufmann

xUnit

xUnit. ,
xUnit 
.

. 746

. 747

xUnit

JUnit
3.8.2

JUnit
4.0+

CsUnit

NUnit 2.0

NUnit
2.1+

MbUnit
2.0

MSTest

PHPUnit

PyUnit

Test::Unit

Java 1.4

Java 5

.NET

.NET

.NET

.NET

.NET

PHP

Python

Ruby

testXxx() setUp()

testXxx

testXxx() setUp()

[Suite]

static
suite()

Test
Loader()
Classname
.suite()

[Test
Fixture]

[Test
Class]

Test::
Unit::
TestCase

unitest.
TestCase

TestCase

[Test
Method]

[Suite]

[Test
Fixture]
[Test]

[Test]

[Test]

[Suite]

[Test
Fixture]

[TearDown]

[TearDown]

[TearDown]

[TearDown]

@After

tearDown()

setUp

teardown

tearDown

tearDown()

[ClassInitialize]

[Fixture
Setup]

[TestFixtureSetUp]

@Before


(Suite
Fixture Setup)

[TestIni- [Test
tialize] Cleanup]

[SetUp]

[SetUp]

[SetUp]

[SetUp]

[Test]

[Suite]

[Test
Fixture]

@Before

testXxx() setUp()

static
suite()

@Test

(Test
Method)


(Test Suite
Factory)

import
static
org.junit. suite()
Test

TestCase

(Testcase
Class)

[Class
Cleanup]

[Fixture
Teardown]

[TestFixture
TearDown]

@After

(Suite Fixture
Teardown)

assert_raise

assert raise

Expected
Exception
Test

[Expected
Exception()]

[Expected
Exception()]

[Expected
Exception()]

[Expected
Exception()]

[Expected
Exception()]

@Exception

Expected
Exception
Test

(Expected
Exception Test)

. 748

xUnit

SUnit

VbUnit

ABAP
Unit

Smalltalk

VB 6

SAP
ABAP

FOR
TESTING

IFixture

Super
class:
TestCase

(Testcase
Class)

tearDown

setup

teardown

TestXxx() IFixture_ IFixture_


Setup()
TearDown

ISuite

setUp

class_
setup

IFixture
Frame_
Create()


(Suite
Fixture Setup)

(Test
Method)
$

TestSuite TestXxx
named:

(Test Suite
Factory)

class_
teardown

IFixture
Frame_
Destroy

(Suite Fixture
Teardown)

on error...

should:raise:

(Expected
Exception Test)

xUnit
xUnit 

. 
. :
http://xprogramming.com/software.htm

ABAP Object Unit


xUnit SAP ABAP. 
JUnit ABAP,
, .
ABAP Object Unit www.abapunittests.com. 
ABAP. SAP/ABAP 6.40
.

ABAP Unit
xUnit SAP ABAP
6.40 (NetWeaver 2004s). ABAP Unit 

.
ABAP Unit SAP AG
NetWeaver 2004s. 
ABAP SAP
www.abapunittests.com. SAP/ABAP 6.40 (NetWeaver 2004s)
ABAP Object Unit ( ).

CppUnit
xUnit C++. 
http://cppunit.sourceforge.net. .NET
NUnit.

. 749

750

CsUnit
xUnit C#.
www.csunit.org. .NET 
NUnit.

CUnit
xUnit C. 
:
http://cunit.sourceforge.net/doc/index.html

DbUnit
JUnit,
. www.dbunit.org.

IeUnit
xUnit Web, 
Microsoft Internet Explorer JavaScript DHTML. 
http://ieunit.sourceforge.net/.

JBehave
xUnit, 
(Tests as Specification) .
JBehave xUnit 
,
. , fixture context, assert  should
.. JBehave http://jbehave.codehaus.org. 
Ruby RSpec.

JUnit
xUnit Java. 2005
, Java 1.5. 
www.junit.org.

. 750

xUnit

751

MbUnit
xUnit C#.
MbUnit (Para
metrized Test). www.nunit.orgmbunit.com.
.NET NUnit, CsUnit MSTest.

MSTest
xUnit ,
Microsoft.VisualStudio.TestTools.UnitTesting,
, MSTest.
(CommandLine Test Runner) mstest.exe.
MSTest Visual Studio 2005 Team System. 
Visual Studio . MSTest 
, $
(DataDriven Test).
MSDN :
http://msdn.microsoft.com/en-us/library/ms182516.aspx

( ) 
.NET NUnit, CsUnit MbUnit.

NUnit
xUnit .NET. 
www.nunit.org. C#
CsUnit, MbUnit MSTest.

PHPUnit
xUnit PHP. 
, PHPUnit JUnit 3.8.
(Mock Object),
(Code Coverage), (Agile Documentation)
(Incomplete and Skipped Tests). PHPUnit
http://www.phpunit.de. PHPUnit.

PyUnit
xUnit Python. 
JUnit.
http://pyunit.sourceforge.net/.

. 751

752

RSpec
xUnit, 
(Tests as Specification) .
RSpec xUnit
, 
. , fixture context, assert  should
.. RSpec http://rspec.rubyforge.org.
Java JBehave.

runit
xUnit Ruby. Test::Unit,
.
www.rubypeople.org.

SUnit
. 
SUnit Smalltalk.
http://sunit.sourceforge.net.

Test::Unit
xUnit Ruby.
www.rubypeople.org Ruby Development Tools 
Eclipse.

TestNG
xUnit Java. 
JUnit . TestNG 
(Test
Method). http://
testng.org.

utPLSQL
xUnit PL/SQL. 
http://utplsql.
sourceforge.net/. utPLSQL 
Oracle www.ounit.com.

. 752

xUnit

753

VB Lite Unit
xUnit,
Visual Basic VBA (Visual Basic for Applications). VB Lite Unit 
Visual Basic VBA. 
. VB Lite Unit 
, 
,
Visual Basic 6 VBA. , 
, Visual Basic VBA ,
.
Visual Basic VBA VbUnit.
VB.NET NUnit, CsUnit MbUnit.

VbUnit
xUnit Visual Basic 6.0.
(Suite Fix
ture Setup)
(Testcase Class).
VbUnit
(Assertion Method). , 
, $
(Test Runner). $
(Custom Assertion),
(Expected Exception
Test). $
(Custom Assertion) (Encapsulated
Test Runner).
xUnit. www.vbunit.org.
; , .
Visual Basic VBA VB Lite Unit.
VB.NET NUnit, CsUnit MbUnit.

xUnit
(Test Automation
Framework) , SUnit JUnit.
xUnit
http://xprogramming.com http://en.wikipedia.org/wiki/XUnit. 

www.opensourcetesting.org.

. 753

. 754

. 
, 
xUnit.

Ant
,
Java. .NET NAnt.

AntHill
, Java.

BPT
(Scripted Test), 

, (Recorded Test).
,
, .
Mercury Interactive. 
Mercury Interactive 
HewlettPackard, .

Canoo WebTest
(Scripted Test), 
XML. Canoo WebTest Fit,

.
http://webtest.canoo.com http://webtest-community.canoo.com.

. 755

756

Cruise Control
, Java. 
.NET Cruise Control.net.

DDSteps
DataDriven Test JUnit. DDSteps
JUnit, . ,
DDSteps .
www.ddsteps.org.

EasyMock
(Mock Object)
Java. EasyMock (Configuration Mode)
, . 
www.easymock.org.

eCATT
(Recorded Test), 
SAP.
www.sap.com www.sdn.sap.com.

Eclipse
Java. Eclipse
IBM, Eclipse Foundation. 

xUnit. , Java JUnit,
Ruby Development Tools  Test::Unit. Eclipse
www.eclipse.org.

Fit
, 
. Fit 
Web 
. Fit , 
, , Java,
.NET, Ruby Python. 
. , Fitnesse, 
.
.

. 756

757

http://fit.c2.com [FitB],
.

FitNesse
Fit,
Object Mentor. FitNesse Wiki
.
. 
www.fitnesse.org.

HttpUnit
JUnit , Web
HTTP. HttpUnit ,

(, AJAX).
http://httpunit.sourceforge.net.

Idea
Java,
. Idea [JBrains]
. Visual Studio,
ReSharper.

JFCUnit
JUnit, HttpUnit 
Web HTTP. JFCUnit 
(Test Utility Method), $
(HigherLevel Language) Web.
HttpUnit, . 
, JFCUnit
(, AJAX). 
http://jfcunit.sourceforge.net.

JMock
(Mock Object)
Java. (Configuration Inter
face) .
www.jmock.org.

. 757

758

NMock
(Mock Object)
.NET. (Configuration
Interface) 
. http://nmock.org.

QTP (QuickTest Professional)


, 
. 
Expert View QTP 
. 
.
Mercury Interactive.
Mercury Interactive 
HewlettPackard, .

ReSharper
JetBrains (
Idea) Visual Studio. 
[JBrains].

Visual Studio
Microsoft,
.NET. (
). MSTEst
. , 
(. [JBrains]), xUnit (. CsUnit, MbUnit NUnit).

Watir
Web Application Testing in Ruby.
Internet Explorer
(Scripted Test), Ruby. 
http://wtr.rubyforge.org/.

. 758

. 759

(Bug
Repellent)

78


(Bug Repellent)


(Communicate Intent)

95


(Communicate Intent)

(Defect
Localization)

78


(Defect Localization)


(Design for
Testability)

94


(Design for
Testability)

(Do No Harm)

79

(Do No Harm)

$
(Dont Modify
the SUT)

95

$
(Dont
Modify the SUT)

$

(Ensure Commensurate Effort
and Responsibility)

101

$

(Ensure Commensurate
Effort and Responsibility)


(Executable Specification)

77


(Tests as Specification)


(Expressive Tests)

83


(Expressive Tests)


(Front Door First)

94

$
(Use the Front Door
First)

$
(Fully
Automated Tests)

81

$
(Fully
Automated Tests)

(Higher
Level Language)

95


(Communicate Intent)


(Independent Tests)

96


(Keep Tests
Independent)

760

. 760


(Isolate the SUT)

97


(Isolate the SUT)


(Keep Test Logic
Out of Production Code)

99


(Keep Test
Logic Out of Production
Code)


(Keep Tests
Independent)

96


(Keep Tests
Independent)


(Minimize Test
Overlap)

98

$
(Minimize Test
Overlap)

$
(Minimize
Untestable Code)

98

$
(Minimize
Untestable Code)


(No Test Logic in
Production Code)

99


(Keep Test
Logic Out of Production
Code)


(No Test Risk)

79

(Do No Harm)


(Repeatable Tests)

81


(Repeatable Tests)

(Robust
Test)

84


(Robust Test)

(Safety
Net)

79

(Tests
as Safety Net)


(SelfChecking Test)

81


(SelfChecking Test)


(Separation of Concerns)

83


(Separation of Concerns)

(Simple Tests)

83

(Simple
Tests)

(Single
Condition Test)

99


(Verify One
Condition per Test)


(Single Glance Readable)

95


(Communicate Intent)

$
(Test Concerns
Separately)

101

$
(Test Concerns
Separately)


(TestDriven Development)

94


(Write the Tests First)

761

. 761

$
(Test First Development)

94


(Tests as Documentation)


(Write the Tests First)

79


(Tests as Documentation)

(Tests as
Safety Net)

79


(Tests as Safety Net)

(Tests
as Specification)

77


(Tests as Specification)


(Use the Front Door First)

94


(Use the Front
Door First)


(Verify One Condition
per Test)

99


(Verify One
Condition per Test)

(Write
the Tests First)

94


(Write the Tests First)

. 762

. 763



(Assertion Roulette)


(Assertion Roulette)

264


(Asynchronous Code)

252


(HardtoTest Code)

15


(Asynchronous Test)

291

(Slow
Tests)

16

$
(Behavior Sensitivity)

279


(Fragile Test)

16

(Buggy Test)

296

(Buggy
Test)

17

(Complex
Teardown)

248


(Conditional Test Logic)

15

(Complex
Test)

230


(Obscure Test)

15


(Conditional Test Logic)

243


(Conditional Test Logic)

15


(Conditional Verification
Logic)

246


(Conditional Test Logic)

15

$
(Context Sensitivity)

282


(Fragile Test)

16


(Cutand
Paste Code Reuse)

255


(Test Code Duplication)

15


(Data Sensitivity)

280


(Fragile Test)

16


(Developers Not
Writing Tests)

298


(Eager Test)

231


(Assertion Roulette)

16

(Equality
Pollution)

260


(Test Logic in Production)

15


(Developers Not
Writing Tests)

16

17

764

. 764



(Erratic Test)


(Erratic Test)

267

(Flexible Test)

245


(Conditional Test Logic)

15


(For Tests Only)

259


(Test Logic in Production)

15

$
(Fragile Fixture)

284


(Fragile Test)

16

(Fragile Test)

277


(Fragile Test)

16

(Frequent
Debugging)

285


(Frequent Debugging)

16


(General
Fixture)

234


(HardtoTest Code)

251


(HardCoded Dependency)

252


(HardCoded Test Data)

238


(Obscure Test)

$
(High Test
Maintenance Cost)

300

(Highly
Coupled Code)

252


(HardtoTest Code)

15


(Indented Test Code)

243

15


(Indirect Testing)

239


(Obscure Test)

15


(Infrequently Run Tests)

303


(Production Bugs)

17


(Interacting Test
Suites)

270


(Erratic Test)

16


(Interacting Tests)

268


(Erratic Test)

16

$
(Interface Sensitivity)

278


(Fragile Test)

16


(Irrelevant Information)

235


(Obscure Test)

15

(Lonely Test)

271


(Erratic Test)

16


(Obscure Test)

16

15


(HardtoTest Code)

15


(HardtoTest Code)

15

$
(High Test
Maintenance Cost)


(Conditional Test Logic)

15
17

765

. 765



(Obscure Test)

(Long Test)

230

(Lost Test)

304


(Production Bugs)

17

(Manual
Debugging)

285

16


(Manual Event Injection)

288


(Manual Intervention)

16


(Manual Fixture
Setup)

287


(Manual Intervention)

16


(Manual Intervention)

287


(Manual Intervention)

16


(Manual Result Verification)

288


(Manual Intervention)

16


(Missing
Assertion Message)

265


(Assertion Roulette)

16


(Missing Unit Test)

305


(Production Bugs)

17


(Multiple Test Conditions)

249


(Conditional Test Logic)

15

(Mystery
Guest)

232


(Obscure Test)

15


(Neverfail Test)

308


(Production Bugs)

17


(Nondeterministic Test)

275


(Erratic Test)

16

(Not
Enough Time)

298


(Developers Not
Writing Tests)

17

(Obscure
Test)

230


(Overcoupled Test)

283


(Overspecified Software)

283


(Production Bugs)

303

$
(Production Logic in Test)

247


(Conditional Test Logic)

15


(Reinventing the Wheel)

256


(Test Code Duplication)

15

(Frequent
Debugging)

15


(Obscure Test)

15


(Fragile Test)

16


(Fragile Test)

16


(Production Bugs)

17

766

. 766

(Resource
Leakage)

271


(Erratic Test)

16


(Resource Optimism)

272


(Erratic Test)

16


(Sensitive Equality)

283


(Fragile Test)

16


(Slow Component
Usage)

290


(Slow Tests)

16

(Slow Tests)

289


(Slow Tests)

16


(Test Code Duplication)

254


(Test Code Duplication)

15


(Test Dependency in
Production)

260


(Test Logic in Production)

15


(Test Logic in Production)

257


(Test Logic in Production)

15


(Test Run War)

274


(Erratic Test)

16


(Too Many Tests)

292


(Slow Tests)

16


(Unrepeatable Test)

272


(Erratic Test)

16


(Untestable Test Code)

253


(HardtoTest Code)

15


(Untested Code)

306


(Production Bugs)

17


(Untested Requirement)

307


(Production Bugs)

17

(Verbose Test)

230

15

$
(Wrong
Test Automation Strategy)

299


(Developers Not
Writing Tests)


(Obscure Test)

17

. 767


(Abstract Setup Decorator)

472


(Setup Decorator)

20

$
(Abstract Test Fixture)

646


(Testcase Superclass)

24

(Abstract
Testcase)

646


(Testcase Superclass)

24

(AllTests Suite)

605


(Named Test
Suite)

24


(Anonymous Creation Method)

443


(Creation Method)

20


(ArgumentDescribing Message)

399

$
(Assertion
Message)

19


(AssertionIdentifying
Message)

399

$
(Assertion
Message)

19


(Assertion Message)

398

$
(Assertion
Message)

19

(Assertion
Method)

390

$
(Assertion Method)

19

(Attachment
Method)

444


(Creation Method)

20

$
(Automated Exercise
Teardown)

523

$
(Automated
Teardown)

22


(Automated Fixture
Teardown)

522

$
(Automated
Teardown)

22

768

. 768


(Automated Teardown)

521


(Automated Unit Test)

318


(Back Door Manipulation)

359


(Back Door Setup)

360


(Back Door Teardown)

$
(Automated
Teardown)

22

$
(Scripted Test)

18


(Back
Door Manipulation)

18


(Back
Door Manipulation)

18

361


" " (Back
Door Manipulation)

18


(Back Door Verification)

362


(Back
Door Manipulation)

18


(BehaviorExposing Subclass)

592


(TestSpecific
Subclass)

23

$
(BehaviorModifying Subclass)

592


(TestSpecific
Subclass)

23

(Behavior
Verification)

489


(Behavior Verification)

21

(Bespoke
Assertion)

495

$
(Custom
Assertion)

21

(Builtin
Test Recording)

313


(Recorded Test)

18

(Calculated
Values)

722


(Derived Value)

27

/
(Capture/Playback Test)

311


(Recorded Test)

18

(Chained Tests)

477


(Chained Tests)

20

(Cleanup Method)

613

(Test
Utility Method)

24


(CommandLine
Test Runner)

407


(Test Runner)

19

(Component
Broker)

692


(Dependency Lookup)

26

769

. 769

(Component
Registry)

692


(Dependency Lookup)

26

(Component Test)

371

(Layer
Test)

18


(Configurable Mock Object)

571

$

(Configurable Test
Double)

23


(Configurable Test Double)

571

$

(Configurable Test
Double)

23


(Configurable Test Spy)

571

$

(Configurable Test
Double)

23


(Configurable Test Stub)

571

$

(Configurable Test
Double)

23


(Configuration Interface)

573

$

(Configurable Test
Double)

23

(Configuration
Mode)

573

$

(Configurable Test
Double)

23

(Constant
Value)

718


(Literal Value)

27

(Constructor
Injection)

686


(Dependency Injection)

26

(Constructor
Test)

381

(Test
Method)

19

(Creation Method)

441


(Creation Method)

20

(Custom
Assertion)

495

$
(Custom
Assertion)

21


(Custom Assertion Test)

498

$
(Custom
Assertion)

21

$
(Custom Equality Assertion)

497

$
(Custom
Assertion)

21

770

. 770


(DBSchema per Test
Runner)

659


(Database
Sandbox)

25

(Data Loader)

362


(Back
Door Manipulation)

18

(Data Retriever)

363


(Back
Door Manipulation)

18

(Data
Driven Test)

322


(DataDriven
Test)

18

&
(DataDriven Test
Framework) (Fit)

324


(DataDriven
Test)

18

&
(DataDriven Test
Framework)

334

&

(Test Automation
Framework)

18


(Database Extraction Script)

363


(Back
Door Manipulation)

18


(Database Partitioning Scheme)

660


(Database
Sandbox)

25


(Database Population Script)

362


(Back
Door Manipulation)

18


(Database Sandbox)

658


(Database
Sandbox)

25

&
(Decorated Lazy Setup)

473


(Setup Decorator)

20


(Dedicated Database
Sandbox)

659


(Database
Sandbox)

25


(Delegated Setup)

437

&
(Delegated
Setup)

20

(Delegated
Teardown)

529


(Inline Teardown)

22

 (Delta
Assertion)

505


(Delta Assertion)

21

771

. 771


(Dependency Initialization Test)

381

(Dependency
Injection)

(Test
Method)

19

684


(Dependency Injection)

26

(Dependency
Lookup)

692


(Dependency Lookup)

26

(Derived
Expectation)

723


(Derived Value)

27


(Derived Input)

723


(Derived Value)

27

(Derived
Value)

722


(Derived Value)

27


(Diagnostic Assertion)

497

&
(Custom
Assertion)

21


(Direct Test Method
Invocation)

427


(Test Enumeration)

19


(Distinct Generated Value)

727

&
(Generated Value)

27


(Domain Assertion)

497

&
(Custom
Assertion)

21

(Dummy)

730

&
(Dummy Object)

27

& (Dummy
Argument)

731

&
(Dummy Object)

27

& (Dummy
Attribute)

731

&
(Dummy Object)

27

& (Dummy Object)

730

&
(Dummy Object)

27

& (Dummy
Parameter)

730

&
(Dummy Object)

27

& (Dummy Value)

730

&
(Dummy Object)

27

&
(Dynamically Generated
Test Double)

574


(Configurable Test
Double)

23


(Entity Chain Snipping)

546


(Test Stub)

23

(Equality
Assertion)

393

&
(Assertion Method)

19

772

. 772


(ExpectationDescribing Message)

399

&
(Assertion
Message)

19

(Expected
Behavior)

491


(Behavior Verification)

21

&
(Expected Behavior
Specification)

491


(Behavior Verification)

21

&
(Expected Exception Assertion)

394

&
(Assertion Method)

19


(Expected Exception Test)

380

(Test
Method)

19

(Expected
Object)

486


(State Verification)

21

&
(Expected State Specification)

486


(State Verification)

21

(External
Test Recording)

314


(Recorded Test)

18

(Fake
Database)

566


(Fake Object)

23

(Fake Object)

565


(Fake Object)

23


(Fake Service Layer)

567


(Fake Object)

23

Web (Fake Web


Service)

567


(Fake Object)

23

&
(File System Test
Runner)

498


(Test Runner)

19

&
(Fixture Setup Testcase)

479


(Chained Tests)

20


(FourPhase Test)

387


(FourPhase Test)

19


(FrameworkInvoked
Setup)

449


(Implicit Setup)

20


(FrameworkInvoked
Teardown)

533


(Implicit Teardown)

22

(Fresh Context)

344


(Fresh
Fixture)

18

773

. 773


(Fresh Fixture)

344


(Fuzzy Equality Assertion)

393


(GarbageCollected Teardown)

&
(Fresh
Fixture)

18

&
(Assertion Method)

19

518


(Garbage
Collected Teardown)

22


(Generated Value)

726

&
(Generated Value)

27


(Global Fixture)

455


(Prebuilt
Fixture)

20

&
(Graphical Test
Runner)

406


(Test Runner)

19

(Guard
Assertion)

510

(Guard
Assertion)

21

&
(HandBuilt Test Double)

573


(Configurable Test
Double)

23


(HandScripted Test)

319

&
(Scripted Test)

18

(Hand
Written Test)

319

&
(Scripted Test)

18


(HardCoded Mock Object)

581

&
(Hard
Coded Test Double)

23

&
(HardCoded Setup
Decorator)

473


(Setup Decorator)

20


(HardCoded Test Double)

581

&
(Hard
Coded Test Double)

23


(HardCoded Test Stub)

581

&
(Hard
Coded Test Double)

23

(Hard
Coded Value)

718


(Literal Value)

27

(Hooked
Setup)

449


(Implicit Setup)

20

774

. 774

(Hooked
Teardown)

533


(Implicit Teardown)

22


(Humble Container Adapter)

703


(Humble Object)

26

(Humble
Dialog)

701


(Humble Object)

26


(Humble Executable)

701


(Humble Object)

26

(Humble
Object)

700


(Humble Object)

26

&
(Humble Transaction Controller)

702


(Humble Object)

26


(Immutable Shared
Fixture)

355

&
(Shared
Fixture)

18

(Implicit Setup)

449


(Implicit Setup)

20

(Implicit
Teardown)

533


(Implicit Teardown)

22

(Imposter)

538


(Test Double)

23


(InDatabase
Stored Procedure Test)

663

&
(Stored Procedure
Test)

25

(InMemory
Database)

567


(Fake Object)

23


(Incremental Tabular Test)

620

(Parametrized
Test)

24

(Incremental
Tests)

353

&
(Shared
Fixture)

18


(Indirect Output Registry)

555

(Test
Spy)

23

(Inline
Setup)

434


(Inline Setup)

20

(Inline
Teardown)

527


(Inline Teardown)

22


(Inner Test Double)

583

&
(Hard
Coded Test Double)

23


(Interaction Testing)

489


(Behavior Verification)

21

775

. 775

(Layer Test)

368

(Layer
Crossing Test)

359

(Layered Test)

368

(Lazy Setup)

460

(Lazy Teardown)

670

&
(Leftover Fixture)

350

(Literal Value)

718

(LoopDriven
Test)

621

&
(Minimal Fixture)

336

(Minimal
Context)

336

(Mock Object)

558


(Naive Inline Teardown)

529

&
xUnit (Naive xUnit Test
Interpreter)

(Layer
Test)

18


(Back
Door Manipulation)

18


(Layer Test)

18


(Lazy Setup)

20


(Table
Truncation Teardown)

25


(Shared
Fixture)

18


(Literal Value)

27

(Parametrized
Test)

24

&

(Minimal Fixture)

18

&

(Minimal Fixture)

18


(Mock Object)

23


(Inline Teardown)

22

326


(DataDriven
Test)

18

,
(Named State Reaching
Method)

443


(Creation Method)

20

(Named
Test Suite)

604


(Named Test
Suite)

24


(Object Attribute Equality
Assertion)

497

&
(Custom
Assertion)

21

(Object Factory)

692


(Dependency Lookup)

26

776

. 776

(Object
Mother)

652

(Test
Helper)

24


(One Bad Attribute)

723


(Derived Value)

27

(Parameter
Injection)

686


(Dependency Injection)

26


(Parameterized
Anonymous Creation Method)

443


(Creation Method)

20


(Parameterized Creation Method)

442


(Setup Decorator)

20


(Parameterized Test)

618

(Parameterized
Test)

21

&
(PerRun Fixture)

355


(Shared
Fixture)

18

(Persistence
Layer Test)

370

(Layer
Test)

18

&
(Persistent Fresh Fixture)

347


(Fresh
Fixture)

18

(Placeholder)

730

&
(Dummy Object)

27


(Poor Mans Humble Object)

703


(Humble Object)

26

&
(Prebuilt Context)

454


(Prebuilt
Fixture)

20

&
(Prebuilt Fixture)

454


(Prebuilt
Fixture)

20


(Presentation Layer Test)

369

(Layer
Test)

18


(Private Fixture)

343

&
(Fresh
Fixture)

18


(Procedural Behavior Verification)

491


(Behavior Verification)

21


(Procedural State Verification)

485


(State Verification)

21

777

. 777


(Procedural Test Stub)

546


(Test Stub)

23


(Programmatic Test)

319

&
(Scripted Test)

18

(PseudoObject)

584

&
(Hard
Coded TestDouble)

23


(Pushdown Decorator)

473


(Setup Decorator)

20


(Random Generated Value)

727

&
(Generated Value)

27

&
(Record and Playback Test)

312


(Recorded Test)

18


(Refactored Recorded Test)

314


(Recorded Test)

18


(Related Generated Value)

727

&
(Generated Value)

27

&
(Remoted Stored Procedure Test)

664

&
(Stored Procedure
Test)

25

(Responder)

545


(Test Stub)

23

(Retrieval
Interface)

554

(Test
Spy)

23



(Reuse Test for Fixture Setup)

444


(Creation Method)

20


(Reused Fixture)

350

&
(Shared
Fixture)

18


(Robot User Test)

312


(Recorded Test)

18


& (Robot
User Test Framework)

333

&
(Test Automation
Framework)

18

(Row Test)

620

(Parameterized
Test)

24

&
(SUT
API Encapsulation)

612

(Test
Utility Method)

24


(SUT Encapsulation
Method)

612

(Test
Utility Method)

24

778

. 778

(Saboteur)

545

(Scripted
Test)

319

(Self Shunt)

583

(Self
Describing Value)


(Test Stub)

23

&
(Scripted Test)

18

&
(Hard
Coded Test Double)

23

719


(Literal Value)

27

(Service
Layer Test)

370

(Layer
Test)

18

(Service Locator)

692


(Dependency Lookup)

26

(Setter
Injection)

687


(Dependency Injection)

26

(Setup
Decorator)

471


(Setup Decorator)

20

(Shared Context)

350

&
(Shared
Fixture)

18


(Shared Fixture)

350

&
(Shared
Fixture)

18


(Shared
Fixture State Assertion)

511

&
(Guard
Assertion)

21

(Shared
Setup Method)

449


(Implicit Setup)

20

(Simple
Success Test)

379

(Test
Method)

19

(SingleLayer
Test)

368

(Layer
Test)

18

&
(Single Outcome
Assertion)

394

&
(Assertion Method)

19

(Single Test
Suite)

605


(Named Test
Suite)

24

(Slow Test)

351

&
(Shared
Fixture)

18

(Spy)

552

(Test
Spy)

23

779

. 779

&
(Stale Fixture)

350

&
(Shared
Fixture)

18

(Standard
Context)

338


(Standard
Fixture)

18

&
(Standard Fixture)

338

(Standard Fixture)

18

(State
Verification)

484


(State Verification)

21


(StateBased Testing)

484


(State Verification)

21


(StateExposing Subclass)

592


(TestSpecific
Subclass)

23

&
(Stated Outcome Assertion)

393

&
(Assertion Method)

19

&
(Statically Generated
Test Double)

574

&

(Configurable Test
Double)

23

(Stored
Procedure Test)

662

&
(Stored Procedure
Test)

25

(Stub)

544


(Test Stub)

23

(Stub)

730

&
(Dummy Object)

27


(Subclassed Humble Object)

705


(Humble Object)

26


(Subclased Singleton)

593


(TestSpecific
Subclass)

23


(Subclassed Test Double)

592


(TestSpecific
Subclass)

23


(Subcutaneous Test)

370

(Layer
Test)

18


(Subset Suite)

605


(Named Test
Suite)

24

&
(Substitutable Singleton)

593


(TestSpecific
Subclass)

23

780

. 780

&
(Substituted Singleton)

593


(TestSpecific
Subclass)

23

(Suite of Suites)

415


(Test Suite Object)

19


(Suite Fixture Setup)

465



(Suite Fixture Setup)

20

(Symbolic
Constant)

719


(Literal Value)

27

(Table
Truncation Teardown)

668


(Table
Truncation Teardown)

25

(Tabular Test)

620

(Parameterized
Test)

24

(Teardown
Guard Clause)

528


(Inline Teardown)

22


(Temporary Test Stub)

545


(Test Stub)

23


(Test Automation
Framework)

332


(Test Automation
Framework)

18

(Test Bed)

454

&
&
(Prebuilt
Fixture)

20

(Test
Discovery)

420


(Test Discovery)

19

(Test Double)

538


(Test Double)

23

(Test
Double Class)

582

&
(Hard
Coded Test Double)

23


(Test Double Subclass)

592


(TestSpecific
Subclass)

23


(Test Double as Back Door)

363


(Back
Door Manipulation)

18

(Test
Enumeration)

425


(Test Enumeration)

19

(Test
Fixture)

401


(Testcase Class)

19

781

. 781


(Test Fixture Registry)

652


(Test Helper)

651


(Test Helper Class)

653


(Test Helper Mixin)

(Test
Helper)

24

(Test
Helper)

24

(Test
Helper)

24

647


(Testcase Superclass)

24


(Test Helper Object)

653

(Test
Helper)

24

(Test Hook)

713


(Test Hook)

26

(Test Method)

378

(Test
Method)

19


(Test Method Discovery)

421


(Test Discovery)

19


(Test Method Enumeration)

426


(Test Enumeration)

19


(Test Method Selection)

430

(Test
Selection)

19


(Test Object Registry)

521

(Automated
Teardown)

22


(Test Runner)

405


(Test Runner)

19

(Test Selection)

429

(Test
Selection)

19

(Test Spy)

552

(Test
Spy)

23

(Test Stub)

544


(Test Stub)

23


(Test Suite Enumeration)

426


(Test Enumeration)

19

(Test Suite
Factory)

425


(Test Enumeration)

19

(Test Suite
Object)

414


(Test Suite Object)

19


(Test Suite Object Generator)

326


(DataDriven
Test)

18

782

. 782


(Test Suite Object Simulator)

327


(DataDriven
Test)

19


(Test Tree Explorer)

408


(Test Runner)

19


(Test Utility Method)

610

&
(Test Utility
Method)

24


(Test Utility Test)

614

&
(Test Utility
Method)

24


(TestSpecific Extension)

591


(TestSpecific
Subclass)

23


(TestSpecific Subclass)

591


(TestSpecific
Subclass)

23

(Testcase Class)

401

(Testcase
Class)

19


(Testcase Class Discovery)

421


(Test Discovery)

19


(Testcase Class per Class)

627

&
(Testcase
Class per Class)

24


(Testcase Class per Feature)

633

&
(Testcase
Class per Feature)

24


(Testcase Class per
Fixture)

639

&
&
(Testcase Class
per Fixture)

24


(Testcase Class per Method)

634

&
(Testcase
Class per Feature)

24

&
(Testcase Class
per User Story)

634

&
(Testcase
Class per Feature)

24

(Testcase Class
Selection)

430

(Test
Selection)

19

(Testcase
Class Suite)

414


(Test Suite Object)

19

(Testcase Object)

410


(Testcase Object)

19

(Testcase
Superclass)

646


(Testcase Superclass)

24

783

. 783


(Testing by Layers)

369


(Layer Test)

18

xUnit

334

&

(Test Automation
Framework)

18


(Transaction Rollback Teardown)

675

(Transaction Rollback
Teardown)

25

&
(Transient Fresh Fixture)

347

&
(Fresh
Fixture)

18


(True Humble Object)

704


(Humble Object)

26


(Unfinished Test Assertion)

514

&

(Unfinished Test
Assertion)

21

(Verification
Method)

498

&
(Custom
Assertion)

21


, 
.

ACID
, .

(atomic).
.

(consistent). 
.

(independent). .

(durable). 
( !).

BDUF
(Big design up front)
.
,
.
(emergent design), .

DfT
. (design for testability).

DTO
(Data Transfer Object) [CJ2EEP].

EDD
. (exampledriven develpment).

. 784

785

(test automater)
( ), .
.

(root cause analysis)


,
. 
. ,
?, Toyota.

(annotation)
 . JUnit 4.0 
(Testcase Class) (Test Method).
NUnit .NET.

(anonymous inner class)


Java, .

(HardCoded Test Double).

(anti/pattern)
, , , 
. .

(asynchronous test)
, 
( ) .

, .

. 
, .

/
(aspect/oriented programming)
, 

, .

. 785

786

(atribute)
. xUnit .NET
(Testcase Class)
(Test Method). 
.

(class atribute)
,
, . xUnit
(Testcase Class).

(method atribute)
,
. 
xUnit
(Test Method).

/ (business logic)
, . 
,
, !

(block)
, . ( /
) ( Smalltalk Ruby).
.
. Java 

. C# .

(block closure)
. (block).

(inner class)
Java, . 
, 
.
(HardCoded Test Double).

. 786

787

(emergent design)
BDUF ( ). 

.

(built/in self/test)
,
, . .

(exercise SUT)
,
(fixture setup).

(depended/on component)
, .
.

.

(spike)
(, eXtreme Programming) 

.

(agile method)
( ,
), 
. eX
treme Programming, SCRUM, FeatureDriven Development (FDD) Dynamic Systems De
velopment Method (DSDM).
.

(front door)
. 
(back door).

. 787

788

(global variable)
, .
,
.

(boundary value)
,
(equivalence class). 
,
.

(dynamic binding)
, , 
, .
( )
, .
.
(static binding).  (polymorphism;
).

(liveware)
, . , 
,
.

(task)
. 
(user story) (feature), , 
.

(test debt)

. 
 . 
,
. , 
. , 
.

. 788

789

(substitutable dependency)
.
, 
(Test Double), ..
. 
, (Dependency Injection), $
(Dependency Lookup) (TestSpecific Subclass).

(smell)
. ,
. 
. .
.
(code smell), (behavior smell) /
(project smell). (test smell)
(code smell) (behavior smell).

(code smell)
, .

. ,
.
. (test smell), (behavior smell), (project smell)

(behavior smell)
, .
,
.

(project smell)
. , ,
(code smell) (behavior
smell). , 

.

(test smell)
, (test code).
, .

. 789

790

(pull)
.
,
, 
.
: ,
, ,
. 
, (
).

(test run)
(test) (test suite) ,
. 
.

(green bar)
(Graphical Test Runner)
.
, .
, (red bar).

(inversion of control //// IOC)


, 
. ( 
).
. 

(Test Double).

(incremental delivery)

(). 
. 
.
(feature) (user story).
,
. 
.

. 790

791

(incremental develpment)
,
. 
. 
( ).
(feature)
(user story).
, ,
.
.

(IDE)
, , , ()
.

(interface)
, , 
.
Java , . 

, .

(reflection)

. 
.

(test/driven bug fixing)


, 
, ,
. , 
.

(exploratory testing)
.
,
. . 
,
, .

. 791

792

(outgoing interface)
(, ), 
.
, ,
(indirect input) (indirect output). 
,
, .
,
(Mock Object), 
.

(iterative development)
.
, .
.

, ,
.
.

(equivalence class)
(test condition), 
,
. 
(boundary value), 
.

(production code)
, , /
(production). , 
.  (test code).

(test code)
, (
).

(component)
, 
.

. 792

793

. 
. 
. 
. , 
.

. Windows 
DLL . Java
Java (JAR).
Web.
( ) (
).
(Component Test), 
.

(constructor)

. , , 
new. $
(Complete Constructor Method) [SBPP] 
, . ,
.

(test context)
, 
.
RSpec
(Test Fixture) ( xUnit).
Context: a set fruits with
contents = {apple, orange, pear}
Exercise: remove orange from the fruits set
Verify: fruits set contents = {apple, pear}


.
.

(red bar)
(Graphical Test Runner)
.
, .
, .

. 793

794

(false negative)
, , 
. .
. (false positive).

(false positive)
, , 
. .

. , 
. , .
(, ), 
, .. . 
(
), 
.
. (false negative). 
Wikipedia Type I and type II errors.

(local variable)
, , . 
. 
, .


(fixture holding local variable)
(Test Method), 
(Test Fixture).
(Fresh Fixture),
(Inline Setup) (Delegated Setup).

(meta object)
, , .
, 
.

(meta test)
, . 
.

. 794

795

, ,
.

(accessor)
, , 
.

(class method)
, , .
_._ (, Assert.assertEquals(message,expected,
actual);) .
(instance method)
(instance variables), .. self this. Java 
(static method).
.

(setter)
, .

set (, setName).

(instance method)
, , .
. 
, .
.
.(). 
, (,
this.() self.). ,
.

(mixin)
, 
, ( ) .
(mixin) ( 
), .

, . 
 SCOOPS. ( SAMS
Teach Yourself C++ in 21 Days, 4th edition.)

. 795

796

(domain model)
, 
.
DomainDriven Design [DDD].

(module)
(, , )  
(, 
), .
, .
.

, 
(, ). 
. 
.

(unit test)
, . 
,
(
).
.
, 
.
.
(customer test),
.

(test suite)
, .

(fixture setup)

. , ( )
(Test Fixture) ( , test context), ,
(Test Fixture), /
(fixture setup).

. 796

797

(direct input)
, 
, . ,
, . 
, .

(direct output)
, 
, . ,
, , 
, , 
, .

(continuous integration)

.
. 

. .
, , 
, , , .
, .
.
.

(test failure)
, ,
.

(service object)
, .
.
.
(Service Facade) [CJ2EEP].
EJB Session Bean.

, (stateless)
, : 

.

. 797

798

(entity object)
, .
, . 
(service object), 
. EJB Entity Bean.

/ (object/relational mapping //// ORM)


, 
 ,
.

(expectated outcome)
. (Self
Checking Test) $
(Assertion Method).

(expectation)
. $
(Mock Object) (indirect output)
(Mock Object)
( ). .

(indirect input)
, , ,
() .
, ,
, .

.
(Test Stub).

(indirect output)
, ,
,
() . 
, 
.
(observation point)
.

. 798

799

(Mock Object),
.
. (outgoing interface)

(test maintainer)
( ),
.
. ,
.

(fixture teardown)
, 
.

(test error)
, . 
. ,
(, 
). ,
(test failure), 
.

(test package)

, (Testcase Class).

(class variable)
( ) . 
.
_
._ (, TestHelper.lineFeedCharacter;), ..
self this . Java
(static variable). 
.

. 799

800


(fixture holding class variable)
(Testcase Class), $
(Test Fixture).
(Shared Fixture).

(instance variable)
, , . 
. 
, .


(fixture holding instance variable)
(Testcase Object), $
(Test Fixture).
(Fresh Fixture), (Implicit Setup).

(fluent interface)
, 
. (Configuration Interface), 
JMock (Mock
Object), .

(polymorphism)
(dynamic binding).
.

(user story)
(incremental development) 
. :
, , , ,
[XP123].
(feature) 
. (task),
.

. 800

801

(presentation logic)
. 
, ,
..

(presentation layer)
[DDD, PEAA, WWW], 
.

(customer test)
, .
, .
, .
, 
. (, 
.)

(use case)

. (user
story) ,
.

(Hollywood principle)
:
, ( ).
(inversion of control  IOC).

(result verification)
(FourPhase Test)
() . 
(result verification).

(verify outcome)

( ,
) .
(FourPhase Test).

. 801

802

(acceptance test)
, ,
.
.
. 
, , .

(application programming interface)



. 
.
, .

(design for testability)


,
.
.

(production)
 ,
. , ,
, .

(The simplest thing that could possibly work ////


STTCPW)
" . ,

.

(procedure variable)
, ,
.
( ),
.
.
 
. (, C++) ()
, , 
.

. 802

803

(document/driven development)
, 
, . 
. 
, 
.

(behavior/driven development)
(testdriven development), 
.

xUnit. ,
.
(, , 
 ) 
.

(need/driven development)
,
,
(Mock Object), 
.
. 
, .
(storytest
driven development). , , 
(, ,
(Service Facade) [CJ2EEP]).

(example/driven develpment //// EDD)


, 
.
. 
.

(test/driven development)
, 
. 
.
(testfirst development) 


. 803

804

( /
, emergent design).
. (storytestdriven development).


(storytest/driven development //// STDD)
, 
.
,
.

Industrial XP [IXP].

(test/last development)
, (unit test) 
.
(testfirst development)
.
. 
( ,
).

(test/first development)
,
(unit test) . 
. /
(testdriven development)
. .
(unit test), /
(customer test) .

(regression test)
, .
, 

.

(test result)
(test) (test suite) ,
.

. 804

805

(retrospective)

. 

. ,
. 
 .

(refactoring)
. 
.
.
[Ref].

(garbage collection)
.
 
.

(synchronous test)
, ()
. , .
. 
. 
(asynchronous test), .

(test/specific equality)

.
.
, $
(Equality Pollution). $
(Equality Assertion) ,
(Obscure Test) (Test Code
Duplication). $
(Custom Assertion), .

(static variable)
Java  , 
, .

. 805

806

(class variable), 
Java.
( ).

(static method)
Java  , ( 
). 
(dynamic) ( (virtual) C++) . ,
(class method),
Java.
. .
Assert.assertEquals(message, expected, actual);

(static binding)
,
, . 
(dynamic binding).

(happy path)

. .
, .

(test case)
xUnit
(Testcase Class), (Test Suite Factory) 
(Test Method).

(test)
, 
.

Fit
Fit. (customer test).

(storytest)
,
(user story): , , [XPC]. 

. 806

807

,
.

(component test)
, .
.
, .

.
,
, (unit test),
.
 .

, 
, 
. 
xUnit.

(developer test)
(unit test),
, 
(eXtreme Programming).

(fault insertion test)


, ,
.
,
.
(Saboteur) .

(layer/crossing test)
,
(Back Door Manipulation).
.
(round-trip test).

(round/trip test)
, 
.  (layercrossing test).

. 807

808

, (manual test)
, , .
( $
, Scripted Test) .

(system under test //// SUT)


, . .
(unit test)
( ), ( ) ( )
(customer test) 
.
(dependedon component).

(test database)
, .
.

(test fixture)
xUnit  ,
. 
, ..
.
NUnit VbUnit  (Testcase Class).
Fit  , Fit
, (DataDriven Test).

(test fixture) ( NUnit)


NUnit ( VbUnit xUnit
.NET)  (Testcase Class), (Test
Method). , , [TestFixture].
xUnit , (Testcase Class)
(test context).  NUnit.
,
(Testcase Class per Fixture). 
, (Testcase Class per Class)
(Testcase Class per Feature),
. /
(test fixture) (
, test context), (Testcase Class)  , $
(Test Method) , .

. 808

809

(test fixture) ( xUnit)


xUnit  ,
, .. (test context). xUnit 
(Testcase Class), .
JUnit .
(FourPhase Test). 
(test fixture) .

Fit
Fit Adapter [GOF] Fit
, (DataDriven Test).

(interaction point)
, .
(control point) /
(observation point).

(observation point)
.
(interaction point)

.
. ,
.
, .

(control point)
,
.
, . 
(interaction point).
. 
,
, .

(function pointer)
C, C++, D 
. 
, ( Wikipedia [Wp]).

. 809

810

(legacy software)
, ,
, (Safety Net) $
(Fully Automated Tests).

(UML)
. UML 

, UML (
Wikipedia [Wp]).

(data access layer)


.
, .

(domain layer)
[DDD, PEAA, WWW], 
.
DomainDriven Design [DDD].

(test condition)
, .
:

S1

X,

S2.

(test success)
,
.

(assertion)
.
(Test Automation Framework) xUnit $
(Assertion Method), ,
.

. 810

811

(factory)
, , .

(test stripper)
,
.

(functional test)
. 


( 
) (unit) (component).
.

.

(feature)
, 
. $
(user story) .

(back door)
,
. 
, 
, , ,
(Test Double).
(front door): (application pro
gramming interface).

(black box)
, 
. 
.

. 811

812

(test reader)
, ,
. ,
( , Tests as Documentation).
,
.

(pattern)
.
, , ,
. (design pat
terns) .
.

(design pattern)
, 
.
. 
.
Design Patterns [GOF].

(eXtreme Programming)
, 
,
.

(endoscopic testing)
,
(Mock Object) [ET] .

(pattern language)
,
,
. , .
.
[APLfPW].

. 812


[AP]
AntiPatterns: Refactoring Software, Architectures, and Projects in Crisis
: John Wiley (1998)
ISBN: 0471197130
: (William J. Brown) .
, 
, 
.

[APLfPW]
A Pattern Language for Pattern Writing
Pattern Languages of Program Design 3 [PLoPD3], . 529574.
: AddisonWesley (1998)
: (Gerard Meszaros) (James Doble)


.
. 
, 
, .
.


PDF :
http://patternwritingpatterns.gerardmeszaros.com

HTML :
http://hillside.net/patterns/writing/patternwritingpaper.htm

. 813

814

[ARTRP]
Agile Regression Testing Using Record and Playback
http://AgileRegressionTestPaper.gerardmeszaros.com

: (Gerard Meszaros) (Ralph Bohnet)


XP/Agile Universe 2003 .

. 

OS/2 Windows.

[CJ2EEP]
Core J2EE Patterns, Second Edition: Best Practices and Design Strategies
J2EE.
: Prentice Hall (2003), (2004)
ISBN: 0131422464 (.), 5855822168 (.)
: (Deepak Alur), (Dan Malks) (John Crupi)
Enterprise Java
Beans (EJB), Java 2 Enterprise Edition.
(Session
Facade) [CJ2EEP].

[DDD]
Domain/Driven Design: Tackling Complexity in the Heart of Software
: AddisonWesley (2004)
ISBN: 0321125215
: (Eric Evans)

.
$
.
.

[ET]
Endo/Testing
http://www.connextra.com/aboutUs/mockobjects.pdf

: (Tim Mackinnon), (Steve Freeman)


(Philip Craig)
( XP 2000 ) 
(Mock Object, . 558) 
.

. 814

815

,
.
, . 
(Mock Object)
, . $
,
.

[FaT]
Frameworks and Testing
Proceedings of XP2002.
http://www.agilealliance.org/articles/roockstefanframeworks/file

: (Stefan Roock)
.
, 
, 
, 
, .

[FitB]
Fit for Developing Software
: AddisonWesley (2005)
ISBN: 0321269349
: (Rick Mugridge) (Ward Cunningham)

(DataDriven Test, . 322) .
, 
. .
, ,
. $
Fit , $
$
. Fit ,
FitNesse , .


Fit :
http://fit.c2.com

. 815

816

[GOF]
Design Patterns: Elements of Reusable Object/Oriented Software
$
: AddisonWesley (1995), (2005)
ISBN: 0201633612 (.), 5469011364 (.)
: (Erich Gamma), (Richard Helm),
(Ralph Johnson) (John Vlissides)

. 23 , 
 .
Composite, Factory Method Facade.

[HoN]
Hierarchy of Needs
Wikipedia [Wp]:
, $
(Abraham Maslow) 1943 $
. . $
, $
, .

: ,
,
.
. ,
$
. $
,
.

[IEAT]
Improving the Effectiveness of Automated Tests
http://FasterTestsPaper.gerardmeszaros.com

: (Gerard Meszaros), (Shaun Smith)


(Jennita Andrea)
XP2001.
,
.

. 816

817

[IXP]
Industrial XP
http://ixp.industriallogic.com

Industrial XP  
(eXtreme Programming), Industrial
Logic. , 
.

[JBrains]
JetBrains
http://www.jetbrains.com

JetBrains 
, ( ). 
, 
, , [Ref].

[JNI]
JUnit New Instance
http://www.martinfowler.com/bliki/JunitNewInstance.html


(Testcase Class, . 401) (Test Method,
. 378) JUnit .

[JuPG ]
JUnit Pocket Guide
: OReilly
ISBN: 0596007434
: (Kent Beck)
80
JUnit .
, ,
,
.

[LSD]
Lean Software Development : An Agile Toolkit
: AddisonWesley (2003)
ISBN: 0321150783
: (Mary Poppendieck) (Tom Poppendieck)

. 817

818

22 , 
.
. 
, , !

[MAS]
Mocks Arent Stubs
http://www.martinfowler.com/articles/mocksArentStubs.html

: (Martin Fowler)
(Mock Object,
. 559) (Test Stub, . 544). , 
:
.

[MRNO]
Mock Roles, Not Objects
OOPSLA 2004
: (Steve Freeman), (Tim Mackinnon),
(Nat Pryce) (Joe Walnes)
(Mock Object, . 558)
,
. 
. ACM :
http://portal.acm.org/ft_gateway.cfm?id=1028765&type=pdf

:
http://joe.truemesh.com/MockRoles.pdf

[PEAA]
Patterns of Enterprise Application Architecture

: AddisonWesley (2003), (2004)
ISBN: 0321127420 (.), 9785845905796 (.)
: (Martin Fowler)
,
. ,
.

. 818

819

[PiJV1]
Patterns in Java, Volume 1: A Catalog of Reusable Design Patterns
Illustrated with UML
JAVA. ,
UML
: Wiley Publishing (2002), (2004)
ISBN: 0471227293 (.), 5947350475 (.)
: (Mark Grand)
, Java.


http://www.markgrand.com/id1.html

[PLoPD3]
Pattern Languages of Program Design 3
: AddisonWesley (1998)
ISBN: 0201310112
: (Robert C. Martin), (Dirk Riehle)
(Frank Buschmann)
, Pattern Languages
of Programs (PLoP).

[POSA2]
Pattern/Oriented Software Architecture, Volume 2:
Patterns for Concurrent and Networked Objects
: Wiley & Sons (2000)
ISBN: 0471606952
: (Douglas Schmidt), (Michael Stal),
(Hans Robert) (Frank Buschmann)
PatternOriented Software Architecture (POSA). 
1996 . 17 
, : 
, , .

[PUT]
Pragmatic Unit Testing
: Pragmatic Bookshelf
ISBN: 0974514020 (In C# with NUnit)
ISBN: 0974514012 (In Java with JUnit)

. 819

820

: (Andy Hunt) (Dave Thomas)



. 
. ,

.

[RDb]
Refactoring Databases: Evolutionary Database Design
:
: AddisonWesley (2006), (2007)
ISBN: 0321293533 (.), 9785845911575 (.)
: (Pramodkumar J. Sadalage) (Scott W.
Ambler)

, . 

. , 
. 
:
http://www.ambysoft.com/books/refactoringDatabases.html

[Ref]
Refactoring: Improving the Design of Existing Code
.
: AddisonWesley (1999),  (2007)
ISBN: 0201485672 (.), 5932860456 (.)
: (Martin Fowler) .

,
.

[RTC]
Refactoring Test Code
XP2001.
: (Arie van Deursen), (Leon Moonen),
(Alex van den Bergh) (Gerard Kok)
. 
12 , 
. :
http://homepages.cwi.nl/~leon/papers/xp2001/xp2001.pdf

. 820

821

[RtP]
Refactoring to Patterns

: AddisonWesley (2005), (2006)
ISBN: 0321213351 (.), 9785845910875 (.)
: (Joshua Kerievsky)
( 
) (
). , 
,
( ).

, .

[SBPP]
Smalltalk Best Practice Patterns
: Prentice Hall (1997)
ISBN: 013476904X
: (Kent Beck)
, 
 . 
.
Smalltalk , $
. $
, , .
Smalltalk.
Smalltalk 
, , Smalltalk, 
 . 
,
Smalltalk.

[SCMP]
Software Configuration Management Patterns: Effective Teamwork,
Practical Integration
: AddisonWesley (2003)
ISBN: 0201741171
: (Steve Berczuk) (Brad Appleton)
, 


. 821

822

.
, .


http://www.scmpatterns.com
http://www.scmpatterns.com/book/pattern-summary.html

[SoC]
Secrets of Consulting: A Guide to Giving and Getting Advice Successfully
: Dorset House (1985)
ISBN: 0932633013
: (Gerald Weinberg)
, :
, .

[TAM]
Test Automation Manifesto
http://TestAutomationManifesto.gerardmeszaros.com

: (Shaun Smith) (Gerard Meszaros)


XP/Agile Universe 2003
. , 
xUnit .

[TDD/APG]
Test/Driven Development: A Practical Guide
: Prentice Hall (2004)
ISBN: 0131016490
: (David Astels)

.
Java.

[TDD/BE]
Test/Driven Development: By Example
:
: AddisonWesley (2003), (2003)
ISBN: 0321146530 (.), 5804600516 (.)
: (Kent Beck)

. 822

823


. 
$
(Test Automation Framework, . 332) Python.
. 

.
.

[TDD.Net]
Test/Driven Development in Microsoft .NET
: Microsoft Press (2004)
ISBN: 0735619484
: (James W. Newkirk) (Alexei A. Vorontsov)

, Microsoft.NET.

[TI]
Test Infected
http://junit.sourceforge.net/doc/testinfected/testing.htm

: (Eric Gamma) (Kent Beck)


Java Report Test
Infected  Programmers Love Writing Tests. , 
JUnit. 
xUnit .

[TPS]
Toyota Production System: Beyond Large/Scale Production
: Productivity Press (1995)
ISBN: 0915299143
: (Taiichi Ohno)
, justintime manufacturing, 
, , 
.
?.

[UTF]
Unit Test Frameworks: Tools for High/Quality Software Development
: OReilly (2004)
ISBN: 0596006896

. 823

824

: (Paul Hamill)
xUnit.

[UTwHCM]
Unit Testing with Hand/Crafted Mocks
http://refactoring.be/articles/mocks/mocks.html

: (Sven Gorts)
, $
(HandBuilt Test Double; . , Configurable Test
Double, . 571) , (Test Stub, . 544)
(Mock Object, . 559). .
$

. $
,
. $
.

[UTwJ]
Unit Testing in Java: How Tests Drive the Code
: Morgan Kaufmann (2003)
ISBN: 1558608680
: (Johannes Link) (Peter
Frohlich)

. , 
.

[VCTP]
The Virtual Clock Test Pattern
http://www.nusco.org/docs/virtual_clock.pdf

: (Paolo Perrotta)

(Responder), Virtual Clock Test Pattern (VCTP).
(Decorator) [GOF] , 
.
(HardCoded Test Stub)
(Configurable Test Stub).
.

. 824

825

, .
, $
.

[WEwLC]
Working Effectively with Legacy Code
: Prentice Hall (2005)
ISBN: 0131177052
: (Michael Feathers)

. 
(
), 
.

[Wp]
Wikipedia
Wikipedia:
(. Wikipedia) $$$$ $
, . $
, .

[WWW]
World Wide Web
[WWW] , . 
.

[XP123]
XP123
http://xp123.com

: (William Wake)
, 
.

. 825

826

[XPC]
XProgramming.com
http://xprogramming.com

: (Ron Jeffries)
, 
. 
, xUnit.

[XPE]
eXtreme Programming Explained, Second Edition: Embrace Change
: AddisonWesley (2005)
ISBN: 0321278658
: (Kent Beck)

. (ISBN: 0201616416) 12 
. 
. 
. 
. 
.

. 826


X
xUnit, 109; 110; 127; 133; 201
, 134

, 76

, 213; 215
, 217

, 192
, 162
, 211

, 163

, 212
, 73
, 230
, 254
, 243
, 257
, 230
, 230
, 251
, 230
, 243
, 70
, 277
, 289

. 827

, 267
, 285
, 264
, 287
, 285
, 69

, 300
, 303
, 298
, 296
, 67
, 131

, 87
, 353
, 106

, 203
, 134
, 77
, 119
, 106

, 351
, 63; 105

, 130; 206
, 210

828

, 134
, 183
, 166
, 175
, 175

, 211
, 169
, 209
, 188
, 370
, 187
, 193
, 62; 104

, 95
, 97
,
98
,
98

, 99

, 95
, 96

, 101
, 95
, 99
,
94
, 94
,
94
, 94
, 96
, 99
,
101
, 95

, 252
, 291
,
270

. 828

, 268
, 274
, 308
, 245
, 260
, 283
, 260

, 290
, 257
, 247
, 298
, 275
, 272
, 297; 301

, 299
, 249
, 307
, 306
, 253
, 235
, 303
, 271
, 239
,
272

, 265
, 305
, 256

, 255
, 304
, 288

, 287
, 288
, 292
, 283
, 248
, 297; 298;
301
, 232
, 252

, 234; 290
, 259
, 246
, 271

, 252
, 238
, 284
, 296; 301
, 283
, 280
, 278
, 282
, 279
, 231; 264
, 164
, 161

, 89
, 87

, 738

, 737

, 740
, 739
, 741
, 737
, 739
, 314

, 159
, 206
, 168

, 75
, 381
, 105; 371
, 381
, 369
, 106
, 106
, 370
, 370
, 104
, 106
, 185

. 829

829

, 111; 112; 130; 137


, 346
, 140
, 145
, 141
, 143
, 139
, 114; 139
, 115
, 116; 154
, 152
, 145
, 151
, 147
, 140; 156
, 211
, 183; 189; 197; 743
, 190
, 186
, 203
, 119

, 169
, 170

, 217

, 77
, 83
, 78
,
79
, 79
, 81

, 81
, 83
, 83
, 78
, 81
, 79
, 79

830

, 77
, 79
, 84

, 646
,
319
, 521
, 552
, 692
, 651
, 610
, 684
, 434
, 527
, 429

, 533
, 722
, 326
, 471
, 437
, 505
, 544
, 730
, 312
, 552
, 604
, 327

, 332
, 401
, 627

, 639
, 633
, 718
, 565
, 460
, 713
, 692
, 359
, 533
, 390
, 441

, 336

. 830

, 336
, 700
, 319
, 571

, 465
, 449
, 533
, 344
, 344
, 420
, 350
, 350
, 414
, 410
, 730
, 675
, 518
, 668
, 533
, 618
, 425
, 658
, 565
, 558
, 692

, 454
, 489
, 484
, 405
, 319

xUnit, 326
, 692
, 521
, 538
, 591
, 726
, 398
, 495

, 338
, 338
, 510
, 646
, 312

, 312
, 319

, 368
, 662
, 489
, 544
, 401
, 552
, 538
, 378
, 454
, 718
, 322

, 514

. 831

, 425
, 692
, 718

, 581
, 477
, 387

, 197

831

Unit:

..
..
..
.. , ..

. .
127055, . , . , . 43, . 1
20.08.2008. 70100/16
NewtonC .
. . . 67,08. .). . 49,1
3000 . 0000
CtP
. . .
197110, ), ., 15

. 832