The document provides guidelines for testing Rails applications. It recommends that any code change should be driven by a failed test. Tests should be close to the code being tested and focus on functionality rather than specific code. It discusses testing models, associations, named scopes, validations, controllers, views, helpers, emails, user interactions, Ajax requests, external sites, Rake tasks, file uploads, legacy applications, and more. The goal is to have tests that result in high-quality code through a test-first approach.
Report
Share
Report
Share
1 of 74
More Related Content
How To Test Everything
1. How To Test
Everything
Noel Rappin
Pathfinder Development
2. How To Test
Everything
... In Rails
Noel Rappin
Pathfinder Development
11. What Framework To
Use?
Short Answer: I don’t care
Longer Answer: Start with Rails Core,
move when you have an unfulfilled
need
12. What Framework To
Use?
Short Answer: I don’t care
Longer Answer: Start with Rails Core,
move when you have an unfulfilled
need
Those needs: Contexts, Factories,
Mocks
15. Associations
No need to just check for the existence
of an association
Associations should be driven by
failing tests of actual functionality
Code extensions in an association
block should be treated like any other
code
17. Named Scopes
Named scopes are methods
Don’t test that a named scope has the
SQL decorations you put in
Do test that the scope correctly finds
or manages the objects you expect
20. Named Scope Tests
assert_same_elements [@melvin, @thomas],
User.primary_status
should_have_named_scope :primary_status do |u|
["online", "away"]include?(u.status)
end
21. Should Have Scope
def self.should_match_named_scope(named_scope,
*args, &block)
should "match named scope #{named_scope}" do
ar_class = self.class.model_class
scoped_objects = ar_class.send(named_scope, *args)
assert !scoped_objects.blank?
scoped_objects.each do |obj|
assert block.call(obj)
end
non_scoped_objects = ar_class.all - scoped_objects
assert !non_scoped_objects.blank?
non_scoped_objects.each do |obj|
assert !block.call(obj)
end
end
end
23. Validations
Don’t test Rails code
Do test for valid state
Do test anything custom
And anything with a regex
Failing saves can lead to irritating test
28. Views
Test for semantic structure (DOM ID,
class)
assert_select is your friend
Sometimes, not test first
29. Test for the Negative
What’s not there is as important as
what is
30. Test for the Negative
What’s not there is as important as
what is
assert_select "#edit_link", :count => 0
31. Test for the Negative
What’s not there is as important as
what is
assert_select "#edit_link", :count => 0
assert_select "li:not(#edit_link)", :count => 2
37. Helpers
DO TEST HELPERS
Auto generated in Rails 2.3 and up
test/unit/helpers
Methods like url_for can be stubbed in
the test class
class UsersHelperTest < ActionView::TestCase
end
44. Testing Output
def make_headline
Helpers
concat("<h1 class='headline'>#{yield}</h1>")
end
test "make headline" do
assert_dom_equal("<h1 class='headline'>fred</h1>",
make_headline { "fred" })
end
45. Testing Output
def make_headline
Helpers
concat("<h1 class='headline'>#{yield}</h1>")
end
test "make headline" do
assert_dom_equal("<h1 class='headline'>fred</h1>",
make_headline { "fred" })
end
test "make headline with output buffer" do
make_headline { "fred" }
assert_dom_equal("<h1 class='headline'>fred</h1>",
output_buffer)
end
50. Email
ActionMailer::Base.deliveries.clear
Treat emails like views
assert_select_email
email_spec plugin for Cucumber &
RSpec
Shoulda: assert_did_not_sent_email,
assert_sent_email
51. Email
ActionMailer::Base.deliveries.clear
Treat emails like views
assert_select_email
email_spec plugin for Cucumber &
RSpec
Shoulda: assert_did_not_sent_email, do
should "send an email to mom"
assert_sent_email assert_sent_email do |email|
email.to == "mom@mommy.com"
end
end
61. Rake Tasks
Encapsulate the task into a class/
method and test that method
test "my rake task" do
@rake = Rake::Application.new
Rake.application = @rake
Rake.application.rake_require "lib/tasks/app"
Rake::Task.define_task(:environment)
@rake[:task_name].invoke
end
http://
www.philsergi.com