SlideShare a Scribd company logo
1 of 73
Realistic Test-Driven Development:Paying and PreventingTechnical Debt Rob Myers Agile Development Practices 11 November 2009 11 November 2009 © Rob Myers 2009 1
11 November 2009 © Rob Myers 2009 2 Unit testing is sooooDEPRESSING
11 November 2009 © Rob Myers 2009 3 TDD is fun, and provides much more than just unit-tests!
11 November 2009 © Rob Myers 2009 4 from XP to ATDD & BDD
11 November 2009 © Rob Myers 2009 5 waste
11 November 2009 © Rob Myers 2009 6 #1 automation public static void Main() { Console.WriteLine(     “I sure hope this works...” + myObject.Foo()); }
11 November 2009 © Rob Myers 2009 7
11 November 2009 © Rob Myers 2009 8 #2 Test-First We write a test before writing the code that makes it pass.
Why Wait? 11 November 2009 © Rob Myers 2009 9 Code Test Months Code Test Weeks Code Test Days Code Test
What If? 11 November 2009 © Rob Myers 2009 10 Code Run Test Test Write Test Run Test Run Test Run Test
Benefits of Test-First Just-In-Time analysis. We know when something is… …done. …done correctly. …broken. …and fixed! 11 November 2009 © Rob Myers 2009 11
11 November 2009 © Rob Myers 2009 12
11 November 2009 © Rob Myers 2009 13 #3 Any behavior-preserving change that improves maintainability.
11 November 2009 © Rob Myers 2009 14
11 November 2009 © Rob Myers 2009 15
11 November 2009 © Rob Myers 2009 16 #4 Mock Objects
Prep road-data for new Mars Colony Road/Canal Service ,[object Object]
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 2009 17 #5 A To-Do List
11 November 2009 © Rob Myers 2009 18 Analogies  &  Metaphors
11 November 2009 © Rob Myers 2009 19
11 November 2009 © Rob Myers 2009 20
11 November 2009 © Rob Myers 2009 21 “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 2009 22 real value
11 November 2009 © Rob Myers 2009 23 architectural perspective
11 November 2009 © Rob Myers 2009 24 roadblocks
11 November 2009 © Rob Myers 2009 25 discipline
11 November 2009 © Rob Myers 2009 26 steps Write 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 2009 27  given  when  then
11 November 2009 © Rob Myers 2009 28 TDD Demo
11 November 2009 © Rob Myers 2009 29 Basic UML Class Diagrams Foo - intprivateVariable + intPublicMethod() Bar Baz + void AbstractMethod(         object parameter) - void PrivateMethod()
11 November 2009 © Rob Myers 2009 30 Global Currency Money-Market Account
11 November 2009 © Rob Myers 2009 31 Global ATMAccess
Stories As 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 2009 32
Primary Objects 11 November 2009 © Rob Myers 2009 33 Currency Account Holding
More Detail 11 November 2009 © Rob Myers 2009 34 Currency Holding value currency currencyConverter CurrencyConverter convert value to   another currency
Start Simple To Do ,[object Object]
When value is zero.11 November 2009 © Rob Myers 2009 35
Specification, and Interface 11 November 2009 © Rob Myers 2009 36 [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 2009 37 using 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 2009 38 class CurrencyConverter {     public double convert(         double value, string from, string to) { return 0.0;     } }
Just Enough to Pass 11 November 2009 © Rob Myers 2009 39 public double convert(     double value, string from, string to) {     return 100.0; }
a.  Refactor Away the Duplication 11 November 2009 © Rob Myers 2009 40 [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.  Triangulate 11 November 2009 © Rob Myers 2009 41
11 November 2009 © Rob Myers 2009 42 We don’t add any behavior without a failing test… Rodin’s The Thinker, photo by CJ on Wikipedia
Triangulating Test 11 November 2009 © Rob Myers 2009 43 [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 2009 44 class CurrencyConverter {     public double convert(         double value, string from, string to) {         return value;     } }
Maintain the Tests 11 November 2009 © Rob Myers 2009 45 [TestMethod] public void GivesZeroWhenValueIsZero() { CurrencyConverter converter = new CurrencyConverter();     // ... } [TestMethod] public void GivesSameValueWhenSameCurrencyRequested() { CurrencyConverter converter = new CurrencyConverter();     // ... }
TestInitialize Runs Before Each Test 11 November 2009 © Rob Myers 2009 46 private 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 2009 47 [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 2009 48 [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 2009 49 public double convert(     double value, string from, string to) {     if (to.Equals(from))         return value;     return value * 0.5000; }
…Refactor… 11 November 2009 © Rob Myers 2009 50 public 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 It To Do ,[object Object]
When value is zero.
Fix the hard-coded ConversionRate11 November 2009 © Rob Myers 2009 51
11 November 2009 © Rob Myers 2009 52 Well, What is It??? Where does it come from?
Circumstantial Coupling? 11 November 2009 © Rob Myers 2009 53 CurrencyConverter
Managing the Transaction 11 November 2009 © Rob Myers 2009 54 Account CurrencyConverter Holding Holding Holding ConversionRates Holding
Another Object Emerges To Do ,[object Object]
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 2009 55
New Test Class 11 November 2009 © Rob Myers 2009 56 using 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));     } }
Fail 11 November 2009 © Rob Myers 2009 57 public 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 Coy 11 November 2009 © Rob Myers 2009 58 public 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 Behavior 11 November 2009 © Rob Myers 2009 59 public 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 Do ,[object Object]
When value is zero.

More Related Content

What's hot

What's hot (10)

Structure on a freeform world
Structure on a freeform worldStructure on a freeform world
Structure on a freeform world
 
Asynchronous JavaScript Programming with Callbacks & Promises
Asynchronous JavaScript Programming with Callbacks & PromisesAsynchronous JavaScript Programming with Callbacks & Promises
Asynchronous JavaScript Programming with Callbacks & Promises
 
Tdd iPhone For Dummies
Tdd iPhone For DummiesTdd iPhone For Dummies
Tdd iPhone For Dummies
 
React Native Evening
React Native EveningReact Native Evening
React Native Evening
 
Javascript Promises/Q Library
Javascript Promises/Q LibraryJavascript Promises/Q Library
Javascript Promises/Q Library
 
Callback Function
Callback FunctionCallback Function
Callback Function
 
Refactoring
RefactoringRefactoring
Refactoring
 
Kotlin a problem solver - gdd extended pune
Kotlin   a problem solver - gdd extended puneKotlin   a problem solver - gdd extended pune
Kotlin a problem solver - gdd extended pune
 
Functions in javascript
Functions in javascriptFunctions in javascript
Functions in javascript
 
Advanced Javascript
Advanced JavascriptAdvanced Javascript
Advanced Javascript
 

Viewers also liked

IFAD Egg Noodles_IMC_Campaign
IFAD Egg Noodles_IMC_CampaignIFAD Egg Noodles_IMC_Campaign
IFAD Egg Noodles_IMC_CampaignAbu Jubaer
 
L'activité e-commerce des TPE-PME - Edition 2011
L'activité e-commerce des TPE-PME - Edition 2011L'activité e-commerce des TPE-PME - Edition 2011
L'activité e-commerce des TPE-PME - Edition 2011PowerBoutique
 
Bushrod_Resume 2015
Bushrod_Resume 2015Bushrod_Resume 2015
Bushrod_Resume 2015Lena Bushrod
 
Interview b2b Summit 7 juillet 2016 Laurent Ollivier Aressy BtoB
Interview b2b Summit 7 juillet 2016 Laurent Ollivier Aressy BtoBInterview b2b Summit 7 juillet 2016 Laurent Ollivier Aressy BtoB
Interview b2b Summit 7 juillet 2016 Laurent Ollivier Aressy BtoBaressy
 
Enlace Ciudadano Nro 235 tema: reuniones de representantes del ecuador con ch...
Enlace Ciudadano Nro 235 tema: reuniones de representantes del ecuador con ch...Enlace Ciudadano Nro 235 tema: reuniones de representantes del ecuador con ch...
Enlace Ciudadano Nro 235 tema: reuniones de representantes del ecuador con ch...Presidencia de la República del Ecuador
 
FESCO CHINESE PRESENTATION 30 march
FESCO CHINESE PRESENTATION 30 marchFESCO CHINESE PRESENTATION 30 march
FESCO CHINESE PRESENTATION 30 marchArnaud Veere
 

Viewers also liked (12)

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

Similar to Test-Driven Development Overview

The Value of Refactoring on an Agile Team
The Value of Refactoring on an Agile TeamThe Value of Refactoring on an Agile Team
The Value of Refactoring on an Agile TeamRob Myers
 
Automated Testing with Ruby
Automated Testing with RubyAutomated Testing with Ruby
Automated Testing with RubyKeith Pitty
 
What’s new in .NET
What’s new in .NETWhat’s new in .NET
What’s new in .NETDoommaker
 
Advanced Testing on RubyEnRails '09
Advanced Testing on RubyEnRails '09Advanced Testing on RubyEnRails '09
Advanced Testing on RubyEnRails '09Edwin Vlieg
 
Essential Test-Driven Development
Essential Test-Driven DevelopmentEssential Test-Driven Development
Essential Test-Driven DevelopmentTechWell
 
Intro To JavaScript Unit Testing - Ran Mizrahi
Intro To JavaScript Unit Testing - Ran MizrahiIntro To JavaScript Unit Testing - Ran Mizrahi
Intro To JavaScript Unit Testing - Ran MizrahiRan Mizrahi
 
Essential Test-Driven Development
Essential Test-Driven DevelopmentEssential Test-Driven Development
Essential Test-Driven DevelopmentTechWell
 
Unit Testing for Great Justice
Unit Testing for Great JusticeUnit Testing for Great Justice
Unit Testing for Great JusticeDomenic Denicola
 
PHP7. Game Changer.
PHP7. Game Changer. PHP7. Game Changer.
PHP7. Game Changer. Haim Michael
 
Web technologies-course 12.pptx
Web technologies-course 12.pptxWeb technologies-course 12.pptx
Web technologies-course 12.pptxStefan Oprea
 
ECMAScript.Next ECMAScipt 6
ECMAScript.Next ECMAScipt 6ECMAScript.Next ECMAScipt 6
ECMAScript.Next ECMAScipt 6Kevin DeRudder
 
Refactoring Simple Example
Refactoring Simple ExampleRefactoring Simple Example
Refactoring Simple Exampleliufabin 66688
 
.NET Coding Standards For The Real World (2012)
.NET Coding Standards For The Real World (2012).NET Coding Standards For The Real World (2012)
.NET Coding Standards For The Real World (2012)David McCarter
 

Similar to Test-Driven Development Overview (20)

The Value of Refactoring on an Agile Team
The Value of Refactoring on an Agile TeamThe Value of Refactoring on an Agile Team
The Value of Refactoring on an Agile Team
 
Automated Testing with Ruby
Automated Testing with RubyAutomated Testing with Ruby
Automated Testing with Ruby
 
What’s new in .NET
What’s new in .NETWhat’s new in .NET
What’s new in .NET
 
Advanced Testing on RubyEnRails '09
Advanced Testing on RubyEnRails '09Advanced Testing on RubyEnRails '09
Advanced Testing on RubyEnRails '09
 
Essential Test-Driven Development
Essential Test-Driven DevelopmentEssential Test-Driven Development
Essential Test-Driven Development
 
Intro To JavaScript Unit Testing - Ran Mizrahi
Intro To JavaScript Unit Testing - Ran MizrahiIntro To JavaScript Unit Testing - Ran Mizrahi
Intro To JavaScript Unit Testing - Ran Mizrahi
 
Essential Test-Driven Development
Essential Test-Driven DevelopmentEssential Test-Driven Development
Essential Test-Driven Development
 
JS Class 2016
JS Class 2016JS Class 2016
JS Class 2016
 
JS class slides (2016)
JS class slides (2016)JS class slides (2016)
JS class slides (2016)
 
Unit Testing for Great Justice
Unit Testing for Great JusticeUnit Testing for Great Justice
Unit Testing for Great Justice
 
From dot net_to_rails
From dot net_to_railsFrom dot net_to_rails
From dot net_to_rails
 
Promises, Promises
Promises, PromisesPromises, Promises
Promises, Promises
 
PHP7. Game Changer.
PHP7. Game Changer. PHP7. Game Changer.
PHP7. Game Changer.
 
Web technologies-course 12.pptx
Web technologies-course 12.pptxWeb technologies-course 12.pptx
Web technologies-course 12.pptx
 
ECMAScript.Next ECMAScipt 6
ECMAScript.Next ECMAScipt 6ECMAScript.Next ECMAScipt 6
ECMAScript.Next ECMAScipt 6
 
Es.next
Es.nextEs.next
Es.next
 
Test driven development
Test driven developmentTest driven development
Test driven development
 
Refactoring Simple Example
Refactoring Simple ExampleRefactoring Simple Example
Refactoring Simple Example
 
.NET Coding Standards For The Real World (2012)
.NET Coding Standards For The Real World (2012).NET Coding Standards For The Real World (2012)
.NET Coding Standards For The Real World (2012)
 
UI Testing
UI TestingUI Testing
UI Testing
 

More from Rob Myers

The Business Value of Agile Engineering Practices
The Business Value of Agile Engineering PracticesThe Business Value of Agile Engineering Practices
The Business Value of Agile Engineering PracticesRob Myers
 
The Business Value of Test-Driven Development
The Business Value of Test-Driven DevelopmentThe Business Value of Test-Driven Development
The Business Value of Test-Driven DevelopmentRob Myers
 
Roots of Agility - Better Software Agile Dev Practices East 2014 Keynote
Roots of Agility - Better Software Agile Dev Practices East 2014 KeynoteRoots of Agility - Better Software Agile Dev Practices East 2014 Keynote
Roots of Agility - Better Software Agile Dev Practices East 2014 KeynoteRob Myers
 
Assessing the business value of Agile Engineering Practices
Assessing the business value of Agile Engineering PracticesAssessing the business value of Agile Engineering Practices
Assessing the business value of Agile Engineering PracticesRob Myers
 
The Business Value of Agile Engineering Practices
The Business Value of Agile Engineering PracticesThe Business Value of Agile Engineering Practices
The Business Value of Agile Engineering PracticesRob Myers
 
Unit-Testing Your Legacy JavaScript
Unit-Testing Your Legacy JavaScriptUnit-Testing Your Legacy JavaScript
Unit-Testing Your Legacy JavaScriptRob Myers
 
Mock Objects from Concept to Code
Mock Objects from Concept to CodeMock Objects from Concept to Code
Mock Objects from Concept to CodeRob Myers
 
Technical Debt
Technical DebtTechnical Debt
Technical DebtRob Myers
 
Successful Teams are TDD Teams
Successful Teams are TDD TeamsSuccessful Teams are TDD Teams
Successful Teams are TDD TeamsRob Myers
 
TDD? Sure, but What About My Legacy Code?
TDD? Sure, but What About My Legacy Code?TDD? Sure, but What About My Legacy Code?
TDD? Sure, but What About My Legacy Code?Rob Myers
 
Metrics In An Agile World
Metrics In An Agile WorldMetrics In An Agile World
Metrics In An Agile WorldRob Myers
 
Successful Teams are Test-Driven Teams
Successful Teams are Test-Driven TeamsSuccessful Teams are Test-Driven Teams
Successful Teams are Test-Driven TeamsRob Myers
 
Agile Testing: Solving the Agilist\'s Dilemma
Agile Testing: Solving the Agilist\'s DilemmaAgile Testing: Solving the Agilist\'s Dilemma
Agile Testing: Solving the Agilist\'s DilemmaRob Myers
 

More from Rob Myers (13)

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

Test-Driven Development Overview

  • 1. Realistic Test-Driven Development:Paying and PreventingTechnical Debt Rob Myers Agile Development Practices 11 November 2009 11 November 2009 © Rob Myers 2009 1
  • 2. 11 November 2009 © Rob Myers 2009 2 Unit testing is sooooDEPRESSING
  • 3. 11 November 2009 © Rob Myers 2009 3 TDD is fun, and provides much more than just unit-tests!
  • 4. 11 November 2009 © Rob Myers 2009 4 from XP to ATDD & BDD
  • 5. 11 November 2009 © Rob Myers 2009 5 waste
  • 6. 11 November 2009 © Rob Myers 2009 6 #1 automation public static void Main() { Console.WriteLine( “I sure hope this works...” + myObject.Foo()); }
  • 7. 11 November 2009 © Rob Myers 2009 7
  • 8. 11 November 2009 © Rob Myers 2009 8 #2 Test-First We write a test before writing the code that makes it pass.
  • 9. Why Wait? 11 November 2009 © Rob Myers 2009 9 Code Test Months Code Test Weeks Code Test Days Code Test
  • 10. What If? 11 November 2009 © Rob Myers 2009 10 Code Run Test Test Write Test Run Test Run Test Run Test
  • 11. Benefits of Test-First Just-In-Time analysis. We know when something is… …done. …done correctly. …broken. …and fixed! 11 November 2009 © Rob Myers 2009 11
  • 12. 11 November 2009 © Rob Myers 2009 12
  • 13. 11 November 2009 © Rob Myers 2009 13 #3 Any behavior-preserving change that improves maintainability.
  • 14. 11 November 2009 © Rob Myers 2009 14
  • 15. 11 November 2009 © Rob Myers 2009 15
  • 16. 11 November 2009 © Rob Myers 2009 16 #4 Mock Objects
  • 17.
  • 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 2009 17 #5 A To-Do List
  • 23. 11 November 2009 © Rob Myers 2009 18 Analogies & Metaphors
  • 24. 11 November 2009 © Rob Myers 2009 19
  • 25. 11 November 2009 © Rob Myers 2009 20
  • 26. 11 November 2009 © Rob Myers 2009 21 “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 2009 22 real value
  • 28. 11 November 2009 © Rob Myers 2009 23 architectural perspective
  • 29. 11 November 2009 © Rob Myers 2009 24 roadblocks
  • 30. 11 November 2009 © Rob Myers 2009 25 discipline
  • 31. 11 November 2009 © Rob Myers 2009 26 steps Write 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 2009 27  given  when  then
  • 33. 11 November 2009 © Rob Myers 2009 28 TDD Demo
  • 34. 11 November 2009 © Rob Myers 2009 29 Basic UML Class Diagrams Foo - intprivateVariable + intPublicMethod() Bar Baz + void AbstractMethod( object parameter) - void PrivateMethod()
  • 35. 11 November 2009 © Rob Myers 2009 30 Global Currency Money-Market Account
  • 36. 11 November 2009 © Rob Myers 2009 31 Global ATMAccess
  • 37. Stories As 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 2009 32
  • 38. Primary Objects 11 November 2009 © Rob Myers 2009 33 Currency Account Holding
  • 39. More Detail 11 November 2009 © Rob Myers 2009 34 Currency Holding value currency currencyConverter CurrencyConverter convert value to another currency
  • 40.
  • 41. When value is zero.11 November 2009 © Rob Myers 2009 35
  • 42. Specification, and Interface 11 November 2009 © Rob Myers 2009 36 [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 2009 37 using 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 2009 38 class CurrencyConverter { public double convert( double value, string from, string to) { return 0.0; } }
  • 45. Just Enough to Pass 11 November 2009 © Rob Myers 2009 39 public double convert( double value, string from, string to) { return 100.0; }
  • 46. a. Refactor Away the Duplication 11 November 2009 © Rob Myers 2009 40 [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. Triangulate 11 November 2009 © Rob Myers 2009 41
  • 48. 11 November 2009 © Rob Myers 2009 42 We don’t add any behavior without a failing test… Rodin’s The Thinker, photo by CJ on Wikipedia
  • 49. Triangulating Test 11 November 2009 © Rob Myers 2009 43 [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 2009 44 class CurrencyConverter { public double convert( double value, string from, string to) { return value; } }
  • 51. Maintain the Tests 11 November 2009 © Rob Myers 2009 45 [TestMethod] public void GivesZeroWhenValueIsZero() { CurrencyConverter converter = new CurrencyConverter(); // ... } [TestMethod] public void GivesSameValueWhenSameCurrencyRequested() { CurrencyConverter converter = new CurrencyConverter(); // ... }
  • 52. TestInitialize Runs Before Each Test 11 November 2009 © Rob Myers 2009 46 private 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 2009 47 [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 2009 48 [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 2009 49 public 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 2009 50 public 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.
  • 59. Fix the hard-coded ConversionRate11 November 2009 © Rob Myers 2009 51
  • 60. 11 November 2009 © Rob Myers 2009 52 Well, What is It??? Where does it come from?
  • 61. Circumstantial Coupling? 11 November 2009 © Rob Myers 2009 53 CurrencyConverter
  • 62. Managing the Transaction 11 November 2009 © Rob Myers 2009 54 Account CurrencyConverter Holding Holding Holding ConversionRates Holding
  • 63.
  • 67. Make a factory for ConversionRates that uses the FOREX.com Web Service.11 November 2009 © Rob Myers 2009 55
  • 68. New Test Class 11 November 2009 © Rob Myers 2009 56 using 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. Fail 11 November 2009 © Rob Myers 2009 57 public 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 Coy 11 November 2009 © Rob Myers 2009 58 public 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 Behavior 11 November 2009 © Rob Myers 2009 59 public 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; } }
  • 72.
  • 76. Make a factory for ConversionRates that uses the FOREX.com Web Service.11 November 2009 © Rob Myers 2009 60
  • 77. Fix SetUp 11 November 2009 © Rob Myers 2009 61 [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 2009 62 public 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 Value 11 November 2009 © Rob Myers 2009 63 public 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.
  • 84. Make a factory for ConversionRates that uses the FOREX.com Web Service.11 November 2009 © Rob Myers 2009 64
  • 85. What is the Missing Piece? 11 November 2009 © Rob Myers 2009 65 ConversionRates rates = ConversionRates.ByAccountAnd???( account, ???);
  • 86.
  • 87. ConversionRates returns 1/rate if inverse rate found.
  • 88. ConversionRates throws when rate not found.11 November 2009 © Rob Myers 2009 66
  • 89. Testing Exceptional Behavior 11 November 2009 © Rob Myers 2009 67 [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 Exception 11 November 2009 © Rob Myers 2009 68 using System; public class RateNotFoundException : Exception { }
  • 91. 11 November 2009 © Rob Myers 2009 69
  • 92. Back in ConversionRates 11 November 2009 © Rob Myers 2009 70 public double GetRate(string from, string to) { if (!rates.ContainsKey(Key(from, to))) throw new RateNotFoundException(); return rates[Key(from, to)]; }
  • 93. An Alternative Test 11 November 2009 © Rob Myers 2009 71 [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 Exception 11 November 2009 © Rob Myers 2009 72 [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 2009 73 Test-Driven Development: By Example Kent Beck Addison-Wesley, November 2002 Refactoring: Improving the Design of Existing Code Martin FowlerAddison-Wesley, July 1999 The Art of Agile Development James Shore & Shane Warden O'Reilly Media, October 2007 Rob.Myers@agileInstitute.com http://PowersOfTwo.agileInstitute.com/

Editor's Notes

  1. NW story: Can’t do TDD, they haven’t even figured out unit tests yet!
  2. TDD is easier.My personal goal is to show you Robbie’s point of view. Perhaps you’ll make it your own.
  3. Codified by Kent Beck.From his XP practices.Led to automated unit-test frameworks and refactoring tools.Adapted by Agilists into two distinct practices.
  4. Problem:Time spent RE-testingTime spent debugging
  5. SolutionFastRepeatable resultsBetter than…
  6. 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)
  7. 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?
  8. 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!
  9. 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
  10. 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…
  11. Problem: Dependencies
  12. Solution:… Actors
  13. One Analogy for the DesignThe suite of tests preserves all prior behavior while we address design, allowing for Emergent Designs
  14. AnAnalogy for theProgrammer:Each test remains as an individual investment in the behavior and the quality of the design
  15. 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
  16. Weinberg’s “Are Your Lights On?” Golden ______OTIS2 data conversionOTIS2 “GUI” conversionDenali Internationalization
  17. 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.
  18. 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).
  19. 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
  20. 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!
  21. Read it<click>tolerance<click> won’t compile, of course
  22. VS writes this. Nice, in case we ever forget, but I want the test to FAIL, not THROW.
  23. Is this crazy?
  24. If it’s a constant, make it a constantOr find a simplistic implementation
  25. If there’s no clear refactoring, go on to the next test.
  26. 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.
  27. 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!
  28. It’s not really about reduction of duplication, but about arranging for all tests in the class.One test class per behavior group.
  29. What if we don’t know?Find out, or make it happen.
  30. 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.
  31. Should the converter know?
  32. We’re deferring the decision.<TODO: Maybe draw a sequence diagram!>
  33. Part of Emergent Design: Discovering that YOU need something, and building it.
  34. Refactor? Is there duplication?
  35. If you doubt yourself, just change one of the 50’s.Now there’s duplication in the test. Make a constant <TODO: do it!>
  36. We’re not actually going to do it, but what might it look like?
  37. 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”]
  38. Which I will leave for the enthusiastic TDD programmer to complete (it ain’t hard)
  39. Thank you!