Successfully reported this slideshow.
Your SlideShare is downloading. ×

Avatars of Test Driven Development (TDD)

Avatars of Test Driven Development (TDD)

Download to read offline

It's easy to speak of test-driven development as if it were a single method, but there are several ways to approach it. In my experience, different approaches lead to quite different solutions.

In this hands-on workshop, with the help of some concrete examples, I'll demonstrate the different styles and more importantly what goes into the moment of decision when a test is written? And why TDDers make certain choices. The objective of the session is not to decide which approach is best, rather to highlight various different approaches/styles of practicing test-driven development.

By the end of this session, you will understand how TTDers break down a problem before trying to solve it. Also you'll be exposed to various strategies or techniques used by TDDers to help them write the first few tests.

It's easy to speak of test-driven development as if it were a single method, but there are several ways to approach it. In my experience, different approaches lead to quite different solutions.

In this hands-on workshop, with the help of some concrete examples, I'll demonstrate the different styles and more importantly what goes into the moment of decision when a test is written? And why TDDers make certain choices. The objective of the session is not to decide which approach is best, rather to highlight various different approaches/styles of practicing test-driven development.

By the end of this session, you will understand how TTDers break down a problem before trying to solve it. Also you'll be exposed to various strategies or techniques used by TDDers to help them write the first few tests.

More Related Content

Related Books

Free with a 30 day trial from Scribd

See all

Related Audiobooks

Free with a 30 day trial from Scribd

See all

Avatars of Test Driven Development (TDD)

  1. 1. Avatars of TDD Rule of Diversity Distrust all claims for “One True Way” Naresh Jain naresh@agilefaqs.com @nashjain http://nareshjain.com Copyright © 2013, AgileFAQs. All Rights Reserved.
  2. 2. Key Questions Business Facing Are we building the right product? Are we building the product right? Technology/Implementation Facing Copyright © 2013, AgileFAQs. All Rights Reserved.
  3. 3. Brian Marick’s Test Categorization Before/While Coding Post Coding Business Facing Supports Programming Critique product Technology/Implementation Facing Copyright © 2013, AgileFAQs. All Rights Reserved.
  4. 4. It Helps to Think of Tests this way... Business Facing Acceptance Testing Exploratory Testing Drives Development Critique product Low-fi prototypes UI and Usability Testing Performance Testing Unit Testing System Tests Technology/Implementation Facing Copyright © 2013, AgileFAQs. All Rights Reserved.
  5. 5. Business Facing Drives Development Inside Out Critique product Outside In Technology/Implementation Facing Brian Marick’s Test Categorization
  6. 6. TDD Rhythm Test, Code, Refactor Add a Test Pass Run the Test Fail Make a little change Fail Run the Test Pass Refactor
  7. 7. Acceptance Test Driven Development Iteration Automated Acceptance Acceptance Tests P E Criteria R F O R Story Automated M Unit Test E T Automated UI N E C Tests S E T S Automated Acceptance Tests Acceptance Exploratory Criteria Testing Copyright © 2013, AgileFAQs. All Rights Reserved.
  8. 8. Commercial Break!
  9. 9. Copyright © 2013, AgileFAQs. All Rights Reserved.
  10. 10. Tech Talks!
  11. 11. It all started with... Veterinarian Information System Copyright © 2013, AgileFAQs. All Rights Reserved.
  12. 12. 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
  13. 13. Outside In: Output
  14. 14. 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 end
  15. 15. Outside In: Output
  16. 16. 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); } }
  17. 17. Inside Out: Output
  18. 18. Inside Out: Another Example public class ChargeAccountForServices { private static final Billable bill = createMock(Billable.class); private static final Accountable account = createMock(Accountable.class); private static final Clinic clinic = new Clinic(); @Before public void setUp() { reset(account); reset(bill); } @Test public void shouldHaveZeroAmountDueOnReceiptIfCompletePaymentIsMade() { @Test expect(bill.amount()).andReturn(300); public void shouldMakePaymentsAgainstAnAccount() { 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(0, receipt.amountDue()); } } @Test public void shouldDisplayAmountDueOnTheReceiptIfIncompletePaymentIsMade() { expect(bill.amount()).andReturn(500); replay(bill); Receipt receipt = clinic.pay(300, bill, account); verify(bill); assertEquals(300, receipt.amount()); assertEquals(200, receipt.amountDue()); } }
  19. 19. Inside Out: Example Continued... public class CreateBillForClientAccount { private static final List<Service> services = new ArrayList<Service>(); private static final Accountable account = createMock(Accountable.class); private Bill bill; @Before public void setUp() { reset(account); } @Test public void shouldThrowExceptionIfAccountIsNotDueForPayment() { expect(account.isPaymentDue()).andReturn(false); replay(account); @Test try { public void shouldCreateABillWithTheTotalCostOfAllTheServices() { new Bill(account, null); IMocksControl control = createControl(); } catch (NoPaymentDueException e) { Service rabiesVaccination = control.createMock(Service.class); // expected Service routineVisit = control.createMock(Service.class); } services.add(rabiesVaccination); verify(account); services.add(routineVisit); } expect(account.isPaymentDue()).andReturn(true); @After expect(account.unpaidServices()).andReturn(services); public void cleanUp() { bill(); services.clear(); } expect(rabiesVaccination.cost()).andReturn(250); expect(routineVisit.cost()).andReturn(50); control.replay(); assertEquals(300, bill.amount()); control.verify(); } private void bill() throws NoPaymentDueException { replay(account); bill = new Bill(account, null); verify(account); } }
  20. 20. Inside Out: Output
  21. 21. 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 Copyright © 2013, AgileFAQs. All Rights Reserved.
  22. 22. Bonus Calculator Sales Quota Commission % Tax % Result 1200 1100 10 10 9 1200 1500 10 10 0 1200 1200 10 10 0 Copyright © 2013, AgileFAQs. All Rights Reserved.
  23. 23. First Few Tests Inside-Out Tests @Test ! public void noBonusForLowPerformers() { ! ! whenSalesIs(0).andQuotaIs(100).thenIndividualBonusIs(0); ! } ! @Test ! public void noBonusForAveragePerformers() { ! ! whenSalesIs(100).andQuotaIs(100).thenIndividualBonusIs(0); ! } ! @Test ! public void bonusIsBasedOnCommissionPercentage() { ! ! whenSalesIs(110).andQuotaIs(10).andCommissionIs(100).thenIndividualBonusIs(100); ! ! whenSalesIs(110).andQuotaIs(10).andCommissionIs(10).thenIndividualBonusIs(10); ! } ! @Test ! public void bonusIsBasedOnCommissionPercentageAfterTax() { ! ! whenSalesIs(110).andQuotaIs(10).andCommissionIs(100).andTaxIs(10).thenIndividualBonusIs(90); ! ! whenSalesIs(110.02).andQuotaIs(10.01).andCommissionIs(10).andTaxIs(10).thenIndividualBonusIs(9); ! } Copyright © 2013, AgileFAQs. All Rights Reserved.
  24. 24. Sales Tax Basic sales tax is applicable at a rate of 10% on all goods, except books, food, and medical products that are exempt. Import duty is an additional sales tax applicable on all imported goods at a rate of 5%, with no exemptions. When I purchase items I receive a receipt which lists the name of all the items and their price (including tax), finishing with the total cost of the items, and the total amounts of sales taxes paid. Write an application that prints out the receipt details for these shopping baskets... Input 1: Input 2: Input 3: 1 book at 12.49 1 imported box of chocolates at 10.00 1 imported bottle of perfume at 27.99 1 music CD at 14.99 1 bottle of perfume at 18.99 1 imported bottle of perfume at 47.50 1 packet of headache pills at 9.75 1 chocolate bar at 0.85 1 box of imported chocolates at 11.25 Output 2: Output 1: 1 imported box of chocolates: 10.50 Output 3: 1 book : 12.49 1 imported bottle of perfume: 54.65 1 imported bottle of perfume: 32.19 1 music CD: 16.49 1 bottle of perfume: 20.89 Sales Taxes: 7.65 1 chocolate bar: 0.85 1 packet of headache pills: 9.75 Total: 65.15 Sales Taxes: 1.50 1 imported box of chocolates: 11.85 Total: 29.83 Sales Taxes: 6.70 Total: 74.68 Copyright © 2013, AgileFAQs. All Rights Reserved.
  25. 25. First Few Outside-In Tests @Test public void checkOutEmptyCart() { assertTotalIs(0); } @Test public void checkOutAnExemptedDomesticItem() { cart.add(rs100DomesticBook); assertTotalIs(100); } @Test public void checkOutTaxableDomesticItem() { cart.add(rs100DomesticMusicCD); assertTotalIs(110); } @Test public void checkOutExemptedImportedItem() { cart.add(rs100ImportedBook); assertTotalIs(105); } @Test public void checkOutImportedItem() { cart.add(rs100ImportedMacBook); assertTotalIs(115); } Copyright © 2013, AgileFAQs. All Rights Reserved.
  26. 26. Medical System Age Calculating Program Age Reported in Greater than 1 Year <Patient Name> is # Years old > 1 Month & < 1 Year <Patient Name> is # Months old > 1 Day & < 1 Month <Patient Name> is # Days old > 1 Hr & < 1 Day <Patient Name> is # Hours old Doctors and Nurses might like to add and remove new Durations. For Ex: If they add Decade, and Patient’s age is greater than 10 years, then age should be reported as <Patient Name> is # Decades old. Similarly: If they add Week, and Patient’s age is greater than 7 Day, but less than a month, then age should be reported as <Patient Name> is # Weeks old. Copyright © 2013, AgileFAQs. All Rights Reserved.
  27. 27. First Few Inside-Out Tests @RunWith(Parameterized.class) public class DurationTest extends FixedTimeTestCase { ! private final Date date; ! private final String result; @Test public void canRegisterAndUnregisterLargestDuration() { ! public DurationTest(Object date, Object result) { assertEquals("31 Years", Duration.since(may3rd1980)); ! ! this.date = (Date) date; ! ! this.result = (String) result; Duration.register("Decades", MILLISECONDS_PER_YEAR * 10); ! } assertEquals("3 Decades", Duration.since(may3rd1980)); ! @Parameters Duration.unregister("Decades"); ! public static List<Object[]> data() { ! ! return new ArrayList<Object[]>() { assertEquals("31 Years", Duration.since(may3rd1980)); ! ! ! { } ! ! ! ! add(new Object[] { may3rd1980, "31 Years" }); ! ! ! ! add(new Object[] { jan1st2011, "9 Months" }); ! ! ! ! add(new Object[] { oct1st2011, "10 Days" }); ! ! ! ! add(new Object[] { oct11nth2011Afternoon, "0 Hours" }); ! ! ! } ! ! }; @Test ! } public void canRegisterAndUnregisterSmallestDuration() { ! @Test assertEquals("0 Hours", Duration.since(oct11nth2011Morning)); ! public void calculatesDurationSince() { ! ! String value = Duration.since(date); Duration.register("Minutes", MILLISECONDS_PER_MINUTE); ! ! assertEquals("For " + date, result, value); assertEquals("2 Minutes", Duration.since(oct11nth2011Morning)); ! } Duration.unregister("Minutes"); ! @Override assertEquals("0 Hours", Duration.since(oct11nth2011Morning)); ! protected Date currentTime() { } ! ! return oct11nth2011Afternoon; ! } } Copyright © 2013, AgileFAQs. All Rights Reserved.
  28. 28. Meeting Assistant Copyright © 2013, AgileFAQs. All Rights Reserved.
  29. 29. First Few Outside-In Tests @Test public void jackWantsThinkingTime() { jack().isAvailable(now).forEver(); @Test firstAvailableSlotFor(THIRTY_MINS).is(now); public void jackIsAvailableLaterForARequiredDuration() { } jack().isAvailable(now).forNext(TWENTY_MINS); jack().isAvailable(inTwoHours).forEver(); @Test firstAvailableSlotFor(THIRTY_MINS).is(inTwoHours); public void jackBusyForNextTwoHours() { } jack().isAvailable(inTwoHours).forEver(); firstAvailableSlotFor(THIRTY_MINS).is(inTwoHours); @Test(expected = RuntimeException.class) } public void jackHasNoTimeToThink() { jack().isNotAvailable(); @Test assistant.firstAvailableTimeFor(participants, THIRTY_MINS); public void jackAndJillAreAvailableRightNowToMeet() { } jack().isAvailable(now).forEver(); jill().isAvailable(now).forEver(); between(JACK, JILL).firstAvailableSlotFor(THIRTY_MINS).is(now); } Copyright © 2013, AgileFAQs. All Rights Reserved.
  30. 30. 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 Copyright © 2013, AgileFAQs. All Rights Reserved.
  31. 31. Thank you Naresh Jain naresh@agilefaqs.com Copyright © 2013, AgileFAQs. All Rights Reserved.

×