際際滷

際際滷Share a Scribd company logo
Test Driven Development
(TDD)
Sameer Soni
@_sameersoni
What TDD is not
 is not about Testing
 is not Test Last
What TDD is
is about
evolving the design of the system through Tests.
Game Of Life - Stories
1. Any live cell with fewer than two live neighbours dies, as if caused by
under-population.
2. Any live cell with two or three live neighbours lives on to the next
generation.
3. Any live cell with more than three live neighbours dies, as if by
overcrowding.
4. Any dead cell with exactly three live neighbours becomes a live cell, as
if by reproduction.
Specify what test should do
[TestClass]	
 
	
 	
 	
 	
 public	
 class	
 GameOfLifeTest	
 
	
 	
 	
 	
 {	
 
	
 	
 	
 	
 	
 	
 	
 	
 [TestMethod]	
 
	
 	
 	
 	
 	
 	
 	
 	
 public	
 void	
 LiveCell_WithLessThanTwoNeighbour_Dies()	
 
	
 	
 	
 	
 	
 	
 	
 	
 {	
 
	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 //Given	
 
	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 CellState	
 cellState	
 =	
 CellState.ALIVE;	
 
	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 int	
 neighbourCount	
 =	
 1;	
 
	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 //When	
 
	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 CellState	
 result	
 =	
 LifeRules.GetNewState(cellState,	
 neighbourCount);	
 
	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 //Then	
 
	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 Assert.AreEqual(CellState.DEAD,	
 result);	
 
	
 	
 	
 	
 	
 	
 	
 	
 }	
 
	
 	
 	
 	
 }	
 
}
Write enough to compile
public	
 class	
 LifeRules	
 
{	
 
	
 	
 	
 public	
 static	
 CellState	
 GetNewState(CellState	
 cellState,	
 int	
 neighbourCount)	
 
	
 	
 	
 {	
 
	
 	
 	
 	
 	
 	
 throw	
 new	
 System.NotImplementedException();	
 
	
 	
 	
 }	
 
}
RED
Write enough to pass your
test
public	
 class	
 LifeRules	
 
{	
 
	
 	
 	
 public	
 static	
 CellState	
 GetNewState(CellState	
 currentState,	
 int	
 neighbourCount)	
 
	
 	
 	
 {	
 	
 	
 	
 
	
 	
 	
 	
 	
 	
 	
 if	
 (currentState	
 ==	
 CellState.ALIVE	
 &&	
 neighbourCount	
 <	
 2)	
 
	
 	
 	
 	
 	
 	
 	
 {	
 
	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 return	
 CellState.DEAD;	
 
	
 	
 	
 	
 	
 	
 	
 }	
 
	
 	
 	
 	
 	
 	
 	
 return	
 currentState;	
 
	
 	
 	
 }	
 
}
GREEN
General Test Structure
Minimum Setup for Test (Given)
Invoke the event (When)
Verify assertions (Then)
Add Test for next story
[TestMethod]	
 
public	
 void	
 LiveCell_WithTwoOrThreeNeighbour_Survives()	
 
{	
 
	
 	
 	
 	
 //Given	
 
	
 	
 	
 	
 CellState	
 cellState	
 =	
 CellState.ALIVE;	
 
	
 	
 	
 	
 int	
 neighbourCount	
 =	
 3;	
 
	
 	
 	
 	
 //When	
 
	
 	
 	
 	
 CellState	
 result	
 =	
 LifeRules.GetNewState(cellState,	
 neighbourCount);	
 
	
 	
 	
 	
 //Then	
 
	
 	
 	
 	
 Assert.AreEqual(CellState.ALIVE,	
 result);	
 
}
Add Implementation
public	
 class	
 LifeRules	
 
{	
 
	
 	
 	
 public	
 static	
 CellState	
 GetNewState(CellState	
 currentState,	
 int	
 neighbourCount)	
 
	
 	
 	
 {	
 	
 	
 	
 
	
 	
 	
 	
 	
 	
 	
 if	
 (currentState	
 ==	
 CellState.ALIVE	
 &&	
 neighbourCount	
 <	
 2)	
 
	
 	
 	
 	
 	
 	
 	
 {	
 
	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 return	
 CellState.DEAD;	
 
	
 	
 	
 	
 	
 	
 	
 }	
 
if	
 (currentState	
 ==	
 CellState.ALIVE	
 &&	
 neighbourCount	
 >	
 3)	
 
	
 	
 	
 	
 	
 {	
 
	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 return	
 CellState.DEAD;	
 
	
 	
 	
 	
 	
 	
 	
 }	
 
	
 	
 	
 	
 	
 	
 	
 return	
 currentState;	
 
	
 	
 	
 }	
 
}
Add Test for two more stories
[TestMethod]	
 
public	
 void	
 LiveCell_WithMoreThanThreeNeighbour_Dies()	
 
{	
 
	
 	
 	
 	
 //Given	
 
	
 	
 	
 	
 CellState	
 cellState	
 =	
 CellState.ALIVE;	
 
	
 	
 	
 	
 	
 	
 	
 int	
 neighbourCount	
 =	
 4;	
 
	
 	
 	
 	
 //When	
 
	
 	
 	
 	
 CellState	
 result	
 =	
 LifeRules.GetNewState(cellState,	
 neighbourCount);	
 
	
 	
 	
 //Then	
 
	
 	
 	
 Assert.AreEqual(CellState.DEAD,	
 result);	
 
}	
 
[TestMethod]	
 
public	
 void	
 DeadCell_WithThreeNeighbour_Lives()	
 
{	
 
	
 	
 	
 	
 //Given	
 
	
 	
 	
 	
 CellState	
 cellState	
 =	
 CellState.DEAD;	
 
	
 	
 	
 	
 int	
 neighbourCount	
 =	
 3;	
 
	
 	
 	
 	
 //When	
 
	
 	
 	
 	
 CellState	
 result	
 =	
 LifeRules.GetNewState(cellState,	
 neighbourCount);	
 
	
 	
 	
 	
 //Then	
 
	
 	
 	
 	
 Assert.AreEqual(CellState.ALIVE,	
 result);	
 
}
Add remaining implementations
public	
 class	
 LifeRules	
 
{	
 
	
 	
 	
 	
 public	
 static	
 CellState	
 GetNewState(CellState	
 currentState,	
 int	
 neighbourCount)	
 
	
 	
 	
 	
 {	
 	
 	
 	
 
	
 	
 	
 	
 	
 	
 	
 	
 if	
 (currentState	
 ==	
 CellState.ALIVE	
 &&	
 neighbourCount	
 <	
 2)	
 
	
 	
 	
 	
 	
 	
 	
 	
 {	
 
	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 return	
 CellState.DEAD;	
 
	
 	
 	
 	
 	
 	
 	
 	
 }	
 
	
 	
 	
 	
 	
 	
 	
 	
 if	
 (currentState	
 ==	
 CellState.ALIVE	
 &&	
 neighbourCount	
 >	
 3)	
 
	
 	
 	
 	
 	
 	
 	
 	
 {	
 
	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 return	
 CellState.DEAD;	
 
	
 	
 	
 	
 	
 	
 	
 	
 }	
 
	
 	
 	
 	
 	
 	
 	
 	
 if	
 (currentState	
 ==	
 CellState.DEAD	
 &&	
 neighbourCount	
 ==	
 3)	
 
	
 	
 	
 	
 	
 	
 	
 	
 {	
 
	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 return	
 CellState.ALIVE;	
 
	
 	
 	
 	
 	
 	
 	
 	
 }	
 
	
 	
 	
 	
 	
 	
 	
 	
 return	
 currentState;	
 
	
 	
 	
 	
 }	
 
}
REFACTOR
Refactored Code
public	
 class	
 LifeRules	
 
{	
 
	
 	
 	
 	
 public	
 static	
 CellState	
 GetNewState(CellState	
 currentState,	
 int	
 neighbourCount)	
 
	
 	
 	
 	
 {	
 
	
 	
 	
 	
 	
 	
 	
 	
 switch	
 (currentState)	
 
	
 	
 	
 	
 	
 	
 	
 	
 {	
 
	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 case	
 CellState.ALIVE:	
 
	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 if	
 (neighbourCount	
 <	
 2	
 ||	
 neighbourCount	
 >	
 3)	
 
	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 return	
 CellState.DEAD;	
 
	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 break;	
 
	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 case	
 CellState.DEAD:	
 
	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 if	
 (neighbourCount	
 ==	
 3)	
 
	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 return	
 CellState.ALIVE;	
 
	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 break;	
 
	
 	
 	
 	
 	
 	
 	
 	
 }	
 
	
 	
 	
 	
 	
 	
 	
 	
 return	
 currentState;	
 
	
 	
 	
 	
 }	
 
}
Theme of TDD
FAIL
PASS
REFACTOR
Crux of TDD
 Analysing the minimalistic need of story and
implementing it in the cleanest way possible
 Design the code unit by unit
Bene鍖ts of TDD
 Deliver what is necessary.
 Helps take baby steps.
 System so developed does just what is required, no
more, no less.
 No future stories development (YAGNI - You aint
gonna need it).
 Better Code Coverage
TDD results in decoupled design
 Favours composition over inheritance.
 Small loosely coupled classes.
 Promotes coding to supertypes.
Bene鍖ts of TDD
 Increased con鍖dence in developers working on test-
driven codebases
 Better code quality (in particular, less coupling and
higher cohesion)
 Improved maintainability and changeability of
codebases
 Ability to refactor without fear of breaking things
Bene鍖ts of TDD
 Test act as a "living speci鍖cation" of expected behaviour
 Smaller production codebases with more simple designs
 Easier detection of 鍖aws in the interactions between
objects
 Reduced need for manual testing
 Faster feedback loop for discovering whether an
implementation is correct
Removes Code Smells
 Duplicate Code
 Long methods
 Classes with too much code
 Lot of unused code
 Too many private methods
 Excessive Overloading
Costs of TDD
Claim - Slower per-feature development work because tests take
a lot of time to write
Rebut - Prevents speculative design and living with debugger.
Claim - Tests are code in themselves, require maintenance and
thats overhead.
Rebut - Better than maintaining bug list.
Claim - E鍖ectiveness is highly dependent on experience/
discipline of dev team.
Rebut - TDD is not a silver bullet. Just like with any skill, one
needs time to hone their skills.
Good Test are
 Small
 Expressive
 Maintainable
 Should execute fast
 talk Domain language
 must be thorough
 automated
 repeatable
Flavours of Test
 Unit Tests
 Integration Tests
 End to End Tests
Unit testing frameworks
 JUnit/TestNG for Java
 NUnit/MsTest for C#
 Minitest/TestUnit for Ruby
 pyUnit/unittest for Python
Thank you

More Related Content

Test Driven Development (TDD)

  • 2. What TDD is not is not about Testing is not Test Last
  • 3. What TDD is is about evolving the design of the system through Tests.
  • 4. Game Of Life - Stories 1. Any live cell with fewer than two live neighbours dies, as if caused by under-population. 2. Any live cell with two or three live neighbours lives on to the next generation. 3. Any live cell with more than three live neighbours dies, as if by overcrowding. 4. Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction.
  • 5. Specify what test should do [TestClass] public class GameOfLifeTest { [TestMethod] public void LiveCell_WithLessThanTwoNeighbour_Dies() { //Given CellState cellState = CellState.ALIVE; int neighbourCount = 1; //When CellState result = LifeRules.GetNewState(cellState, neighbourCount); //Then Assert.AreEqual(CellState.DEAD, result); } } }
  • 6. Write enough to compile public class LifeRules { public static CellState GetNewState(CellState cellState, int neighbourCount) { throw new System.NotImplementedException(); } }
  • 7. RED
  • 8. Write enough to pass your test public class LifeRules { public static CellState GetNewState(CellState currentState, int neighbourCount) { if (currentState == CellState.ALIVE && neighbourCount < 2) { return CellState.DEAD; } return currentState; } }
  • 10. General Test Structure Minimum Setup for Test (Given) Invoke the event (When) Verify assertions (Then)
  • 11. Add Test for next story [TestMethod] public void LiveCell_WithTwoOrThreeNeighbour_Survives() { //Given CellState cellState = CellState.ALIVE; int neighbourCount = 3; //When CellState result = LifeRules.GetNewState(cellState, neighbourCount); //Then Assert.AreEqual(CellState.ALIVE, result); }
  • 12. Add Implementation public class LifeRules { public static CellState GetNewState(CellState currentState, int neighbourCount) { if (currentState == CellState.ALIVE && neighbourCount < 2) { return CellState.DEAD; } if (currentState == CellState.ALIVE && neighbourCount > 3) { return CellState.DEAD; } return currentState; } }
  • 13. Add Test for two more stories [TestMethod] public void LiveCell_WithMoreThanThreeNeighbour_Dies() { //Given CellState cellState = CellState.ALIVE; int neighbourCount = 4; //When CellState result = LifeRules.GetNewState(cellState, neighbourCount); //Then Assert.AreEqual(CellState.DEAD, result); } [TestMethod] public void DeadCell_WithThreeNeighbour_Lives() { //Given CellState cellState = CellState.DEAD; int neighbourCount = 3; //When CellState result = LifeRules.GetNewState(cellState, neighbourCount); //Then Assert.AreEqual(CellState.ALIVE, result); }
  • 14. Add remaining implementations public class LifeRules { public static CellState GetNewState(CellState currentState, int neighbourCount) { if (currentState == CellState.ALIVE && neighbourCount < 2) { return CellState.DEAD; } if (currentState == CellState.ALIVE && neighbourCount > 3) { return CellState.DEAD; } if (currentState == CellState.DEAD && neighbourCount == 3) { return CellState.ALIVE; } return currentState; } }
  • 16. Refactored Code public class LifeRules { public static CellState GetNewState(CellState currentState, int neighbourCount) { switch (currentState) { case CellState.ALIVE: if (neighbourCount < 2 || neighbourCount > 3) return CellState.DEAD; break; case CellState.DEAD: if (neighbourCount == 3) return CellState.ALIVE; break; } return currentState; } }
  • 18. Crux of TDD Analysing the minimalistic need of story and implementing it in the cleanest way possible Design the code unit by unit
  • 19. Bene鍖ts of TDD Deliver what is necessary. Helps take baby steps. System so developed does just what is required, no more, no less. No future stories development (YAGNI - You aint gonna need it). Better Code Coverage
  • 20. TDD results in decoupled design Favours composition over inheritance. Small loosely coupled classes. Promotes coding to supertypes.
  • 21. Bene鍖ts of TDD Increased con鍖dence in developers working on test- driven codebases Better code quality (in particular, less coupling and higher cohesion) Improved maintainability and changeability of codebases Ability to refactor without fear of breaking things
  • 22. Bene鍖ts of TDD Test act as a "living speci鍖cation" of expected behaviour Smaller production codebases with more simple designs Easier detection of 鍖aws in the interactions between objects Reduced need for manual testing Faster feedback loop for discovering whether an implementation is correct
  • 23. Removes Code Smells Duplicate Code Long methods Classes with too much code Lot of unused code Too many private methods Excessive Overloading
  • 24. Costs of TDD Claim - Slower per-feature development work because tests take a lot of time to write Rebut - Prevents speculative design and living with debugger. Claim - Tests are code in themselves, require maintenance and thats overhead. Rebut - Better than maintaining bug list. Claim - E鍖ectiveness is highly dependent on experience/ discipline of dev team. Rebut - TDD is not a silver bullet. Just like with any skill, one needs time to hone their skills.
  • 25. Good Test are Small Expressive Maintainable Should execute fast talk Domain language must be thorough automated repeatable
  • 26. Flavours of Test Unit Tests Integration Tests End to End Tests
  • 27. Unit testing frameworks JUnit/TestNG for Java NUnit/MsTest for C# Minitest/TestUnit for Ruby pyUnit/unittest for Python