Upgrade to Pro — share decks privately, control downloads, hide ads and more …

The hitchhicker’s guide to unit testing

The hitchhicker’s guide to unit testing

You already know TDD, your code coverage is almost at 80%, jUnit has no secret for you? But you feel that you could do more with your tests, the tools you use have limitations. Or maybe you're just tired of assertEquals?

Don't panic! We will see how you can code tests. We will look upon:

- Mutation Testing
- BDD, Behaviour Driven Development
- Property Testing

More Decks by Rémy-Christophe Schermesser

Other Decks in Programming

Transcript

  1. Ruby!   Scala!   Java!   Python!   PHP!  

    But  don’t  forget  your  towel  
  2. Test::Unit   ScalaTest   jUnit   uniFest   PHPUnit  

    Again  don’t  forget  your  towel  
  3. And  again  again   void  testMyTest()  {      Obj

     obj  =  new  Obj();    //  10  lignes  of  things    assertEquals(…);   }  
  4. Problem   void  testMyTest()  {      Obj  obj  =

     new  Obj();    //  10  lignes  of  things    assertEquals(…);   }  
  5. describe  CompaniesController  do        describe  "POST  create"  do

                 context  "when  recruiter     signed_in  with  no  company"  do                    …              end        end   end  
  6. describe  CompaniesController  do        describe  "POST  create"  do

                 context  "when  recruiter     signed_in  with  no  company"  do                    …              end        end   end  
  7. describe  CompaniesController  do        describe  "POST  create"  do

                 context  "when  recruiter     signed_in  with  no  company  an  email  is   sent"  do                    …              end        end   end  
  8. let!(:recruiter)  {  login_recruiter  create(:recruiter,            

         company_id:  nil)  }       context  "when  good  params"  do    let(:params)  {  …  }          it  {  expect  {  post  :create,  params  }.to  change(Company,  :count).by  1  }      it  {  expect  {  post  :create,  params  }.to          change(Ac1onMailer::Base.deliveries,  :count).by  2  }     end   “When  recruiter  signed_in  with  no  company”
  9. let!(:recruiter)  {  login_recruiter  create(:recruiter,  company_id:  nil)  }      

    context  "when  good  params"  do    let(:params)  {  …  }          it  {  expect  {  post  :create,  params  }.to  change(Company,  :count).by  1  }      it  {  expect  {  post  :create,  params  }.to          change(Ac1onMailer::Base.deliveries,  :count).by  2  }     end   “When  recruiter  signed_in  with  no  company”
  10. let!(:recruiter)  {  login_recruiter  create(:recruiter,  company_id:  nil)  }      

    context  "when  good  params"  do    let(:params)  {  …  }          it  {  expect  {  post  :create,  params  }.to  change(Company,  :count).by  1  }      it  {  expect  {  post  :create,  params  }.to          change(Ac1onMailer::Base.deliveries,  :count).by  2  }     end   “When  recruiter  signed_in  with  no  company”
  11. let!(:recruiter)  {  login_recruiter  create(:recruiter,  company_id:  nil)  }      

    context  "when  good  params"  do    let(:params)  {  …  }          it  {  expect  {  post  :create,  params  }.to                  change(Company,  :count).by  1  }      it  {  expect  {  post  :create,  params  }.to              change(Ac1onMailer::Base.deliveries,  :count).by  2  }     end   “When  recruiter  signed_in  with  no  company”
  12. &&   ++   !=   >   …  

    ||   -­‐-­‐   ==   <   …   Mutate  it  
  13. if(a  &&  b)  {          i++;  

    }  else  {          i-­‐-­‐;   }   if(a || b) { i++; } else { i--; } if(a && b) { i--; } else { i--; } Mutate  it  
  14. Coverage  data   Equivalent  mutant   if(index  >=  10)  break

      and   if(index  ==  10)  break   Selec1ve  muta1on   Parallel  execu1on   Choose  your  mutants  wisely   Using  code  coverage  to   reduce  the  tests  to  run   Speed-­‐up   The  right  tool  
  15. Behavior   tes1ng   JUnit   Property   tes1ng  

    Muta1on   tes1ng   with   ScalaCheck  
  16. How  to  test  string   concatenaZon  ?   assert(  ("ta"

     +  "a")  ==  "taa"  )   assert(  ("ta"  +  "b")  ==  "tab"  )  
  17. How  to  test  string   concatenaZon  ?   assert(  ("ta"

     +  "a")  ==  "taa"  )   assert(  ("ta"  +  "b")  ==  "tab"  )   …  
  18. How  to  test  string   concatenaZon  ?   assert(  ("ta"

     +  "a")  ==  "taa"  )   assert(  ("ta"  +  "b")  ==  "tab"  )   assert(  ("ta"  +  "z")  ==  "taz"  )   …  
  19. How  to  test  string   concatenaZon  ?   assert(  ("ta"

     +  "a")  ==  "taa"  )   assert(  ("ta"  +  "b")  ==  "tab"  )   assert(  ("ta"  +  "z")  ==  "taz"  )   …   But  boring  
  20. ∀n∈N,  ∃!k∈N   (n  =  2k  ⋁  n  =  2k+1)

      Remember  math  class?   ∀n,  n  =  42  
  21. val  n:  Int   val  k:  Int     (n

     ==  2k  ||  n  ==  2k  +  1)  ==  true   (n  %  2    ==  0  ||  n  %  2  ==  1)  ==  true     In  code  
  22. val  a:  String   val  b:  String     ((a+b)

     endsWith  b)    ==  true   ((a+b)  startsWith  a)    ==  true     (a+b).length  ==  a.length  +  b.length   String   concatenaZon   properZes  
  23. List[Int]  =>  isPalindrome(list)     (list.reverse  ==  list)  ==>  isPalindrome(list)

        (list.reverse  !=  list)  ==>  !isPalindrome(list)   Limits  
  24. Behavior  tesZng        Every  day   MutaZon  tesZng

           CriZcal  code   Property  tesZng    à    CriZcal  code   Share  and  Enjoy  
  25. So  Long,  and   Thanks  for  All   the  Fish

      Rémy-­‐Christophe  Schermesser   @el_picador  
  26. Rémy-­‐Christophe  Schermesser   @el_picador   Behavior  tesZng   Rspec  (ruby)

      Jasmine  (javascript)     MutaZon  tesZng   Javalanche  (java)   Mutant  (ruby)   Property  tesZng   ScalaCheck  (scala)   QuickCheck  (haskell)   MrProper  (ruby)