The document discusses test-driven development (TDD). TDD involves writing tests before writing code to specify desired functionality, then writing just enough code to pass each test. This process of red-green-refactor evolves the system design through tests. TDD results in decoupled, well-designed code and provides benefits like confidence, documentation, and safe refactoring. The document also provides tips for writing better tests, such as keeping tests small, expressive, isolated, and automated.
[TestFixture]
public class OddNumberFilterTest{
[Test]
public void FiltersOutOddNumbers() {
OddNumberFilter filter = new OddNumberFilter();
int [] numbers = new int [] { 3, 4 };
int [] evenNumbers = filter.Filter(numbers);
Assert.That(evenNumbers, Has.Count(1));
Assert.That(evenNumbers, Has.Member(4));
Assert.That(evenNumbers, Has.No.Member(3));
}
}
[email protected]
Specify What Software Should Do...
Then
When
Given
public class OddNumberFilter{
public int [] Filter (params int [] numbers)
{
List<int> evenNumbers = new List<int>();
foreach (int number in numbers)
{
if (number % 2 == 0)
{
evenNumbers.Add(number);
}
}
return evenNumbers.ToArray();
}
}
[email protected]
Write Enough Code To Pass The
Specification...
[email protected]
General Test Structure
Setupthe Givens
(Context in which the Test runs)
Then verify the Assertions
(State or Behavior verifications)
Exercise the Whens
(Perform the actual operation)
Arrange
Assert
Act
11.
[TestFixture]
public class NumberFilterTest{
[Test]
public void FiltersOddNumbers() {
OddNumberFilter filter = new OddNumberFilter();
int [] numbers = new int [] { 3, 4 };
int [] evenNumbers = filter.Filter(numbers);
Assert.That(evenNumbers, Has.Count(1));
Assert.That(evenNumbers, Has.Member(4));
Assert.That(evenNumbers, Has.No.Member(3));
}
[email protected]
Add New Feature:
Filter-out Non-Primes
12.
[TestFixture]
public class NumberFilterTest{
[Test]
public void FiltersOddNumbers() {
OddNumberFilter filter = new OddNumberFilter();
int [] numbers = new int [] { 3, 4 };
int [] evenNumbers = filter.Filter(numbers);
Assert.That(evenNumbers, Has.Count(1));
Assert.That(evenNumbers, Has.Member(4));
Assert.That(evenNumbers, Has.No.Member(3));
}
[Test]
public void FiltersNonPrimes() {
NonPrimesFilter filter = new NonPrimesFilter();
int [] numbers = new int [] { 4, 5 };
int [] primeNumbers = filter.Filter(numbers);
Assert.That(primeNumbers, Has.Count(1));
Assert.That(primeNumbers, Has.Member(5));
Assert.That(primeNumbers, Has.No.Member(4));
}
}
[email protected]
Add New Feature:
Filter-out Non-Primes
13.
[TestFixture]
public class NumberFilterTest{
[Test]
public void FiltersOddNumbers() {
OddNumberFilter filter = new OddNumberFilter();
int [] numbers = new int [] { 3, 4 };
int [] evenNumbers = filter.Filter(numbers);
Assert.That(evenNumbers, Has.Count(1));
Assert.That(evenNumbers, Has.Member(4));
Assert.That(evenNumbers, Has.No.Member(3));
}
[Test]
public void FiltersNonPrimes() {
NonPrimesFilter filter = new NonPrimesFilter();
int [] numbers = new int [] { 4, 5 };
int [] primeNumbers = filter.Filter(numbers);
Assert.That(primeNumbers, Has.Count(1));
Assert.That(primeNumbers, Has.Member(5));
Assert.That(primeNumbers, Has.No.Member(4));
}
}
[email protected]
Add New Feature:
Filter-out Non-Primes
Duplication
of Concept
14.
[TestFixture]
public class NumberFilterTest{
[Test]
public void FiltersOddNumbers() {
OddNumberFilter filter = new OddNumberFilter();
int [] numbers = new int [] { 3, 4 };
int [] evenNumbers = filter.Filter(numbers);
Assert.That(evenNumbers, Has.Count(1));
Assert.That(evenNumbers, Has.Member(4));
Assert.That(evenNumbers, Has.No.Member(3));
}
[Test]
public void FiltersNonPrimes() {
NonPrimesFilter filter = new NonPrimesFilter();
int [] numbers = new int [] { 4, 5 };
int [] primeNumbers = filter.Filter(numbers);
Assert.That(primeNumbers, Has.Count(1));
Assert.That(primeNumbers, Has.Member(5));
Assert.That(primeNumbers, Has.No.Member(4));
}
}
[email protected]
Add New Feature:
Filter-out Non-Primes
Duplication
of Concept
Duplication
of Concept
[email protected]
TDD Rhythm Flowchart
Writejust enough
Code to compile
Refactor Code
Pass the Test
(GREEN)
Fail the Test
(RED)
Write just enough
Code to pass the test
Specify what
the software
should do
Pass the Test
(GREEN)
22.
So, TDD isabout…
Analyzing what little you actually need to
do and how cleanly you can do it!
Carving design of your code a unit test at a
time.
23.
[email protected]
Write Tests BeforeWriting Code
! Focuses the mind (and the development
process)
" Deliver only what is absolutely necessary.
" System so developed does exactly what it
needs to do and no more.
" Need not code for future
! YAGNI (You Ain’t Gonna Need It!)...no gold plating!
24.
[email protected]
TDD is aDesign Technique
! Makes you think in terms of Object
behavior.
" How client is going to interact with the object.
! Outside-In
! Object so created is “consumer aware”
" What Object provides and needs from
environment.
" Traditional OOD focuses only on Object’s
Implementation
! Inside-Out
25.
[email protected]
TDD results ina Decoupled Design
! Favors Composition over Inheritance.
" Relies on dependency injection for
collaborators.
! Avoids tight coupling to global objects
" Singletons mix static and state.
" Makes design untestable.
! Many small, loosely coupled classes.
! Makes you think of inter-object
interactions in terms of interfaces.
" Promotes Programming to Super-Types and not
Concretes.
26.
Listening to theTests
! A difficulty in implementing a new
feature is usually a symptom that the
design can be improved.
" Ask why is it difficult to test? Don’t just think
how do I test this?
! TDD is not just about functionality, it gives
us feedback on code’s internal quality.
" How is the coupling and cohesion?
" Are we preserving encapsulation?
" What about implicit or explicit dependencies?
Source: Growing Object-Oriented Software, Guided by Tests
27.
Listening to theTests
! Check continuously, observe and
meditate on the tests, they might tell you
something.
! The idea is to let the test drive the design.
That’s why it is called Test Driven Design.
Source: Growing Object-Oriented Software, Guided by Tests
28.
[email protected]
Benefits of TDD
!Test-a-little and build-a-little gives
confidence
" Green bar gives you confidence
" Reduces fear of change
! Documentation
" Provides starting point to understand code
functionality
! Safety Net
" Checks Regression
" Supports Refactoring
29.
[email protected]
Benefits of TDD
!Effort
" Reduces effort to final delivery
" Writing tests is more productive
! Predictable
" Tells me when am I done
" Continuous Success Vs Illusive Success
! Immediate Feedback
" Makes failures shine at you
30.
[email protected]
Costs of TDD
Claim:It is too much work to write tests!
Rebut: I’d say “are you looking to create a speculative
design?”, “do you want to sleep with a debugger?”
Claim: Tests themselves are code, we need to maintain them,
that’s overhead!
Rebut: I’d say “do you prefer maintaining a big bug list?”
Claim: I have to spend time re-orient my thinking!
Rebut: I’d say “Just as with any skill, you need to allow some
time to apply this effectively.”
[email protected]
Better Test Practices
!Tests must be Small.
" Easy to understand
" They do not break when other parts of the code are
changed.
" One behavioral-assert per test.
! Tests must be Expressive.
" Test code should communicate its intent.
" It should not take more than 2 minutes for readers to
understand what is going on.
! Tests must be Maintainable.
" When a test breaks, what it contains should be easiest to
fix.
33.
[email protected]
Better Test Practices
!Tests must execute Fast.
" Slow running tests increase Build Viscosity.
! Tests are Specifications, not Verifications.
" Do not verify whether the code does what its supposed
to do correctly.
" Specify what should the code do to function correctly.
! Tests should talk the Domain Language.
" Communicate the behavior under test and not how the
system implements that behavior.
" Improves Communication with Non-Technical Members
on the team.
" Developers can understand domain faster.
34.
[email protected]
Better Test Practices
!Tests must run at will.
" Able to write and execute tests without
worrying about how to execute them.
! Tests must be Isolated
" Very little set-up and minimum collaborators.
! Tests must be Thorough
" Test all behavior, not methods.
35.
[email protected]
Better Test Practices
!Tests must be Automated.
" Write them such that methods on objects are invoked by
code rather than by hand.
! Tests must be Self-Verifiable.
" Setup test expectations and compare outcome with
expectations for verdicts.
! Tests must be Repeatable.
" Executing the same test several times under the same
conditions must yield same results.
36.
[email protected]
JUnit/NUnit Better TestPractices
! Test anything that could possibly break.
! Make testing exceptional scenarios easy to read.
! Always explain failure reason in Assert calls.
! Test should usually improve the design of the
code.
! For JUnit Tests
" Make Test code reside in same packages, but
different directories.
! For NUnit Tests
" Make Test code reside in separate project from
source project, in same namespace.
37.
[email protected]
Flavors of Tests
!Object Tests (Unit or Programmer Tests)
" Tests behavior of single object at a time.
! Integration Tests
" Tests collaboration of a number of objects (how they talk
to each other)
" Complex fixtures
" More brittle
! End-to-End Tests
" Thoroughly test the entire system from end-to-end.
38.
[email protected]
Unit Testing Frameworks
!xUnit framework for Unit Testing
" JUnit/TestNG for Java
" NUnit/MbUnit for C#
" cppUnit for C++
" pyUnit for Python
" …and tons of more Unit Testing frameworks.
[email protected]
References
! JUnit Recipes
"J. B. Rainsberger
! JUnit In Action
" Vincent Massol
! Agile Java
" Jeff Langr
! Test-Driven Development Rhythm
" Gunjan Doshi
! Agile Principles, Patterns, and
Practices in C#
" Robert C. Martin, Micah Martin
! xUnit Test Patterns
" Gerard Meszaros
! On TDD (InfoQ): How Do We
Know When We’re Done?
" Steve Freeman
! Growing Object-Oriented
Software, Guided by Tests
" Steve Freeman and Nat Pryce
! 10-Ways-to-Better-Code (InfoQ)
" Neal Ford
! Refactoring Away Duplicated Logic
Creates a Domain Specific
Embedded Language for Testing
" Nat Pryce
! Jay Field’s Blog Entry
" http://blog.jayfields.com/
2007/06/testing-inline-setup.html