TESTING RUBY
USING RSPEC
WITH FACTORY GIRL
AND AUTOTEST
Thursday, July 5, 12
Slide 2
Slide 2 text
Why Test?
Ensure your code is correct
Refactor with confidence
Encourages lots of good practices
Reference for how code works
Thursday, July 5, 12
Slide 3
Slide 3 text
RUBY — TESTING
Thursday, July 5, 12
Slide 4
Slide 4 text
THE EMILY WAY
Thursday, July 5, 12
Slide 5
Slide 5 text
The Basics
Write your test first
Test behavior, not implementation
“You ain’t gonna need it”
Thursday, July 5, 12
Slide 6
Slide 6 text
Test First
Test-Driven Development
Figure out requirements before you
start writing code
Interface before implementation
Thursday, July 5, 12
Slide 7
Slide 7 text
RED
GREEN
REFACTOR
START
Thursday, July 5, 12
Slide 8
Slide 8 text
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
Slide 9
Slide 9 text
YAGNI
Write only as much code
as you need
Thursday, July 5, 12
Slide 10
Slide 10 text
YAGNI
Write only as much code
as you need
THIS IS SURPRISINGLY HARD
Thursday, July 5, 12
Slide 11
Slide 11 text
RSPEC
Thursday, July 5, 12
Slide 12
Slide 12 text
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
Slide 13
Slide 13 text
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
Slide 14
Slide 14 text
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
Slide 15
Slide 15 text
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
Slide 16
Slide 16 text
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
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
Slide 20
Slide 20 text
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
Slide 21
Slide 21 text
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
Slide 22
Slide 22 text
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
Slide 23
Slide 23 text
FACTORY GIRL
Thursday, July 5, 12
Slide 24
Slide 24 text
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
Slide 25
Slide 25 text
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
Slide 26
Slide 26 text
AUTOTEST
Thursday, July 5, 12
Slide 27
Slide 27 text
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
Slide 28
Slide 28 text
AND FINALLY...
Thursday, July 5, 12
Slide 29
Slide 29 text
DO
Write your tests first
Use contexts
Use shared example groups
Test your edge cases
Thursday, July 5, 12
Slide 30
Slide 30 text
DON’T
Test the framework
Test the implementation
Get too clever
Thursday, July 5, 12