Test-Driven Development
Nov 15, 2014
Test-Driven Development
First, Some History
Plan-Do-Check-Act
0Originally called Plan-Do-Study-Act0Created by Walter Shewhart at Bell Labs during the
1930s
Iterative & Incremental Development
0The X-15 program in the 1950s used IID
Test-First in the Swinging 60s
0X-15 team members seeded Project Mercury0 Time-boxed half-day iterations0 Tests were written first0 Reviews after each iteration0 Top-down development with stubs
We were doing incremental development as early as 1957, in Los Angeles, under the direction of Bernie Dimsdale [at IBM’s Service Bureau Corporation]. He was a
colleague of John von Neumann, so perhaps he learned it there, or assumed it as totally natural. I do remember Herb Jacobs (primarily, though we all participated)
developing a large simulation for Motorola, where the technique used was, as far as I can tell, indistinguishable from XP.
When much of the same team was reassembled in Washington, DC in 1958 to develop Project Mercury, we had our own machine and the new Share Operating System,
whose symbolic modification and assembly allowed us to build the system incrementally, which we did, with great success.
Project Mercury was the seed bed out of which grew the IBM Federal Systems Division. Thus, that division started with a history and tradition of incremental development.
All of us, as far as I can remember, thought waterfalling of a huge project was rather stupid, or at least ignorant of the realities… I think what the waterfall description did
for us was make us realize that we were doing something else, something unnamed except for “software development.”
Gerald M. Weinberg
Waterfall in the 1970s & 80s
0Blame the DoD and the CMMI
Other stuff was happening
0Object-orientation0 Simula from the late 60s0 Smalltalk in the 70s at Xerox PARC
0Software distribution
Into the 1990s
0UML evolves0www arrives
What RUP was meant to be
What RUP actually was
RAD elaboration in the 90s
XP arrives
Test-Driven is in XP
Tests are Feedback in XP
Agile arrives
Agile is just XP, rebadged
and a Manifesto
The Philosophy of TDD
The Testing Game
0Red:0 “Write a failing test”
0Green:0 “Pass the failing test”
0Refactor0 “Clean the implementation”
Write a failing test
0To know what test to write, you must:0 Analyze your problem0 Design your solution0 Code intentionally
0To dislike “Big Upfront Design” is not to dislike design
Agile Problem Analysis
0 System Metaphor0 Arises from the Architectural Spike0 A simple design with the defining quality of explaining the
system design without reference to documents0 User Experience
0 Arises from the set of all user stories0 Provides a canvas onto which individual stories can be
painted0 User Story
0 Describes a specific user expectation0 Provides the functional constraints of implementation
User Stories
0A user story comprises one or more sentences in the everyday or business language of the end user that captures what the user wants to achieve
Agile Solutions
0 “Walk the solution”: for each user story0 Understand how this fits into the user experience0 Understand where the necessary functional
implementation goes in the architecture0 Design the functional implementation
Goldilocks Design
0Design only what you need0 avoid YAGNI (You Ain’t Gonna Need It)
0Reuse existing implementation0 be DRY (Don’t Repeat Yourself)
0Prefer sketched designs over definitive design0 allow TDD to be part of your design process
0Don’t experiment in code0 use spikes where necessary
First Exercise
0Brainstorm a realistic candidate application0Write a small set of user stories0Elaborate a user experience0Articulate a system metaphor0Time limit: one hour
Analysis & Design
0There are a variety of approaches to functional analysis and implementation design
0The most commonly used are:0 The UML0 CRC Cards0 Design Patterns0 Linguistics & Semantics0 Personas0 Storyboards
UML
0The UML (Unified Modeling Language)0 It has the advantage that many developers have at least
some familiarity0 It has the disadvantage of significant complexity0 Most agile practitioners use ‘sketch’ UML, typically on a
whiteboard, in order to convey a mental model of a proposed solution
0 Be indicative, not definitive
UML Use Case Diagram
0Describes the functionality provided by a system in terms of actors and their goals represented as use cases
UML Activity Diagram
0Used to describe the business and operational step-by-step workflows of components in a system
UML Sequence Diagram
0Shows how processes operate with one another and in what sequence
UML Class Diagram
0Describes the structure of a system by showing the system's classes, their attributes, methods, and the relationships among the classes
CRC Cards
0 Class Responsibility Collaboration cards are a brainstorming tool, proposed by Ward Cunningham and Kent Beck
0 They are typically used when determining which classes are needed and how they will interact
0 CRC cards are usually created from index cards on which are written:0 The class name0 Any base or derived classes (if applicable)0 The responsibilities of the class0 The names of other classes with which the class will
collaborate to fulfil its responsibilities
CRC Card
Design Patterns
0A general reusable solution to a commonly occurring problem within a given context
0A design pattern is not a finished design that can be transformed directly into code; it is a description or template for how to solve a problem that can be used in many different situations
0Typically show relationships and interactions between classes or objects, without specifying the final application classes or objects that are involved
Some Creational Patterns
0 Factory method0 Define an interface for creating an object, but let derived classes decide which
class to instantiate0 Lazy initialization
0 Tactic of delaying the creation of an object, the calculation of a value, or some other expensive process until the first time it is needed
0 Object pool0 Avoid expensive acquisition and release of resources by recycling objects that
are no longer in use0 Resource acquisition is initialization
0 Ensure that resources are properly released by tying them to the lifespan of suitable objects
0 Singleton0 Ensure a class has only one instance, and provide a global point of access to it
Some Structural Patterns
0 Adapter0 Convert the interface of a class into another interface clients
expect0 Bridge
0 Decouple an abstraction from its implementation allowing the two to vary independently
0 Facade0 Provide a unified interface to a set of interfaces in a subsystem
0 Proxy0 Provide a surrogate or placeholder for another object to
control access to it
Some Behavioural Patterns
0 Chain of responsibility0 Avoid coupling the sender of a request to its receiver by giving
more than one object a chance to handle the request0 Command
0 Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations
0 Iterator0 Provide a way to access the elements of an aggregate object
sequentially without exposing its underlying representation0 Null object
0 Avoid null references by providing a default object
Linguistics & Semantics
0Using the meanings and relationships of words and phrases employed in the user stories and other material to construct a language map of the problem domain
0Especially useful when dealing with ‘expert’ systems
Personas
0Fictional characters created to represent the different user types within a targeted demographic, attitude and/or behaviour set that might use a site, brand or product in a similar way
Storyboards
0A technique borrowed from the film industry
0Shows the user experience in sequence
Second Exercise
0Take one or more of the user stories from the first exercise and apply a selection of the analysis and design techniques
0Draw up a list of the strengths and weaknesses of the techniques in relation to these particular user stories
0Time limit: one hour
Testing Frameworks
0 MSTest0 Built-in to Visual Studio
0 Pex0 Experimental white-box testing from MS Research
0 NUnit0 Early open source port of JUnit for .net
0 MbUnit0 Another open source framework
0 xUnit0 Open source reset of NUnit
0 SpecFlow0 Open source behaviour-driven-development framework
Arrange, Act, Assert
0The default pattern for unit tests1. Arrange all necessary preconditions and inputs2. Act on the object or method under test3. Assert that the expected results have occurred
Test naming conventions
0Ad-hoc0 Anything goes
0Behavioural0 Tests are named according to the behaviour under test0 Good fit for collaboration tests (distinct from unit tests)
procedure CustomerPaysInChequeToCurrentAccount;
0Contractual0 Names follow the unit contract under test
http://alandean.blogspot.com/2011/11/unit-test-naming-convention.html
DUnit Assertions
0 Fundamentals0 Assert(…)0 Check(…)0 CheckSame(…)0 CheckEquals(…) or CheckNotEquals(…)0 CheckNull(…) or CheckNotNull(…)0 Fail(…)0 FailNotSame(…)0 FailEquals(…) or FailNotEquals(…)
0 Errors0 NotSameErrorMessage(…)0 EqualsErrorMessage(…) or NotEqualsErrorMessage(…)
Diagnostics
0OutputDebugString(…)
TDD at the Keyboard
1. Add a new test2. Run all tests and see if the new one fails3. Write some code4. Run all tests and see them succeed5. Refactor code6. Repeat
Exercise 3
0Create a solution with two class libraries:0 TicTacToe0 TicTacToe.Facts
0Add a reference to xUnit.net in the Facts library0 http://nuget.org/
0Use TDD to implement Tic-Tac-Toe0 http://gojko.net/2009/08/02/tdd-as-if-you-meant-it-revisited/
0Time limit: one hour
Refactoring Code
0 A disciplined technique for restructuring an existing body of code, altering its internal structure without changing its external behaviour
0 Usually motivated by noticing a code smell0 There are two general categories of benefits to the activity of refactoring
0 Maintainability0 It is easier to fix bugs because the source code is easy to read and the
intent of its author is easy to grasp0 This might be achieved by reducing large monolithic routines into a set of
individually concise, well-named, single-purpose methods0 It might be achieved by moving a method to a more appropriate class, or
by removing misleading comments.0 Extensibility
0 It is easier to extend the capabilities of the application if it uses recognizable design patterns, and it provides some flexibility where none before may have existed
Refactoring Techniques0 Techniques that allow for more abstraction
0 Encapsulate Field: force code to access the field with getter and setter methods0 Generalize Type: create more general types to allow for more code sharing0 Replace Conditional with Polymorphism: move each leg of the conditional to an overriding
method in a derived class and make the original method abstract0 Techniques for breaking code apart into more logical pieces
0 Extract Method: turn part of a larger method into a new method0 Extract Class: moves part of the code from an existing class into a new class
0 Techniques for improving names and location of code0 Move Method or Field: move to a more appropriate class0 Rename Method or Field: changing the name to one that better reveals its purpose0 Pull Up: move to a base class0 Push Down: move to a derived class
0 Longer lists0 http://martinfowler.com/refactoring/catalog/index.html0 http://docwiki.embarcadero.com/RADStudio/en/Refactoring_Applications_Index
Exercise 4
0Create a solution with two class libraries:0 RomanNumerals0 RomanNumerals.Facts
0Use TDD to solve the problem0 https://sites.google.com/site/tddproblems/all-problems-1/Roman-number-conversion
0Refactor the code as you go0Time limit: one hour
Test Doubles
0 Objects that mimic real objects for testing purposes0 Dummies
0 Have no behaviour or throw exceptions0 Stubs
0 Provide the behaviour of a real object0 Spies
0 Record activity for later verification0 Mocks
0 Define the expected activity before the test is run0 Fakes
0 Employ a simpler implementation such as an in-memory database
0 See also http://martinfowler.com/articles/mocksArentStubs.html
Mocking Frameworks
0Visual Studio doesn’t have one built-in0Moles
0 Experimental framework from MS Research0Open source
0 Moq, NCrunch, NMock2, Rhino Mocks, fakeiteasy0Commercial
0 TypeMock Isolator, JustMock
SOLID Code
0 Single Responsibility principle0 An object should have only a single responsibility
0 Open/Closed principle0 Objects should be open for extension, but closed for modification
0 Liskov Substitution principle0 Objects should be replaceable with instances of their derived types
without altering correctness0 Interface Segregation principle
0 Many client specific interfaces are better than one general purpose interface
0 Dependency Inversion principle0 Depend upon abstractions; do not depend upon concretions
Inversion of Control
0Microsoft0 Unity0 Common Service Locator
0Open source0 Castle Windsor, Autofac, StructureMap, Ninject, LinFu
Exercise 5
0Create a solution with two class libraries:0 Translator0 Translator.Facts
0Use TDD to solve the problem0 TODO
0Refactor the code as you go0Use test doubles to isolate tests from dependencies
and resources to achieve SOLID code0Time limit: two hours