1. Avatars of TDD
Rule of Diversity
Distrust all claims for “One True Way”
Licensed Under Creative Commons by Naresh Jain
Friday, September 18, 2009 1
2. Overview
TDD Rhythm - Test, Code, Refactor
Licensed Under Creative Commons by Naresh Jain
Friday, September 18, 2009 2
3. Overview
Add a Test
TDD Rhythm - Test, Code, Refactor
Licensed Under Creative Commons by Naresh Jain
Friday, September 18, 2009 2
4. Overview
Add a Test
Run the Test
TDD Rhythm - Test, Code, Refactor
Licensed Under Creative Commons by Naresh Jain
Friday, September 18, 2009 2
5. Overview
Add a Test
Pass
Run the Test
TDD Rhythm - Test, Code, Refactor
Licensed Under Creative Commons by Naresh Jain
Friday, September 18, 2009 2
6. Overview
Add a Test
Pass
Run the Test
Fail
TDD Rhythm - Test, Code, Refactor
Licensed Under Creative Commons by Naresh Jain
Friday, September 18, 2009 2
7. Overview
Add a Test
Pass
Run the Test
Fail
TDD Rhythm - Test, Code, Refactor
Make a little
change
Licensed Under Creative Commons by Naresh Jain
Friday, September 18, 2009 2
8. Overview
Add a Test
Pass
Run the Test
Fail
TDD Rhythm - Test, Code, Refactor
Make a little
change
Run the Test
Licensed Under Creative Commons by Naresh Jain
Friday, September 18, 2009 2
9. Overview
Add a Test
Pass
Run the Test
Fail
TDD Rhythm - Test, Code, Refactor
Make a little
change
Fail
Run the Test
Licensed Under Creative Commons by Naresh Jain
Friday, September 18, 2009 2
10. Overview
Add a Test
Pass
Run the Test
Fail
TDD Rhythm - Test, Code, Refactor
Make a little
change
Fail
Run the Test
Pass
Licensed Under Creative Commons by Naresh Jain
Friday, September 18, 2009 2
11. Overview
Add a Test
Pass
Run the Test
Fail
TDD Rhythm - Test, Code, Refactor
Make a little
change
Fail
Run the Test
Pass
Refactor
Licensed Under Creative Commons by Naresh Jain
Friday, September 18, 2009 2
12. Overview
Add a Test
Pass
Run the Test
Fail
TDD Rhythm - Test, Code, Refactor
Make a little
change
Fail
Run the Test
Pass
Refactor
Licensed Under Creative Commons by Naresh Jain
Friday, September 18, 2009 2
13. Overview
Add a Test
Pass
Run the Test
Fail
TDD Rhythm - Test, Code, Refactor
Make a little
change
Fail
Run the Test
Pass
Refactor
Licensed Under Creative Commons by Naresh Jain
Friday, September 18, 2009 2
14. Overview
Add a Test
Pass
Run the Test
Fail
TDD Rhythm - Test, Code, Refactor
Make a little
change
Fail
Run the Test
Pass
Refactor
Licensed Under Creative Commons by Naresh Jain
Friday, September 18, 2009 2
15. Simple
easy to understand, deal with, use, etc.: a simple matter; simple tools.
not elaborate or artificial; plain: a simple style.
not ornate or luxurious; unadorned: a simple gown.
unaffected; unassuming; modest: a simple manner.
not complicated: a simple design.
not complex or compound; single.
occurring or considered alone; mere; bare: the simple truth; a simple fact.
free of deceit or guile; sincere; unconditional: a frank, simple answer.
common or ordinary: a simple soldier.
not grand or sophisticated; unpretentious: a simple way of life.
humble or lowly: simple folk.
inconsequential or rudimentary.
Licensed Under Creative Commons by Naresh Jain
Friday, September 18, 2009 3
16. What is Simple Design?
A design that allows you to keep moving forward
with least amount of resistance
Licensed Under Creative Commons by Naresh Jain
Friday, September 18, 2009 4
17. Embrace Simple Design
Licensed Under Creative Commons by Naresh Jain
Friday, September 18, 2009 5
18. Embrace Simple Design
Licensed Under Creative Commons by Naresh Jain
Friday, September 18, 2009 5
19. Embrace Simple Design
Licensed Under Creative Commons by Naresh Jain
Friday, September 18, 2009 5
20. Simple Design?
easy to understand, deal with: communicates its intent.
not elaborate or artificial; plain: crisp and concise
not ornate or luxurious; unadorned: minimalistic; least possible
components (classes and methods).
unaffected; unassuming; modest: does not have unanticipated side-effects.
not complicated: avoids unnecessary conditional logic.
not complex or compound; single: just does one thing and does it well.
occurring or considered alone; mere; bare: to the point.
Licensed Under Creative Commons by Naresh Jain
Friday, September 18, 2009 6
21. Simple Design? ...
free of deceit or guile; sincere; unconditional: abstracts implementation
from intent, but does not deceive someone by concealing or
misrepresenting the actual concept.
common or ordinary: built on standard patterns which are well
understood.
not grand or sophisticated; unpretentious: fulfills today’s needs without
unnecessary bells and whistles (over-engineering).
humble or lowly.
inconsequential or rudimentary: does not draw your attention to
unnecessary details; achieves good abstractions
Licensed Under Creative Commons by Naresh Jain
Friday, September 18, 2009 7
22. Summary
Do the Simplest thing that could possibly work
YAGNI
Design Patterns.
Code Smells (Code Screams)
Unix Programming Philosophy
OO Design principles - SOLID, DRY, TDA
Functional Programming - Immutability and Side effect free
Simple Design and TDD go hand in hand
Licensed Under Creative Commons by Naresh Jain
Friday, September 18, 2009 8
23. Why bother about TDD?
Confident & Feedback
Design & Code minimalistic and clean
Decoupling and Testable
Safety net of executable, living, up-to-date specification
Learning by listening to your code
Slow down and think
Communicate my design choices
Efficient: Debugging and Manual Testing
Maintain focus
Reduce Wastage: Hand-overs
Licensed Under Creative Commons by Naresh Jain
Friday, September 18, 2009 9
24. Before you take the plunge...
Licensed Under Creative Commons by Naresh Jain
Friday, September 18, 2009 10
25. Before you take the plunge...
System Metaphor
Election Metaphor
‘Google Search Engine’ Metaphor
Licensed Under Creative Commons by Naresh Jain
Friday, September 18, 2009 10
26. Before you take the plunge...
System Metaphor
Election Metaphor
‘Google Search Engine’ Metaphor
Thin Slice
ProTest - Dependency Voter
Profile Picture
Licensed Under Creative Commons by Naresh Jain
Friday, September 18, 2009 10
27. Before you take the plunge...
System Metaphor
Election Metaphor
‘Google Search Engine’ Metaphor
Thin Slice
ProTest - Dependency Voter
Profile Picture
Interaction Design
Licensed Under Creative Commons by Naresh Jain
Friday, September 18, 2009 10
28. Before you take the plunge...
System Metaphor
Election Metaphor
‘Google Search Engine’ Metaphor
Thin Slice
ProTest - Dependency Voter
Profile Picture
Interaction Design
Tracer Bullets: Prototyping, a forgotten Design Practice
Licensed Under Creative Commons by Naresh Jain
Friday, September 18, 2009 10
29. Before you take the plunge...
Micro-Design v/s Macro-Design v/s BUFD
Unit Tests Validates Micro-Design
There is No Spoon
Fluent Interfaces in Test
Behavior (verbs) as Test Class Names
Licensed Under Creative Commons by Naresh Jain
Friday, September 18, 2009 11
30. There is no Spoon
Veterinarian Information System (system responsible for billing & patient history)
ChargeAccountForServices with the following test methods:
makePaymentsAgainstAnAccount()
completePaymentsResultInZeroAmountDueOnReceipt()
incompletePaymentsDisplaysDueAmountOnTheReceipt()
Another test class: GenerateBillsForClientAccount with
notifyIfAccountIsNotDueForPayment()
billContainsTotalCostOfAllServicesTaken()
And another test class: ManageClientVisits with
trackAllServicesTakenByThePatient()
skipVisitIfPatientDidNotTakeAnyService()
Licensed Under Creative Commons by Naresh Jain
Friday, September 18, 2009 12
31. Other Test Naming Convention
Other’s Naming Convention My Naming Convention
itShouldSetAccountToLoggedInWhenPasswordMatches matchingPasswordLogsYouIn
itShouldSetAccountToRevokedAfterThreeFailedLoginAttempts threeFailedLoginAttemptsRevokesYourAccount
itShouldNotSetAccountLoggedInIfPasswordDoesNotMatch nonMatchingPasswordDoesNotLogYouIn
itShouldNotRevokeSecondAccountAfterTwoFailedAttemptsFirst failedLoginAttemptsOnOtherAccountsDoesNotImpact
Account MyAccount
itShouldNowAllowConcurrentLogins sameUserCannotLoginConcurrently
itShouldThrowExceptionIfAccountNotFound onlyUserWithExistingAccountCanLogin
ItShouldNotBePossibleToLogIntoRevokedAccount userWithRevokedAccountCannotLogin
itShouldResetBackToInitialStateAfterSuccessfulLogin successfulLoginResetsFailedAttemptCount
Licensed Under Creative Commons by Naresh Jain
Friday, September 18, 2009 13
32. Fluent Interfaces
Licensed Under Creative Commons by Naresh Jain
Friday, September 18, 2009 14
33. Fluent Interfaces
@Test
public void redirectDomainsWithSubDomainsPermanently() {
server.redirect(“google.com”).withSubDomain().to(“directi.com”);
client_requests(“blog.google.com”);
response = domainForwardingServer.process(request);
assertStatusIs(PermanentRedirect);
assertLocationIs(“directi.com/blog”);
assertStandardResponseHeaderIsPresent();
}
Licensed Under Creative Commons by Naresh Jain
Friday, September 18, 2009 14
34. Fluent Interfaces
@Test
public void redirectDomainsWithSubDomainsPermanently() {
server.redirect(“google.com”).withSubDomain().to(“directi.com”);
client_requests(“blog.google.com”);
response = domainForwardingServer.process(request);
assertStatusIs(PermanentRedirect);
assertLocationIs(“directi.com/blog”);
assertStandardResponseHeaderIsPresent();
}
User naresh_from_mumbai = new User("naresh", "jains", "mumbai", "india", "indian");
Context lets = new Context(userService, dns);
IdentitySuggester suggester = new IdentitySuggester(userService, dns, randomNumberGenerator);
@Test
public void avoidCelebrityNamesInGeneratedIds() {
lets.assume("naresh", "jain").isACelebrityName();
List<String> generatedIds = suggester.generateIdsFor(naresh_from_mumbai);
lets.assertThat(generatedIds).are("nares@jain.com", "naresh@india.com");
}
Licensed Under Creative Commons by Naresh Jain
Friday, September 18, 2009 14
35. Avatars of TDD
Business Facing
Drives Development
Critique product
Inside Out
Outside In
Technology/Implementation Facing
Brian Marick’s Test Categorization
Licensed Under Creative Commons by Naresh Jain
Friday, September 18, 2009 15
36. Outside In: ATDD
Fitnesse Document:
Assertions: 17 right, 0 wrong, 0 ignored, 0 exceptions
com.vis.billing.fixtures.PaidCashBill
procedure details on the bill
account details
name cost
account number patient name owner name
Routine Office Visit 250
1001 Fluffy Dave Atkins
Rabies Vaccination 50
procedure details pay Cash
name cost
patient name? owner name? account number? bill no? payment method? amount paid?
Routine Office Visit 250
Fluffy Dave Atkins 1001 1 Cash 300
Rabies Vaccination 50
bill check paid true
account number? owner name? patient name? total? paid?
1001 Dave Atkins Fluffy 300 false check total 0
Licensed Under Creative Commons by Naresh Jain
Friday, September 18, 2009 16
37. Outside In: ATDD Output
Licensed Under Creative Commons by Naresh Jain
Friday, September 18, 2009 17
38. ATDD: Another Example
Acceptance test:
class FluffyTest < Test::Unit::TestCase
def test_examination_and_shots
vet = Veterinarian.new
clinic = Clinic.new "Main Line health"
dave = Owner.new "Dave"
fluffy = Patient.new "Fluffy"
dave.has fluffy
visit = clinic.visit(fluffy, vet) do |v|
v.procedure "Rabies vaccination", 50
end
invoice = visit.invoice
assert_equal invoice.to_s,
<<-INVOICE
Routine visit: $200
Rabies vaccination: $50
Total: $250
INVOICE
receipt = clinic.pay_for visit, 100
assert_equal receipt.to_s,
<<-RECEIPT
Paid $100 for Routine visit
Paid $0 for Rabies vaccination
Outstanding: $150
RECEIPT
end Licensed Under Creative Commons by Naresh Jain
end
Friday, September 18, 2009 18
39. Output from ATDD
Licensed Under Creative Commons by Naresh Jain
Friday, September 18, 2009 19
40. Inside Out: Unit TDD
public class ClinicTest {
private Clinic clinic = new Clinic();
public class BillableTest {
@Test
public void amountOnTheReceiptShouldMatchBillableAmount() throws Exception { private static final Account daveSAccount = new Account(101, "Dave");
Billable billable = new Billable() { private static final List<Service> services = new ArrayList<Service>();
public int totalAmount() { return 0; }
}; @Test
Account dave = new Account(101, "Dave"); public void totalBillableAmountShouldBeZeroIfNoServicesAreProvided() {
Billable bill = new Bill(daveSAccount, services);
Receipt rcpt = clinic.payCash(dave, billable); assertEquals("Total amount is not Zero", 0, bill.totalAmount());
assertEquals("Amount on receipt does match procedure cost", billable.totalAmount(), rcpt.getAmount()); }
}
@Test
@Test public void totalBillableAmountShouldBeTotalOfEachServiceProvided() {
public void customerPayesBillableAmountForCashTransaction() throws Exception { services.add(new Procedure("Rabies Vaccination", 250));
final int billableAmount = 56; services.add(new Procedure("Regular office Visit", 50));
class AmountCharged { int charged; };
final AmountCharged charged = new AmountCharged(); Billable bill = new Bill(daveSAccount, services);
Billable billable = new Billable() { assertEquals("Total Amount is not 300", 300, bill.totalAmount());
public int totalAmount() { }
return billableAmount;
} @After
}; public void cleanUp() {
services.clear();
Account dave = new Account(101, "Dave") { }
public void charge(int amount) { }
charged.charged = amount;
}
};
clinic.payCash(dave, billable);
assertEquals("Account is not charged billable amount", billableAmount,charged.charged);
}
}
Licensed Under Creative Commons by Naresh Jain
Friday, September 18, 2009 20
41. Inside Out: Output
Licensed Under Creative Commons by Naresh Jain
Friday, September 18, 2009 21
42. Inside Out: Another Example
@Test
public class ChargeAccountForServices { public void shouldHaveZeroAmountDueOnReceiptIfCompletePaymentIsMade() {
private static final Billable bill = createMock(Billable.class); expect(bill.amount()).andReturn(300);
private static final Accountable account = createMock(Accountable.class); replay(bill);
private static final Clinic clinic = new Clinic(); Receipt receipt = clinic.pay(300, bill, account);
verify(bill);
@Before assertEquals(300, receipt.amount());
public void setUp() { assertEquals(0, receipt.amountDue());
reset(account); }
reset(bill);
} @Test
public void shouldDisplayAmountDueOnTheReceiptIfIncompletePaymentIsMade() {
@Test expect(bill.amount()).andReturn(500);
public void shouldMakePaymentsAgainstAnAccount() throws Exception { replay(bill);
account.paid(bill); Receipt receipt = clinic.pay(300, bill, account);
replay(account); verify(bill);
clinic.pay(300, bill, account); assertEquals(300, receipt.amount());
verify(account); assertEquals(200, receipt.amountDue());
} }
}
Licensed Under Creative Commons by Naresh Jain
Friday, September 18, 2009 22
43. public class CreateBillForClientAccount { @Test
private static final List<Service> services = new ArrayList<Service>(); public void shouldCreateABillWithTheTotalCostOfAllTheServices() {
private static final Accountable account = createMock(Accountable.class); IMocksControl control = createControl();
private Bill bill; Service rabiesVaccination = control.createMock(Service.class);
Service routineVisit = control.createMock(Service.class);
@Before services.add(rabiesVaccination);
public void setUp() { services.add(routineVisit);
reset(account);
} expect(account.isPaymentDue()).andReturn(true);
expect(account.unpaidServices()).andReturn(services);
bill();
@Test
public void shouldThrowExceptionIfAccountIsNotDueForPayment() { expect(rabiesVaccination.cost()).andReturn(250);
expect(account.isPaymentDue()).andReturn(false); expect(routineVisit.cost()).andReturn(50);
replay(account);
try { control.replay();
new Bill(account, null);
} catch (NoPaymentDueException e) { assertEquals(300, bill.amount());
// expected control.verify();
} }
verify(account);
} private void bill() throws NoPaymentDueException {
replay(account);
@After bill = new Bill(account, null);
public void cleanUp() { verify(account);
services.clear(); }
}
}
Licensed Under Creative Commons by Naresh Jain
Friday, September 18, 2009 23
44. Inside Out: Output
Licensed Under Creative Commons by Naresh Jain
Friday, September 18, 2009 24
45. Coffee Vending Machine
How would you develop it?
Licensed Under Creative Commons by Naresh Jain
Friday, September 18, 2009 25
46. Where do you Stand?
Unit Test x Acceptance test
API x User Interface
State x Interaction
OO x Procedural
Easy x Core
Narrow x Broad
Drive Design x Validate Design
Licensed Under Creative Commons by Naresh Jain
Friday, September 18, 2009 26
47. Thank you!
naresh@agilefaqs.com
http://blogs.agilefaqs.com/
Licensed Under Creative Commons by Naresh Jain
Friday, September 18, 2009 27