SlideShare a Scribd company logo
Realistic Test-Driven Development:Paying and PreventingTechnical DebtRob MyersAgile Development Practices11 November 200911 November 2009© Rob Myers 20091
11 November 2009© Rob Myers 20092Unit testing is sooooDEPRESSING
11 November 2009© Rob Myers 20093TDD is fun,and provides much more than just unit-tests!
11 November 2009© Rob Myers 20094fromXPtoATDD&BDD
11 November 2009© Rob Myers 20095waste
11 November 2009© Rob Myers 20096#1automationpublic static void Main() {Console.WriteLine(    “I sure hope this works...” +myObject.Foo());}
11 November 2009© Rob Myers 20097
11 November 2009© Rob Myers 20098#2Test-FirstWe write a test before writing the code that makes it pass.
Why Wait?11 November 2009© Rob Myers 20099CodeTestMonthsCodeTestWeeksCodeTestDaysCodeTest
What If?11 November 2009© Rob Myers 200910CodeRun TestTestWrite TestRun TestRun TestRun Test
Benefits of Test-FirstJust-In-Time analysis.We know when something is……done.…done correctly.…broken.…and fixed!11 November 2009© Rob Myers 200911
11 November 2009© Rob Myers 200912
11 November 2009© Rob Myers 200913#3Any behavior-preserving change that improves maintainability.
11 November 2009© Rob Myers 200914
11 November 2009© Rob Myers 200915
11 November 2009© Rob Myers 200916#4Mock Objects
Prep road-data for new Mars Colony Road/Canal Service Build ‘Earth’ adapter around map-data service
Refactor all callers to use Earth (all?)
Extract abstract  parent ‘Planet’
Planet needs a factory
Test that Mars adapter calls new Mars-map service (mock the service)
Test that Planet factory determines which planet client is on (mock config file)11 November 2009© Rob Myers 200917#5A To-Do List
11 November 2009© Rob Myers 200918Analogies  &  Metaphors
11 November 2009© Rob Myers 200919
11 November 2009© Rob Myers 200920
11 November 2009© Rob Myers 200921“The results of the case studies indicate that the pre-release defect density of the four products decreased between 40% and 90% relative to similar projects that did not use the TDD practice. Subjectively, the teams experienced a 15–35% increase in initial development time after adopting TDD.”http://research.microsoft.com/en-us/projects/esm/nagappan_tdd.pdf, Nagappan et al, © Springer Science + Business Media, LLC 2008
11 November 2009© Rob Myers 200922real value
11 November 2009© Rob Myers 200923architecturalperspective
11 November 2009© Rob Myers 200924roadblocks
11 November 2009© Rob Myers 200925discipline
11 November 2009© Rob Myers 200926stepsWrite oneunit test.Build or add to the object under test until everything compiles.Red:  Watch the test fail!Green:  Make all the tests pass by changing the object under test.Clean: Refactormercilessly!Repeat.
11 November 2009© Rob Myers 200927 given when then
11 November 2009© Rob Myers 200928TDD Demo
11 November 2009© Rob Myers 200929Basic UML Class DiagramsFoo- intprivateVariable+ intPublicMethod()BarBaz+ void AbstractMethod(        object parameter)- void PrivateMethod()
11 November 2009© Rob Myers 200930Global Currency Money-Market Account
11 November 2009© Rob Myers 200931Global ATMAccess
StoriesAs Rob the US account holder, I want to be able to withdraw USD from a US ATM, but select which currency holdings to withdraw from.As Rob, traveling in Europe, I want to be able to withdraw EUR from either my EUR holdings or my USD holdings.  The default should be the most beneficial to me at the time.Shortly after the end of each month, I want to receive a report of my holdings and balance.  The total balance should appear in the currency of my account address (USD).11 November 2009© Rob Myers 200932
Primary Objects11 November 2009© Rob Myers 200933CurrencyAccountHolding
More Detail11 November 2009© Rob Myers 200934CurrencyHoldingvaluecurrencycurrencyConverterCurrencyConverterconvert value to  another currency
Start SimpleTo DoWhen currencies are the same.
When value is zero.11 November 2009© Rob Myers 200935
Specification, and Interface11 November 2009© Rob Myers 200936[TestMethod]public void GivesSameValueWhenSameCurrencyRequested() {CurrencyConverter converter = new CurrencyConverter();    string sameCurrency = "USD";    double sameValue = 100.0000;    double converted = converter.convert(sameValue, sameCurrency, sameCurrency);Assert.AreEqual(sameValue, converted, 0.00004);}Will not compile. 
“Thank You, But…”11 November 2009© Rob Myers 200937using System;class CurrencyConverter {    public double convert(        double value, string from, string to) {        throw new NotImplementedException();    }}
“…I Want to See it Fail Successfully”11 November 2009© Rob Myers 200938class CurrencyConverter {    public double convert(        double value, string from, string to) {return 0.0;    }}
Just Enough to Pass11 November 2009© Rob Myers 200939public double convert(    double value, string from, string to) {    return 100.0;}
a.  Refactor Away the Duplication11 November 2009© Rob Myers 200940[TestMethod]public void GivesSameValueWhenSameCurrencyRequested() {CurrencyConverter converter = new CurrencyConverter();    string sameCurrency = "USD";    double sameValue = 100.0000;    double converted = converter.convert(sameValue, sameCurrency, sameCurrency);Assert.AreEqual(sameValue, converted, 0.00004);}public double convert(    double value, string from, string to) {    return 100.0;}
b.  Triangulate11 November 2009© Rob Myers 200941
11 November 2009© Rob Myers 200942We don’t add any behavior without a failing test…Rodin’s The Thinker, photo by CJ on Wikipedia
Triangulating Test11 November 2009© Rob Myers 200943[TestMethod]public void GivesZeroWhenValueIsZero() {CurrencyConverter converter = new CurrencyConverter();    double zero = 0.0000;    double converted = converter.convert(        zero, "USD", "EUR");Assert.AreEqual(zero, converted, 0.00004);}
Still “Cheating”?11 November 2009© Rob Myers 200944class CurrencyConverter {    public double convert(        double value, string from, string to) {        return value;    }}
Maintain the Tests11 November 2009© Rob Myers 200945[TestMethod]public void GivesZeroWhenValueIsZero() {CurrencyConverter converter = new CurrencyConverter();    // ...}[TestMethod]public void GivesSameValueWhenSameCurrencyRequested() {CurrencyConverter converter = new CurrencyConverter();    // ...}
TestInitialize Runs Before Each Test11 November 2009© Rob Myers 200946private CurrencyConverter converter;[TestInitialize]public void InitConverter() {    converter = new CurrencyConverter();}[TestMethod]public void GivesZeroWhenValueIsZero() {    // ...}[TestMethod]public void GivesSameValueWhenSameCurrencyRequested() {    // ...}
What is the Expected Answer?11 November 2009© Rob Myers 200947[TestMethod]public void ConvertsDollarsToEuros() {    double converted = converter.convert(        100.0000, "USD", "EUR");Assert.AreEqual(???, converted, 0.00004);}
Let’s “Guess”…11 November 2009© Rob Myers 200948[TestMethod]public void ConvertsDollarsToEuros() {    double converted = converter.convert(        100.0000, "USD", "EUR");Assert.AreEqual(50.0000, converted, 0.00004);}
…Get it Working…11 November 2009© Rob Myers 200949public double convert(    double value, string from, string to) {    if (to.Equals(from))        return value;    return value * 0.5000;}
…Refactor…11 November 2009© Rob Myers 200950public double convert(    double value, string from, string to) {    if (to.Equals(from))        return value;    return value * ConversionRate(from, to);}private double ConversionRate(string from, string to) {    return 0.5000;}
…And Make a Note of ItTo DoWhen currencies are the same.
When value is zero.
Fix the hard-coded ConversionRate11 November 2009© Rob Myers 200951
11 November 2009© Rob Myers 200952Well, What is It???Where does it come from?
Circumstantial Coupling?11 November 2009© Rob Myers 200953CurrencyConverter
Managing the Transaction11 November 2009© Rob Myers 200954AccountCurrencyConverterHoldingHoldingHoldingConversionRatesHolding
Another Object EmergesTo DoWhen currencies are the same.
When value is zero.
Fix hard-coded ConversionRate().
Write ConversionRates.
Make a factory for ConversionRates that uses the FOREX.com Web Service.11 November 2009© Rob Myers 200955
New Test Class11 November 2009© Rob Myers 200956using Microsoft.VisualStudio.TestTools.UnitTesting;[TestClass]public class ConversionRatesTests {    [TestMethod]    public void StoresAndRetrievesRates() {ConversionRates rates = new ConversionRates();        string from = "USD";        string to = "EUR";        double rate = 0.7424;rates.PutRate(from, to, rate);Assert.AreEqual(rate, rates.GetRate(from, to));    }}
Fail11 November 2009© Rob Myers 200957public class ConversionRates {    public void PutRate(string from, string to, double rate) {    }    public double GetRate(string from, string to) {        return 0.0;    }}
No Need to be Coy11 November 2009© Rob Myers 200958public class ConversionRates {    private Dictionary<string, double> rates        = new Dictionary<string, double>();    public void PutRate(string from, string to, double rate) {        rates[from + to] = rate;    }    public double GetRate(string from, string to) {        return rates[from + to];    }}
Isolate Behavior11 November 2009© Rob Myers 200959public class ConversionRates {    private Dictionary<string, double> rates        = new Dictionary<string, double>();    public void PutRate(string from, string to, double rate) {        rates[Key(from, to)] = rate;    }    public double GetRate(string from, string to) {        return rates[Key(from, to)];    }    private string Key(string from, string to) {        return from + to;    }}
Next?To DoWhen currencies are the same.
When value is zero.

More Related Content

PDF
How Testability Inspires AngularJS Design / Ran Mizrahi
PPTX
Workflow Foundation 4
PDF
Intro to React
PDF
JavaScript Essentials in 1 Hour (2018)
ODP
From object oriented to functional domain modeling
PDF
Getting Comfortable with JS Promises
PDF
React Native One Day
PPTX
T# @ Agile Tour Montreal 2009 En
How Testability Inspires AngularJS Design / Ran Mizrahi
Workflow Foundation 4
Intro to React
JavaScript Essentials in 1 Hour (2018)
From object oriented to functional domain modeling
Getting Comfortable with JS Promises
React Native One Day
T# @ Agile Tour Montreal 2009 En

What's hot (10)

PDF
Structure on a freeform world
PDF
Asynchronous JavaScript Programming with Callbacks & Promises
PDF
Tdd iPhone For Dummies
PDF
React Native Evening
PDF
Javascript Promises/Q Library
PDF
Callback Function
PDF
Refactoring
PDF
Kotlin a problem solver - gdd extended pune
PPTX
Advanced Javascript
Structure on a freeform world
Asynchronous JavaScript Programming with Callbacks & Promises
Tdd iPhone For Dummies
React Native Evening
Javascript Promises/Q Library
Callback Function
Refactoring
Kotlin a problem solver - gdd extended pune
Advanced Javascript
Ad

Viewers also liked (12)

PDF
IFAD Egg Noodles_IMC_Campaign
PPTX
Análisis 2 de la actividad.hercy
PDF
L'activité e-commerce des TPE-PME - Edition 2011
PDF
Bushrod_Resume 2015
PPTX
04 intro of data anal - pow piv_mat
PDF
Ποιος είμαι, ποια είμαι
PDF
Έγγραφο προς σχολεία
PDF
Interview b2b Summit 7 juillet 2016 Laurent Ollivier Aressy BtoB
PPT
Enlace Ciudadano Nro 336 tema: bce y ugdep
PPT
Enlace Ciudadano Nro 235 tema: reuniones de representantes del ecuador con ch...
PPTX
Gevaar
PDF
FESCO CHINESE PRESENTATION 30 march
IFAD Egg Noodles_IMC_Campaign
Análisis 2 de la actividad.hercy
L'activité e-commerce des TPE-PME - Edition 2011
Bushrod_Resume 2015
04 intro of data anal - pow piv_mat
Ποιος είμαι, ποια είμαι
Έγγραφο προς σχολεία
Interview b2b Summit 7 juillet 2016 Laurent Ollivier Aressy BtoB
Enlace Ciudadano Nro 336 tema: bce y ugdep
Enlace Ciudadano Nro 235 tema: reuniones de representantes del ecuador con ch...
Gevaar
FESCO CHINESE PRESENTATION 30 march
Ad

Similar to Test-Driven Development Overview (20)

PPTX
The Value of Refactoring on an Agile Team
PDF
Automated Testing with Ruby
PPTX
What’s new in .NET
KEY
Advanced Testing on RubyEnRails '09
PDF
Essential Test-Driven Development
PDF
Intro To JavaScript Unit Testing - Ran Mizrahi
PDF
Essential Test-Driven Development
PDF
JS Class 2016
PDF
JS class slides (2016)
PDF
Unit Testing for Great Justice
PPTX
From dot net_to_rails
PPTX
Promises, Promises
PDF
PHP7. Game Changer.
PPTX
Web technologies-course 12.pptx
PDF
Es.next
PDF
ECMAScript.Next ECMAScipt 6
PDF
Test driven development
PDF
Variable In Ruby on Rails_ A Comprehensive Guide With Examples
PDF
Refactoring Simple Example
PDF
.NET Coding Standards For The Real World (2012)
The Value of Refactoring on an Agile Team
Automated Testing with Ruby
What’s new in .NET
Advanced Testing on RubyEnRails '09
Essential Test-Driven Development
Intro To JavaScript Unit Testing - Ran Mizrahi
Essential Test-Driven Development
JS Class 2016
JS class slides (2016)
Unit Testing for Great Justice
From dot net_to_rails
Promises, Promises
PHP7. Game Changer.
Web technologies-course 12.pptx
Es.next
ECMAScript.Next ECMAScipt 6
Test driven development
Variable In Ruby on Rails_ A Comprehensive Guide With Examples
Refactoring Simple Example
.NET Coding Standards For The Real World (2012)

More from Rob Myers (13)

PPTX
The Business Value of Agile Engineering Practices
PPTX
The Business Value of Test-Driven Development
PPTX
Roots of Agility - Better Software Agile Dev Practices East 2014 Keynote
PPTX
Assessing the business value of Agile Engineering Practices
PPTX
The Business Value of Agile Engineering Practices
PPTX
Unit-Testing Your Legacy JavaScript
PPTX
Mock Objects from Concept to Code
KEY
Technical Debt
PPTX
Successful Teams are TDD Teams
PPTX
TDD? Sure, but What About My Legacy Code?
PPTX
Metrics In An Agile World
PPTX
Successful Teams are Test-Driven Teams
PDF
Agile Testing: Solving the Agilist\'s Dilemma
The Business Value of Agile Engineering Practices
The Business Value of Test-Driven Development
Roots of Agility - Better Software Agile Dev Practices East 2014 Keynote
Assessing the business value of Agile Engineering Practices
The Business Value of Agile Engineering Practices
Unit-Testing Your Legacy JavaScript
Mock Objects from Concept to Code
Technical Debt
Successful Teams are TDD Teams
TDD? Sure, but What About My Legacy Code?
Metrics In An Agile World
Successful Teams are Test-Driven Teams
Agile Testing: Solving the Agilist\'s Dilemma

Test-Driven Development Overview

  • 1. Realistic Test-Driven Development:Paying and PreventingTechnical DebtRob MyersAgile Development Practices11 November 200911 November 2009© Rob Myers 20091
  • 2. 11 November 2009© Rob Myers 20092Unit testing is sooooDEPRESSING
  • 3. 11 November 2009© Rob Myers 20093TDD is fun,and provides much more than just unit-tests!
  • 4. 11 November 2009© Rob Myers 20094fromXPtoATDD&BDD
  • 5. 11 November 2009© Rob Myers 20095waste
  • 6. 11 November 2009© Rob Myers 20096#1automationpublic static void Main() {Console.WriteLine( “I sure hope this works...” +myObject.Foo());}
  • 7. 11 November 2009© Rob Myers 20097
  • 8. 11 November 2009© Rob Myers 20098#2Test-FirstWe write a test before writing the code that makes it pass.
  • 9. Why Wait?11 November 2009© Rob Myers 20099CodeTestMonthsCodeTestWeeksCodeTestDaysCodeTest
  • 10. What If?11 November 2009© Rob Myers 200910CodeRun TestTestWrite TestRun TestRun TestRun Test
  • 11. Benefits of Test-FirstJust-In-Time analysis.We know when something is……done.…done correctly.…broken.…and fixed!11 November 2009© Rob Myers 200911
  • 12. 11 November 2009© Rob Myers 200912
  • 13. 11 November 2009© Rob Myers 200913#3Any behavior-preserving change that improves maintainability.
  • 14. 11 November 2009© Rob Myers 200914
  • 15. 11 November 2009© Rob Myers 200915
  • 16. 11 November 2009© Rob Myers 200916#4Mock Objects
  • 17. Prep road-data for new Mars Colony Road/Canal Service Build ‘Earth’ adapter around map-data service
  • 18. Refactor all callers to use Earth (all?)
  • 19. Extract abstract parent ‘Planet’
  • 20. Planet needs a factory
  • 21. Test that Mars adapter calls new Mars-map service (mock the service)
  • 22. Test that Planet factory determines which planet client is on (mock config file)11 November 2009© Rob Myers 200917#5A To-Do List
  • 23. 11 November 2009© Rob Myers 200918Analogies & Metaphors
  • 24. 11 November 2009© Rob Myers 200919
  • 25. 11 November 2009© Rob Myers 200920
  • 26. 11 November 2009© Rob Myers 200921“The results of the case studies indicate that the pre-release defect density of the four products decreased between 40% and 90% relative to similar projects that did not use the TDD practice. Subjectively, the teams experienced a 15–35% increase in initial development time after adopting TDD.”http://research.microsoft.com/en-us/projects/esm/nagappan_tdd.pdf, Nagappan et al, © Springer Science + Business Media, LLC 2008
  • 27. 11 November 2009© Rob Myers 200922real value
  • 28. 11 November 2009© Rob Myers 200923architecturalperspective
  • 29. 11 November 2009© Rob Myers 200924roadblocks
  • 30. 11 November 2009© Rob Myers 200925discipline
  • 31. 11 November 2009© Rob Myers 200926stepsWrite oneunit test.Build or add to the object under test until everything compiles.Red: Watch the test fail!Green: Make all the tests pass by changing the object under test.Clean: Refactormercilessly!Repeat.
  • 32. 11 November 2009© Rob Myers 200927 given when then
  • 33. 11 November 2009© Rob Myers 200928TDD Demo
  • 34. 11 November 2009© Rob Myers 200929Basic UML Class DiagramsFoo- intprivateVariable+ intPublicMethod()BarBaz+ void AbstractMethod( object parameter)- void PrivateMethod()
  • 35. 11 November 2009© Rob Myers 200930Global Currency Money-Market Account
  • 36. 11 November 2009© Rob Myers 200931Global ATMAccess
  • 37. StoriesAs Rob the US account holder, I want to be able to withdraw USD from a US ATM, but select which currency holdings to withdraw from.As Rob, traveling in Europe, I want to be able to withdraw EUR from either my EUR holdings or my USD holdings. The default should be the most beneficial to me at the time.Shortly after the end of each month, I want to receive a report of my holdings and balance. The total balance should appear in the currency of my account address (USD).11 November 2009© Rob Myers 200932
  • 38. Primary Objects11 November 2009© Rob Myers 200933CurrencyAccountHolding
  • 39. More Detail11 November 2009© Rob Myers 200934CurrencyHoldingvaluecurrencycurrencyConverterCurrencyConverterconvert value to another currency
  • 40. Start SimpleTo DoWhen currencies are the same.
  • 41. When value is zero.11 November 2009© Rob Myers 200935
  • 42. Specification, and Interface11 November 2009© Rob Myers 200936[TestMethod]public void GivesSameValueWhenSameCurrencyRequested() {CurrencyConverter converter = new CurrencyConverter(); string sameCurrency = "USD"; double sameValue = 100.0000; double converted = converter.convert(sameValue, sameCurrency, sameCurrency);Assert.AreEqual(sameValue, converted, 0.00004);}Will not compile. 
  • 43. “Thank You, But…”11 November 2009© Rob Myers 200937using System;class CurrencyConverter { public double convert( double value, string from, string to) { throw new NotImplementedException(); }}
  • 44. “…I Want to See it Fail Successfully”11 November 2009© Rob Myers 200938class CurrencyConverter { public double convert( double value, string from, string to) {return 0.0; }}
  • 45. Just Enough to Pass11 November 2009© Rob Myers 200939public double convert( double value, string from, string to) { return 100.0;}
  • 46. a. Refactor Away the Duplication11 November 2009© Rob Myers 200940[TestMethod]public void GivesSameValueWhenSameCurrencyRequested() {CurrencyConverter converter = new CurrencyConverter(); string sameCurrency = "USD"; double sameValue = 100.0000; double converted = converter.convert(sameValue, sameCurrency, sameCurrency);Assert.AreEqual(sameValue, converted, 0.00004);}public double convert( double value, string from, string to) { return 100.0;}
  • 47. b. Triangulate11 November 2009© Rob Myers 200941
  • 48. 11 November 2009© Rob Myers 200942We don’t add any behavior without a failing test…Rodin’s The Thinker, photo by CJ on Wikipedia
  • 49. Triangulating Test11 November 2009© Rob Myers 200943[TestMethod]public void GivesZeroWhenValueIsZero() {CurrencyConverter converter = new CurrencyConverter(); double zero = 0.0000; double converted = converter.convert( zero, "USD", "EUR");Assert.AreEqual(zero, converted, 0.00004);}
  • 50. Still “Cheating”?11 November 2009© Rob Myers 200944class CurrencyConverter { public double convert( double value, string from, string to) { return value; }}
  • 51. Maintain the Tests11 November 2009© Rob Myers 200945[TestMethod]public void GivesZeroWhenValueIsZero() {CurrencyConverter converter = new CurrencyConverter(); // ...}[TestMethod]public void GivesSameValueWhenSameCurrencyRequested() {CurrencyConverter converter = new CurrencyConverter(); // ...}
  • 52. TestInitialize Runs Before Each Test11 November 2009© Rob Myers 200946private CurrencyConverter converter;[TestInitialize]public void InitConverter() { converter = new CurrencyConverter();}[TestMethod]public void GivesZeroWhenValueIsZero() { // ...}[TestMethod]public void GivesSameValueWhenSameCurrencyRequested() { // ...}
  • 53. What is the Expected Answer?11 November 2009© Rob Myers 200947[TestMethod]public void ConvertsDollarsToEuros() { double converted = converter.convert( 100.0000, "USD", "EUR");Assert.AreEqual(???, converted, 0.00004);}
  • 54. Let’s “Guess”…11 November 2009© Rob Myers 200948[TestMethod]public void ConvertsDollarsToEuros() { double converted = converter.convert( 100.0000, "USD", "EUR");Assert.AreEqual(50.0000, converted, 0.00004);}
  • 55. …Get it Working…11 November 2009© Rob Myers 200949public double convert( double value, string from, string to) { if (to.Equals(from)) return value; return value * 0.5000;}
  • 56. …Refactor…11 November 2009© Rob Myers 200950public double convert( double value, string from, string to) { if (to.Equals(from)) return value; return value * ConversionRate(from, to);}private double ConversionRate(string from, string to) { return 0.5000;}
  • 57. …And Make a Note of ItTo DoWhen currencies are the same.
  • 59. Fix the hard-coded ConversionRate11 November 2009© Rob Myers 200951
  • 60. 11 November 2009© Rob Myers 200952Well, What is It???Where does it come from?
  • 61. Circumstantial Coupling?11 November 2009© Rob Myers 200953CurrencyConverter
  • 62. Managing the Transaction11 November 2009© Rob Myers 200954AccountCurrencyConverterHoldingHoldingHoldingConversionRatesHolding
  • 63. Another Object EmergesTo DoWhen currencies are the same.
  • 67. Make a factory for ConversionRates that uses the FOREX.com Web Service.11 November 2009© Rob Myers 200955
  • 68. New Test Class11 November 2009© Rob Myers 200956using Microsoft.VisualStudio.TestTools.UnitTesting;[TestClass]public class ConversionRatesTests { [TestMethod] public void StoresAndRetrievesRates() {ConversionRates rates = new ConversionRates(); string from = "USD"; string to = "EUR"; double rate = 0.7424;rates.PutRate(from, to, rate);Assert.AreEqual(rate, rates.GetRate(from, to)); }}
  • 69. Fail11 November 2009© Rob Myers 200957public class ConversionRates { public void PutRate(string from, string to, double rate) { } public double GetRate(string from, string to) { return 0.0; }}
  • 70. No Need to be Coy11 November 2009© Rob Myers 200958public class ConversionRates { private Dictionary<string, double> rates = new Dictionary<string, double>(); public void PutRate(string from, string to, double rate) { rates[from + to] = rate; } public double GetRate(string from, string to) { return rates[from + to]; }}
  • 71. Isolate Behavior11 November 2009© Rob Myers 200959public class ConversionRates { private Dictionary<string, double> rates = new Dictionary<string, double>(); public void PutRate(string from, string to, double rate) { rates[Key(from, to)] = rate; } public double GetRate(string from, string to) { return rates[Key(from, to)]; } private string Key(string from, string to) { return from + to; }}
  • 76. Make a factory for ConversionRates that uses the FOREX.com Web Service.11 November 2009© Rob Myers 200960
  • 77. Fix SetUp11 November 2009© Rob Myers 200961[TestClass]public class CurrencyConverterTests { private CurrencyConverter converter; [TestInitialize] public void InitConverter() {ConversionRates rates = new ConversionRates();rates.PutRate("USD", "EUR", 0.5000); converter = new CurrencyConverter(rates); }
  • 78. Partially Refactored…11 November 2009© Rob Myers 200962public class CurrencyConverter { private ConversionRates rates; public CurrencyConverter(ConversionRates rates) {this.rates = rates; } private double ConversionRate(string from, string to) { return 0.5000; }
  • 79. Replace the Hard-Coded Value11 November 2009© Rob Myers 200963public class CurrencyConverter { private ConversionRates rates; public CurrencyConverter(ConversionRates rates) {this.rates = rates; } private double ConversionRate(string from, string to) { return rates.GetRate(from, to); }
  • 80. What Remains?To DoWhen currencies are the same.
  • 84. Make a factory for ConversionRates that uses the FOREX.com Web Service.11 November 2009© Rob Myers 200964
  • 85. What is the Missing Piece?11 November 2009© Rob Myers 200965ConversionRates rates =ConversionRates.ByAccountAnd???( account, ???);
  • 86. What If, After a Break…To DoMake a ByAccountAndDate() factory for ConversionRates that uses the FOREX.com Web Service.
  • 87. ConversionRates returns 1/rate if inverse rate found.
  • 88. ConversionRates throws when rate not found.11 November 2009© Rob Myers 200966
  • 89. Testing Exceptional Behavior11 November 2009© Rob Myers 200967[TestMethod]public void ThrowsExceptionIfRateNotFound() {ConversionRates rates = new ConversionRates(); string from = "BAR"; string to = "BAZ"; try {rates.GetRate(from, to);Assert.Fail("should throw"); } catch (RateNotFoundException) { // expected }}
  • 90. A New Exception11 November 2009© Rob Myers 200968using System;public class RateNotFoundException : Exception {}
  • 91. 11 November 2009© Rob Myers 200969
  • 92. Back in ConversionRates11 November 2009© Rob Myers 200970public double GetRate(string from, string to) { if (!rates.ContainsKey(Key(from, to))) throw new RateNotFoundException(); return rates[Key(from, to)]; }
  • 93. An Alternative Test11 November 2009© Rob Myers 200971[TestMethod,ExpectedException(typeof(RateNotFoundException))]public void ThrowsExceptionIfRateNotFoundII() {ConversionRates rates = new ConversionRates(); string from = "BAR"; string to = "BAZ";rates.GetRate(from, to);}
  • 94. An Expressive Testfor an Expressive Exception11 November 2009© Rob Myers 200972[TestMethod]public void ThrowsExceptionIfRateNotFound() {ConversionRates rates = new ConversionRates(); string from = "BAR"; string to = "BAZ"; try {rates.GetRate(from, to);Assert.Fail("should throw "+ typeof(RateNotFoundException).Name); } catch (RateNotFoundExceptione) {StringAssert.Contains(e.Message, from);StringAssert.Contains(e.Message, to); }}
  • 95. 11 November 2009© Rob Myers 200973Test-Driven Development: By Example Kent BeckAddison-Wesley, November 2002Refactoring:Improving the Design of Existing Code Martin FowlerAddison-Wesley, July 1999The Art of Agile Development James Shore & Shane Warden O'Reilly Media, October 2007 Rob.Myers@agileInstitute.comhttp://PowersOfTwo.agileInstitute.com/

Editor's Notes

  • #3: NW story: Can’t do TDD, they haven’t even figured out unit tests yet!
  • #4: TDD is easier.My personal goal is to show you Robbie’s point of view. Perhaps you’ll make it your own.
  • #5: Codified by Kent Beck.From his XP practices.Led to automated unit-test frameworks and refactoring tools.Adapted by Agilists into two distinct practices.
  • #6: Problem:Time spent RE-testingTime spent debugging
  • #7: SolutionFastRepeatable resultsBetter than…
  • #8: Story 15 years old, at least (Phoenix).Truck stuck.Fire dept and others arrive and try to figure out what to do.Anecdotally, a young man walks up and says “Why not deflate the tires?”Developers can think about a problem and come up with a possible solution.BUT…first specify the question (Jeopardy-style)
  • #10: We’re talking about a single coding event (story?) and it’s test. If the coding cycle is months, then the delay could be months.The developer will have forgotten. The BA/PO may have forgotten, too!<done with anim and closing gap> Where do we gain value from testing? Running the test, or writing it?
  • #11: If you have to think about how you’d interact with the product, what are you doing? [Analysis]This is the final detailed analysis of a story before AND WHILE it’s being implemented. JIT Analysis!
  • #12: Reduces defects now: Tells you when a task is done, and done correctly.Reduces defects later: Comprehensive suite of isolated regression tests detect and isolate failures immediately.Much less time troubleshooting/debugging and re-testing.For developersBugs are easier and faster to fix while they’re freshBugs are found and fixed before other dependent code is writtenFewer returns from QA, more time spent on developing not fixingFor TestersSpend more time on more critical testing (not finding and validating defects)For the Whole TeamDaily measurable progressProduct health and flexibilitySanity in the workplace and enjoyable work
  • #13: Problem: Iterations imply incremental developmentChange can result in a negative feedback loop - ENTROPY: The Agilist’s DilemmaWe have to address this. It’s not easy, until it becomes easy. At first, we’d rather not check the oil…
  • #16: Problem: Dependencies
  • #17: Solution:… Actors
  • #20: One Analogy for the DesignThe suite of tests preserves all prior behavior while we address design, allowing for Emergent Designs
  • #21: AnAnalogy for theProgrammer:Each test remains as an individual investment in the behavior and the quality of the design
  • #22: Does TDD Work?Microsoft and IBM…Also, “approximately 40% fewer defects” Laurie Williams for ACMdefect rate is considerably lowerfuture enhancements easierin a dynamic market. defects quickly detected
  • #23: Weinberg’s “Are Your Lights On?” Golden ______OTIS2 data conversionOTIS2 “GUI” conversionDenali Internationalization
  • #25: Roadblocks to AdoptionDevelopers skip refactoring, don’t spend the minute to look for and clean up a new bit of code duplication.Inexperienced coaches who confuse the developer-style TDD with the team ATDDManagers waffling over the use of TDD, which limits its effectiveness…and others.
  • #26: A habit…We still use when times are tough…Because we know there is a long-term benefit.Habit: 30-days, support-groupBenefits org, team, individualDiscipline prevents regret (debt).
  • #34: We thought about “Deposit” except that’s not what it is once it’s been deposited<click>And we’re going to tackle Holding first
  • #35: Holding has a useful interface so it may convert its value to different currency, but… the conversion doesn’t really belong in Holding, does it? My gut is telling me it will be helpful to isolate it, keep it simpleIf we guess wrong? Refactor away CurrencyConverter. RARE REFACTORING!
  • #37: Read it<click>tolerance<click> won’t compile, of course
  • #38: VS writes this. Nice, in case we ever forget, but I want the test to FAIL, not THROW.
  • #40: Is this crazy?
  • #41: If it’s a constant, make it a constantOr find a simplistic implementation
  • #42: If there’s no clear refactoring, go on to the next test.
  • #43: Rodin’s chipping away whatever didn’t look like a seated manTriangulation *IS* Test-First<click>Don’t add more production BEHAVIOR without a failing test.
  • #45: This is a perfectly good design for what we’ve asked the system to do so far.As long as the design does not start to DEGRADE!
  • #47: It’s not really about reduction of duplication, but about arranging for all tests in the class.One test class per behavior group.
  • #48: What if we don’t know?Find out, or make it happen.
  • #51: Why? To isolate the problem.Note that we’re thinking about parameter lists. “Programming by intention”. If we miss one, we can refactor further, later.
  • #54: Should the converter know?
  • #55: We’re deferring the decision.<TODO: Maybe draw a sequence diagram!>
  • #56: Part of Emergent Design: Discovering that YOU need something, and building it.
  • #59: Refactor? Is there duplication?
  • #64: If you doubt yourself, just change one of the 50’s.Now there’s duplication in the test. Make a constant <TODO: do it!>
  • #65: We’re not actually going to do it, but what might it look like?
  • #67: We could do these.Or we could, as a team, test that they are impossible.What benefit in NOT doing these? [Simplicity, else each object has to be defensive, as though it were being exposed to “other programmers”]
  • #73: Which I will leave for the enthusiastic TDD programmer to complete (it ain’t hard)
  • #74: Thank you!