2. Do We Have
Legacy Already?
Yes, thousands of rails apps have been
built and deployed over the last three
years. Many of us included few or no
tests. The test-less apps still need
debugging, which should be done with
tests.
3. Testing == Health Food?
“We started the tests, but
haven’t been updating them”
“Who has time for tests?”
“Testing means writing
twice as much code.”
21. Running Tests
with rake
rake test # Test all units and functionals
rake test:functionals # Run the functional tests in test/functional
rake test:integration # Run the integration tests in test/integration
rake test:plugins # Run the plugin tests in vendor/plugins/**/test
rake test:recent # Test recent changes
rake test:uncommitted # Test changes since last checkin (svn only)
rake test:units # Run the unit tests in test/unit
22. running tests directly
Test::Unit automatic runner.
Usage: blog_controller_test.rb [options] [-- untouched arguments]
run them all
ruby article_controller_test.rb
give it a test name
ruby article_controller_test.rb -n test_show
try regular expressions
ruby article_controller_test.rb -n /show/
get help: ruby --help
23. An Example
def User.find_popular(n=20)
sql = quot;select u.*, count(j.user_id) as popularity
from users u, talks_users j
where u.id = j.user_id group by j.user_id
order by popularity desc limit #{n}quot;
return User.find_by_sql(sql)
end
24. An Example
def User.find_popular(n=20)
sql = quot;select u.*, count(j.user_id) as popularity
from users u, talks_users j
where u.id = j.user_id group by j.user_id
order by popularity desc limit #{n}quot;
return User.find_by_sql(sql)
end
def test_popular
assert_nothing_raised { users = User.find_popular(2) }
assert_equal 2, users.size, quot;find_popular should return two usersquot;
assert users.first.popularity > users.last.popularity, quot;should sort popular usersquot;
end
$ ruby ./test/unit/user_test -n test_popular
brickhouse:~/code/icalico/trunk/test/unit rabble$ ruby user_test.rb -n /popular/
Loaded suite user_test
Started
.
Finished in 0.290563 seconds.
25. Refactor
def self.find_popular(n=20)
return conference.attendees.find(:all,
:select => quot;users.*, count(talks_users.user_id) as popularityquot;,
:joins => quot;LEFT JOIN talks_users on users.id = talks_users.user_idquot;,
:group => quot;talks_users.user_idquot;,
:order => 'popularity',
:limit => n
)
end
$ ruby ./test/unit/user_test -n test_popular
brickhouse:~/code/icalico/trunk/test/unit rabble$ ruby user_test.rb -n /popular/
Loaded suite user_test
Started
F
Finished in 0.290563 seconds.
1) Failure:
test_popular(UserTest) [user_test.rb:10]:
Exception raised:
Class: <NoMethodError>
Message: <quot;You have a nil object when you didn't expect it!nThe error occured
while evaluating nil.attendeesquot;>
---Backtrace---
/Users/rabble/code/icalico/trunk/config/../app/models/user.rb:35:in `find_popular'
user_test.rb:10:in `test_popular'
user_test.rb:10:in `test_popular'
---------------
26. Refactor
def self.find_popular(n=20)
return self.find(:all,
:select => quot;users.*, count(talks_users.user_id) as popularityquot;,
:conditions => [quot;users.conference_id = ? quot;, conference.id],
:joins => quot;LEFT JOIN talks_users on users.id = talks_users.user_idquot;,
:group => quot;talks_users.user_idquot;,
:order => 'popularity',
:limit => n )
end
$ ruby ./test/unit/user_test -n test_popular
brickhouse:~/code/icalico/trunk/test/unit rabble$ ruby user_test.rb -n /popular/
Loaded suite user_test
Started
.
Finished in 0.290563 seconds.
27. build test from logs
./log/development.log
Processing ArticlesController#show
(for 0.0.0.0 at 2006-07-20 11:28:23) [GET]
Session ID:
Parameters: {quot;actionquot;=>quot;showquot;, quot;idquot;=>quot;2quot;, quot;controllerquot;=>quot;articlesquot;}
Article Load (0.002371) SELECT * FROM articles LIMIT 1
Rendering within layouts/articles
Rendering articles/show
Article Columns (0.007194) SHOW FIELDS FROM articles
Completed in 0.10423 (9 reqs/sec) |
Rendering: 0.08501 (81%) |
DB: 0.01022 (9%) |
200 OK [http://test.host/articles/show/1]
28. the functional test
./test/functional/article_controller_test.rb
require File.dirname(__FILE__) + '/../test_helper'
require 'articles_controller'
# Re-raise errors caught by the controller.
class ArticlesController
def rescue_action(e)
raise e
end
end
class ArticlesControllerTest < Test::Unit::TestCase
def setup
@controller = ArticlesController.new
@request = ActionController::TestRequest.new
@response = ActionController::TestResponse.new
end
# Replace this with your real tests.
def test_truth
assert true
end
end
29. get the params
./log/development.log
Processing ArticlesController#show
(for 0.0.0.0 at 2006-07-20 11:28:23) [GET]
Session ID:
Parameters: {quot;actionquot;=>quot;showquot;, quot;idquot;=>quot;2quot;, quot;controllerquot;=>quot;articlesquot;}
Article Load (0.002371) SELECT * FROM articles LIMIT 1
Rendering within layouts/articles
Rendering articles/show
Article Columns (0.007194) SHOW FIELDS FROM articles
Completed in 0.10423 (9 reqs/sec) |
Rendering: 0.08501 (81%) |
DB: 0.01022 (9%) |
200 OK [http://test.host/articles/show/1]
30. what to test?
1. Assert that the page action
rendered and returned successful
HTTP response code, i.e. 200.
2. Assert that the correct
template was rendered.
3. Assert that action assigns a
value to the @article variable.
4. Assert that the right @article
object was loaded.
31. writing the test
./test/functional/article_controller_test.rb
def test_show
get :show, {quot;actionquot;=>quot;showquot;, quot;idquot;=>quot;2quot;, quot;controllerquot;=>quot;articlesquot;}
#confirm that the http response was a 200 (i.e. success)
assert_response :success
#confirm that the correct template was used for this action
assert_template 'articles/show'
#confirm that the variable @article was assigned a value
assert assigns( :article )
#confirm that the @article object loaded has the id we want
assert_equal 2, assigns( :article ).id
end
32. running the test
rabble:~/code/tblog/test/functional evan$ ruby
articles_controller_test.rb -n test_show
Loaded suite articles_controller_test
Started
F
Finished in 0.625045 seconds.
1) Failure: test_show(ArticlesControllerTest)
[articles_controller_test.rb:27]:
<2> expected but was <1>.
1 tests, 4 assertions, 1 failures, 0 errors
33. fix the bug
The old code
app/controller/articles_controller.rb:
def show
@article = Article.find(:first)
end
The fix is easy, we update it so the Article.find method
app/controller/articles_controller.rb:
def show
@article = Article.find(params[:id])
end
34. running the test
rabble:~/code/tblog/test/functional evan$ ruby
articles_controller_test.rb -n test_show
Loaded suite articles_controller_test
Started
.
Finished in 0.426828 seconds.
1 tests, 3 assertions, 0 failures, 0 errors