$30 off During Our Annual Pro Sale. View Details »

Testing Ruby

Testing Ruby

A fairly high-level intro to testing Ruby using RSpec, Factory Girl, and Autotest.

Emily Hyland

July 05, 2012
Tweet

More Decks by Emily Hyland

Other Decks in Programming

Transcript

  1. TESTING RUBY
    USING RSPEC
    WITH FACTORY GIRL
    AND AUTOTEST
    Thursday, July 5, 12

    View Slide

  2. Why Test?
    Ensure your code is correct
    Refactor with confidence
    Encourages lots of good practices
    Reference for how code works
    Thursday, July 5, 12

    View Slide

  3. RUBY — TESTING
    Thursday, July 5, 12

    View Slide

  4. THE EMILY WAY
    Thursday, July 5, 12

    View Slide

  5. The Basics
    Write your test first
    Test behavior, not implementation
    “You ain’t gonna need it”
    Thursday, July 5, 12

    View Slide

  6. Test First
    Test-Driven Development
    Figure out requirements before you
    start writing code
    Interface before implementation
    Thursday, July 5, 12

    View Slide

  7. RED
    GREEN
    REFACTOR
    START
    Thursday, July 5, 12

    View Slide

  8. Test Behavior
    Behavior-Driven Development
    Unit tests are sentences
    starting with “it should”
    Use mocks for outside collaborators
    Changing the implementation
    shouldn’t break the test
    Thursday, July 5, 12

    View Slide

  9. YAGNI
    Write only as much code
    as you need
    Thursday, July 5, 12

    View Slide

  10. YAGNI
    Write only as much code
    as you need
    THIS IS SURPRISINGLY HARD
    Thursday, July 5, 12

    View Slide

  11. RSPEC
    Thursday, July 5, 12

    View Slide

  12. Why RSpec?
    Tests are very easy to read
    Syntax encourages good practices
    Specify behavior instead
    of verifying state
    Tests as documentation
    Tests are more expressive
    and more maintainable
    Thursday, July 5, 12

    View Slide

  13. describe  Array  do
       context  "when  empty"  do
           subject  {  Array.new  }
           it  {  should  be_empty  }
           its(:first){  should  be_nil  }
           its(:length){  should  ==  0  }
       end
    end
    Basic Syntax
    Thursday, July 5, 12

    View Slide

  14. More Syntax
    let(:user){  User.new  }
    before{  set_current_user(user)  }
    it  "should  be  reasonable"  do
       "foo".should_not  eq("bar")
    end
    it  "should  be  magic"  do
       pending  "invent  magic"
    end
    Thursday, July 5, 12

    View Slide

  15. Shared Examples
    shared_examples  "collections"  do  |
    klass|
       it  "is  empty  when  first  created"  do
           klass.new.should  be_empty
       end
    end
    describe  Array  do
       include_examples  "collections",  Array
    end
    Thursday, July 5, 12

    View Slide

  16. Matchers
    it.should  eq(expected)
    it.should  ==  expected
    it.should  be(expected)
    it.should  equal(expected)
    it.should  be  >  minimum
    it.should  be_within(x).of(y)
    Thursday, July 5, 12

    View Slide

  17. Predicate Matchers
    it.should  be_a_kind_of(klass)
    it.should  be_true
    it.should  be_empty
    it.should  be_present
    it.should  be_*
    Thursday, July 5, 12

    View Slide

  18. Expect Matchers
    expect  {  ...  }.to  raise_error
    expect  {  ...  }.to  throw_symbol
    expect  {  ...  }.to  yield_control
    expect  {  ...  }.to  change{  it  }
    Thursday, July 5, 12

    View Slide

  19. On Rails
    Different file layout than
    with Test::Unit
    Directories for model, controller,
    helper, and view specs
    Lots of Rails-specific matchers, etc.
    Thursday, July 5, 12

    View Slide

  20. Model
    Classic unit test
    Test each model individually
    Ideally, isolate from the database
    Check validations, but indirectly
    Add a context for each
    non-trivial method
    Thursday, July 5, 12

    View Slide

  21. Controller
    Did you get the right response code?
    Did the expected redirect happen?
    Were the correct instance
    variables set?
    Were the right flash messages
    displayed?
    Thursday, July 5, 12

    View Slide

  22. Legacy
    Write tests for what you have
    before you change it
    Write a failing test before you fix a bug
    Don’t try to do it all at once
    Thursday, July 5, 12

    View Slide

  23. FACTORY GIRL
    Thursday, July 5, 12

    View Slide

  24. Why Factories?
    Fixtures quickly get hard to maintain
    “What did I call the fixture for my
    admin user without an email?”
    Create the right object
    when you need it
    Use templates to keep it DRY
    Thursday, July 5, 12

    View Slide

  25. Syntax
    FactoryGirl.define  do
       factory  :user  do
           name  "John  Doe"
           factory  :admin  do
               admin  true
           end
       end
    end
    FactoryGirl.build(:user)
    Thursday, July 5, 12

    View Slide

  26. AUTOTEST
    Thursday, July 5, 12

    View Slide

  27. Why Autotest?
    Never forget to run your tests again
    Get nearly instant notification when
    you break something
    Run the right tests at the right time
    Thursday, July 5, 12

    View Slide

  28. AND FINALLY...
    Thursday, July 5, 12

    View Slide

  29. DO
    Write your tests first
    Use contexts
    Use shared example groups
    Test your edge cases
    Thursday, July 5, 12

    View Slide

  30. DON’T
    Test the framework
    Test the implementation
    Get too clever
    Thursday, July 5, 12

    View Slide