28
Test Driven Development (TDD) Sameer Soni @_sameersoni

Test Driven Development (TDD)

Embed Size (px)

Citation preview

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 Codepublic  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

Benefits 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 ain’t gonna need it).

• Better Code Coverage

TDD results in decoupled design

• Favours composition over inheritance.

• Small loosely coupled classes.

• Promotes coding to supertypes.

Benefits of TDD• Increased confidence 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

Benefits of TDD• Test act as a "living specification" of expected behaviour

• Smaller production codebases with more simple designs

• Easier detection of flaws 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 TDDClaim - Slower per-feature development work because tests take a lot of time to writeRebut - Prevents speculative design and living with debugger.

Claim - Tests are code in themselves, require maintenance and that’s overhead.Rebut - Better than maintaining bug list.

Claim - Effectiveness 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