Thư viện tri thức trực tuyến
Kho tài liệu với 50,000+ tài liệu học thuật
© 2023 Siêu thị PDF - Kho tài liệu học thuật hàng đầu Việt Nam

TDD for Android Time-tested tricks to do Test-Driven Development well
Nội dung xem thử
Mô tả chi tiết
Test-Driven Development: Extensive
Tutorial
Grzegorz Gałęzowski
This book is for sale at http://leanpub.com/tdd-ebook
This version was published on 2020-07-13
This is a Leanpub book. Leanpub empowers authors and publishers with the Lean Publishing
process. Lean Publishing is the act of publishing an in-progress ebook using lightweight tools
and many iterations to get reader feedback, pivot until you have the right book and build
traction once you do.
This work is licensed under a Creative Commons Attribution 3.0 Unported License
Tweet This Book!
Please help Grzegorz Gałęzowski by spreading the word about this book on Twitter!
The suggested hashtag for this book is #tddebookxt.
Find out what other people are saying about the book by clicking on this link to search for this
hashtag on Twitter:
#tddebookxt
Contents
Front Matter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
Dedications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
Thanks! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
About code examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
Notes for C# users . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
Notes for Java users . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
Part 1: Just the basics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
Motivation – the first step to learning TDD . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
What TDD feels like . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
Let’s get it started! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
The essential tools . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
Test framework . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
Mocking framework . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
Anonymous values generator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
It’s not (only) a test . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
When a test becomes something more . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
Taking it to the software development land . . . . . . . . . . . . . . . . . . . . . . . . . . 28
A Specification rather than a test suite . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
The differences between executable and “traditional” specifications . . . . . . . . . . . 30
Statement-first programming . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
What’s the point of writing a specification after the fact? . . . . . . . . . . . . . . . . . 31
“Test-First” means seeing a failure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
“Test-After” often ends up as “Test-Never” . . . . . . . . . . . . . . . . . . . . . . . . . . 37
“Test-After” often leads to design rework . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
Practicing what we have already learned . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
Let me tell you a story . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
Act 1: The Car . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
Act 2: The Customer’s Site . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
CONTENTS
Act 3: Test-Driven Development . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
Epilogue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
Sorting out the bits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
How to start? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
Start with a good name . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
Start by filling the GIVEN-WHEN-THEN structure with the obvious . . . . . . . . . . 66
Start from the end . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
Start by invoking a method if you have one . . . . . . . . . . . . . . . . . . . . . . . . . . 71
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
How is TDD about analysis and what does “GIVEN-WHEN-THEN” mean? . . . . . . 75
Is there a commonality between analysis and TDD? . . . . . . . . . . . . . . . . . . . . 75
Gherkin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
TODO list… again! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
What is the scope of a unit-level Statement in TDD? . . . . . . . . . . . . . . . . . . . . . 83
Scope and level . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
On what level do we specify our software? . . . . . . . . . . . . . . . . . . . . . . . . . . 84
What should be the functional scope of a single Statement? . . . . . . . . . . . . . . . . 84
Failing to adhere to the three rules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86
How many assertions do I need? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
Developing a TDD style and Constrained Non-Determinism . . . . . . . . . . . . . . . . 90
A style? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
Principle: Tests As Specification . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
First technique: Anonymous Input . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
Second technique: Derived Values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
Third technique: Distinct Generated Values . . . . . . . . . . . . . . . . . . . . . . . . . . 93
Fourth technique: Constant Specification . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
Summary of the example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
Constrained non-determinism . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
Specifying functional boundaries and conditions . . . . . . . . . . . . . . . . . . . . . . . 99
Sometimes, an anonymous value is not enough . . . . . . . . . . . . . . . . . . . . . . . 99
Exceptions to the rule . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
Rules valid within boundaries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105
Combination of boundaries – ranges . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111
Driving the implementation from Specification . . . . . . . . . . . . . . . . . . . . . . . . 113
Type the obvious implementation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113
Fake it (‘til you make it) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114
Triangulate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130
CONTENTS
Part 2: Object-Oriented World . . . . . . . . . . . . . . . . . . . . 131
On Object Composability . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133
Another task for Johnny and Benjamin . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133
A Quick Retrospective . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140
Telling, not asking . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141
Contractors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141
A Quick Retrospective . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147
The need for mock objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148
Composability… again! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148
Why do we need composability? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149
Pre-object-oriented approaches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149
Object-oriented programming to the rescue! . . . . . . . . . . . . . . . . . . . . . . . . . 151
The power of composition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152
Summary – are you still with me? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157
Web, messages and protocols . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158
So, again, what does it mean to compose objects? . . . . . . . . . . . . . . . . . . . . . . 158
Alarms, again! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163
Composing a web of objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164
Three important questions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164
A preview of all three answers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164
When are objects composed? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165
How does a sender obtain a reference to a recipient (i.e. how connections are made)? 166
Receive as a constructor parameter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166
Receive inside a message (i.e. as a method parameter) . . . . . . . . . . . . . . . . . . . 168
Receive in response to a message (i.e. as a method return value) . . . . . . . . . . . . . 169
Receive as a registered observer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171
Where are objects composed? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 178
Composition Root . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 178
Factories . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 182
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199
Interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 200
Classes vs interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 200
Events/callbacks vs interfaces – few words on roles . . . . . . . . . . . . . . . . . . . . . 201
Small interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 203
Protocols . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 208
Protocols exist . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 208
Protocol stability . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 210
CONTENTS
Craft messages to reflect the sender’s intention . . . . . . . . . . . . . . . . . . . . . . . 210
Model interactions after the problem domain . . . . . . . . . . . . . . . . . . . . . . . . . 211
Message recipients should be told what to do, instead of being asked for information 213
Most of the getters should be removed, return values should be avoided . . . . . . . . 216
Protocols should be small and abstract . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 223
Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 224
Single Responsibility Principle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 224
Static recipients . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 228
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 231
Object Composition as a Language . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 232
More readable composition root . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 232
Refactoring for readability . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 234
Composition as a language . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 243
The significance of a higher-level language . . . . . . . . . . . . . . . . . . . . . . . . . . 245
Some advice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 246
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 251
Value Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 252
What is a value object? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 252
Example: money and names . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 252
Value object anatomy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 258
Class signature . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 259
Hidden data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 259
Hidden constructor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 259
String conversion methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 265
Equality members . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 266
The return of investment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 267
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 269
Aspects of value objects design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 270
Immutability . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 270
Handling of variability . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 278
Special values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 282
Value types and Tell Don’t Ask . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 283
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 284
Part 3: TDD in Object-Oriented World . . . . . . . . . . . 285
Mock Objects as a testing tool . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 287
A backing example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 287
Interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 288
Protocols . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 288
Roles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 289
CONTENTS
Behaviors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 289
Filling in the roles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 290
Using a mock channel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 292
Mocks as yet another context . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 294
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 294
Test-first using mock objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 295
How to start? – with mock objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 295
Responsibility and Responsibility . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 295
Channel and DataDispatch one more time . . . . . . . . . . . . . . . . . . . . . . . . . . 296
The first behavior . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 296
Second behavior – specifying an error . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 306
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 310
Test-driving at the input boundary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 312
Fixing the ticket office . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 312
Initial objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 313
Bootstrap . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 316
Writing the first Statement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 316
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 338
Test-driving at the input boundary – a retrospective . . . . . . . . . . . . . . . . . . . . . 339
Outside-in development . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 339
Workflow specification . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 340
Data Transfer Objects and TDD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 342
Using a ReservationInProgress . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 346
Interface discovery and the sources of abstractions . . . . . . . . . . . . . . . . . . . . . 350
Do I need all of this to do TDD? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 350
What’s next? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 350
THIS IS ALL I HAVE FOR NOW. WHAT FOLLOWS IS RAW, UNORDERED MATERIAL THAT’S NOT YET READY TO BE CONSUMED AS PART OF THIS TUTORIAL 351
Mock objects as a design tool . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 391
Outside-in development . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 391
Worked example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 391
Programming by intention . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 391
Responsibility-Driven Design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 391
Specifying factories . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 391
What not to mock? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 392
Internals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 392
How to use value objects in Statements? . . . . . . . . . . . . . . . . . . . . . . . . . . . . 392
How to specify value objects? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 392
Terminal nodes in object graph . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 392
Guidance of test smells . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 393
Long Statements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 393
CONTENTS
Lots of stubbing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 393
Specifying private members . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 393
Mocking third party . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 393
Revisiting topics from chapter 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 394
Constrained non-determinism in OO world . . . . . . . . . . . . . . . . . . . . . . . . . . 394
Behavioral boundaries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 394
Triangulation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 394
Maintainable mock-based Statements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 395
Setup and teardown . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 395
Refactoring mock code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 396
Part 4: Application architecture . . . . . . . . . . . . . . . . . . . 397
On stable/architectural boundaries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 398
Ports and adapters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 399
Physical separation of layers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 399
What goes into application? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 400
Application and other layers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 400
What goes into ports? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 401
Data transfer objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 401
Ports are not a layer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 401
Part 5: TDD on application architecture level . . . . 402
Designing automation layer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 403
Adapting screenplay pattern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 403
Driver . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 403
Actors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 403
Data builders . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 403
Further Reading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 404
Motivation – the first step to learning TDD . . . . . . . . . . . . . . . . . . . . . . . . . . 404
The Essential Tools . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 404
Value Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 404
Front Matter
Dedications
Ad Deum qui laetificat iuventutem meam.
To my beloved wife Monika and our lovely son Daniel.
Thanks!
I would like to thank the following people (listed alphabetically by name) for valuable feedback,
suggestions, typo fixes and other contributions:
• Brad Appleton
• Borysław Bobulski
• Chris Kucharski
• Daniel Dec
• Daniel Żołopa (cover image)
• Donghyun Lee
• Łukasz Maternia
• Marek Radecki
• Martin Moene
• Michael Whelan
• Polina Kravchenko
• Rafał Bigaj
• Reuven Yagel
• Rémi Goyard
• Robert Pająk
• Wiktor Żołnowski
This book is not original at all. It presents various topics that others invented and I just picked
up. Thus, I would also like to thank my mentors and authorities on test-driven development and
object-oriented design that I gained most of my knowledge from (listed alphabetically by name):
• Amir Kolsky
• Dan North
• Emily Bache
• Ken Pugh
• Kent Beck
• Mark Seemann
• Martin Fowler
• Nat Pryce
• Philip Schwarz
• Robert C. Martin
• Scott Bain
• Steve Freeman
About code examples
Notes for C# users
The language of choice for code examples is C#, however, I made some exception from the typical
C# code conventions.
Dropping “I” from interface names
I am not a big fan of using ISomething as an interface name, so I decided to drop the I even
though most C# developers expect to see it. I hope you can forgive on this one.
Idiomatic C#
Most of the code in this book is not idiomatic C#. I tried to avoid properties, events, and most
modern features. My goal is to allow users of other languages (especially Java) to benefit from
the book.
Using underscore in field names
Some people like it, some not. I decided to stick to the convention of putting an underscore (_)
before a class field name.
Notes for Java users
The language of choice for the code examples is C#. That said, I wanted the book to be as
technology-agnostic as possible, to allow especially Java programmers to benefit from it. I tried
using a minimum number of C#-specific features and in several places even made remarks
targeted at Java users to make it easier for them. Still, there are some things I could not avoid.
That’s why I wrote up a list containing several of the differences between Java and C# that Java
users could benefit from knowing when reading the book.
Naming conventions
Most languages have their default naming conventions. For example, in Java, a class name is
written with pascal case (e.g. UserAccount), methods and fields are written with camel case,
e.g. payTaxes and constants/readonly fields are typically written in underscored upper-case (e.g.
CONNECTED_NODES).
C# uses pascal case for both classes and methods (e.g. UserAccount, PayTaxes, ConnectedNodes).
For fields, there are several naming conventions. I chose the one starting with underscore (e.g.
_myDependency). There are other minor differences, but these are the ones you are going to
encounter quite often.
About code examples 5
var keyword
For example brevity, I chose to use the var keyword in the examples. This keyword serves as
automatic type inference, e.g.
1 var x = 123; //x inferred as integer
Of course, this is no dynamic typing by any means – everything is resolved at compile time.
One more thing – var keyword can only be used when the type can be inferred, so occasionally,
you will see me declaring types explicitly as in:
1 List<string> list = null; //list cannot be inferred
string as keyword
C# has a String type, similar to Java. It allows, however, to write this type name as keyword,
e.g. string instead of String. This is only syntactic sugar which is used by default by the C#
community.
Attributes instead of annotations
In C#, attributes are used for the same purpose as annotations in Java. So, whenever you see:
1 [Whatever]
2 public void doSomething()
think:
1 @Whatever
2 public void doSomething()
readonly and const instead of final
Where Java uses final for constants (together with static) and read-only fields, C# uses two
keywords: const and readonly. Without going into details, whenever you see something like:
About code examples 6
1 public class User
2 {
3 // a constant with literal:
4 private const int DefaultAge = 15;
5
6 // a "constant" object:
7 private static readonly TimeSpan DefaultSessionTime
8 = TimeSpan.FromDays(2);
9
10 // a read-only instance field:
11 private readonly List<int> _marks = new List<int>();
12 }
think:
1 public class User {
2 //a constant with literal:
3 private static final int DEFAULT_AGE = 15;
4
5 //a "constant" object:
6 private static final Duration
7 DEFAULT_SESSION_TIME = Duration.ofDays(2);
8
9 // a read-only instance field:
10 private final List<Integer> marks = new ArrayList<>();
11 }
A List<T>
If you are a Java user, note that in C#, List<T> is not an interface, but a concrete class. it is
typically used where you would use an ArrayList.
Generics
One of the biggest difference between Java and C# is how they treat generics. First of all, C#
allows using primitive types in generic declarations, so you can write List<int> in C# where in
Java you have to write List<Integer>.
The other difference is that in C# there is no type erasure as there is in Java. C# code retains all
the generic information at runtime. This impacts how most generic APIs are declared and used
in C#.
A generic class definition and creation in Java and C# are roughly the same. There is, however,
a difference on a method level. A generic method in Java is typically written as: