test driven development: why i hate it; but secretly love it
TRANSCRIPT
Test Driven Development
Why I hate it, but really love it.
Start with FAIL
Make it Green!
Make it Pretty (refactor)
(Not Like this chap)
Eh?
• Why???• How???• When???
WHY TDD?
Stability
Flexibility
Documentation
MORE SPEEEEDzzz
Design
HOW TDD?
(Disclaimer: Code incoming!)
• Failing Test:
def test_add_1_plus_1 assert_equal 2, add(1,1)end
Output:tdd.rb:6:in `test_add_1_plus_1': undefined method `add' for main:Object (NoMethodError)from tdd.rb:9
Writing an adding, er.. Thing…
WHATS THE NEXT STEP?
• Make it pass:
def add(i,j) return 2endOutput:Loaded suite TddExampleStarted.Finished in 0.000455 seconds. 1 tests, 1 assertions, 0 failures, 0 errors
Waait!! Why isn’t it just:
def add(i,j) return i+jend
WHATS THE NEXT STEP?
Write another failing test:
def test_add_1_plus_2 assert_equal 3, add(1,2)End
Loaded suite TddExampleStartedFFinished in 0.042739 seconds. 1) Failure:test_add_1_plus_1(TddExample) [tdd.rb:42]:<3> expected but was<2>. 1 tests, 1 assertions, 1 failures, 0 errors
Make it pass:
def add(i,j) return i+jEnd
Loaded suite TddExampleStarted..Finished in 0.000462 seconds.
2 tests, 2 assertions, 0 failures, 0 errors
All about the baby steps
Problems?
add(1,2,3)
Fail.
add(1,”two”)
Fail.
How do we cope?
• Any number of arguments?• First add a test..
def test_adding_three_arguments assert_equal 4, add(1,2,1)End
Make it pass!!
Add another test!!
def test_adding_four_arguments assert_equal 8, add(1,2,1,4)end
Refactor
For the general solution:
def add(*args) return args.inject(0){|sum,n| sum + n}End
Loaded suite TddExampleStarted....Finished in 0.000941 seconds. 4 tests, 4 assertions, 0 failures, 0 errors
Dependency Injection(This has nothing to do with children)
Example:
class PersonDAO def initialize(user, password) @data_source = Database.connect(user,
password) endend
VS
class PersonDAO def initialize(data_source) @data_source = data_source endend
Why is this better?
And you’re telling me this… why?
Start off with a test
def setup @person = FamilGuyDao.newend
def test_return_full_name_is_reginald_von_griffen assert_equal "Reginald Von-Griffin",
@person.full_nameend
#But how do we make it vary? Pass in the name? Pull it from somewhere #Lets assume there is some Griffin Family Tree in the sky
def test_return_full_name_is_stewie_griffin assert_equal "Stewie Griffin", @person.full_name end
For now we’ll pass in the name
Next Test….
Make it pass…
WHATS THE NEXT STEP?
• The General Case
Integration faked by Mock object!
MAKE IT PASS!!
DONE!