Beruflich Dokumente
Kultur Dokumente
Ruby on Rails [RoR], a fairly new web development RoR was developed with a lot of tasks in mind. One
framework that utilizes the MVC design pattern, includes specific functionality that you don’t always find in other
a very important and powerful set of testing tools. RoR frameworks, but you do in RoR, is the inclusion of
pushes the developer to use these tools by automatically automated test functionality.
generating test files which can be immediately used to Note: Ruby code ahead!
design test cases with. A feature like this is what sets
RoR apart from aging web technologies. With more and 1.1 All thanks to Ruby
more applications being ported to the web, it is time to
begin treating them like true applications which means
RoR as you might be able to guess is built on top of
extensive testing.
the Ruby programming language. It’s an interpretive
language that was developed in Japan in 1995. It is
Keywords: Web Development, Ruby, Ruby on Rails,
heavily influenced by older languages such as Lisp,
Testing Frameworks, Web Testing
ADA and Perl. It’s also a very beautiful and elegant
language, words you don’t often see when describing a
programming language. 37Signals choose to build Rails
1. Introduction
on top of Ruby for these reasons. Ruby is also
completely object oriented. Everything you encounter in
Ruby on Rails [RoR], an accidental web
Ruby can be treated as an object which makes it very
development framework developed by 37Signals
powerful and very easy to use, not to mention very
(http://www.37signals.com), has gained much popularity
readable.[8]
since its conception in 2004. The term accidental is used
Ruby comes standard with testing libraries.
because unlike many frameworks which are built from
Test/unit provides extensive unit testing and shares many
the ground up, RoR was extracted from a 37Signals
of the same attributes as other unit testing frameworks
product called Basecamp. The developers at 37Signals
available for other programming languages. Not only
decided to build their own development toolset while
are you able to develop extensive unit tests but you are
building Basecamp and when the application was
open to functional testing and integration testing as well.
complete, they discovered that the framework could
Unit testing will generally be to test the logic
easily be extracted and used by any web application and
throughout your application. Calculations and
then open sourced it under the MIT license.[1]
validations will most often be the most prevalent in your
The main focus of RoR is convention over
tests as they are easy to develop to get your application
configuration. In most cases you’re doing 80% of what
tests growing.
everyone else is doing and the other 20% is what makes
Functional tests will be used against your
you stand out. The developers built RoR because there
controllers. You may have methods to post form data or
weren’t any tools available at the time that could
generate session data, with RoR you can easily generate
accomplish their tasks in such a way that it would make
functional tests to verify they work.
them happy. Developers who are happy and who enjoy
Integration testing ties everything together. Once
developing in the environment they are in will produce
you have core functionality in your application, you can
great things.
write integration tests to check against various 3 Ruby on Rails and Test Driven
scenarios.[9] Development
Because all of this capability is a part of every
standard Ruby install, it is available to your RoR RoR is very much considered a great platform for
application. Ruby is the key factor in making this all test driven development [TDD]. Before you even begin
happen. writing code, you can start writing your test cases at
which then you can start coding your controller in such a
2. Automated File Generation way that it will pass all your tests. Many developers
adopt a very agile programming methodology based
RoR does a great amount of file generation. Using a around the automated tests. By using such a simple
variety of scripts, you can easily build your application methodology as not committing modified code to a
while RoR maintains all of your files in a standardized version control system until that code passes all of its
directory structure. This not only helps out with tests. In doing so you’re maintaining a bug free branch
readability but also helps from applications going awry of your application that other developers can work off of.
on the developer.
3.1 Automating Tests with Rake
$ruby script/generate model user
exists app/models/ Another benefit of RoR is the inclusion of Rake, the
exists test/unit/ Ruby equivalent of Make. Rake will allow you to
exists test/fixtures/ automate many redundant tasks. These tasks could be
create app/models/user.rb basic database maintenance or backups or more
create test/unit/users_test.rb importantly, running tests.
create test/fixtures/users.yml
task :runtests do
Table 1 - Automated file generation example tests = FileList['test/**/*_test.rb']
tests.each do |file|
2.1 Automated Test Generation m = %r".*/([^/].*)_test.rb".match(file)
puts m[1]+" should:\n"
One of the crucial files generated in Table 1 is the test_definitions = File::readlines(file).select {|line| line =~ /.*def
users_test.rb file. RoR does its best to enforce good test.*/}
development habits, one of which is a large focus on test_definitions.each do |definition|
testing. Each model in your application has a m = %r"test_(should_)?(.*)".match(definition)
corresponding test file. puts " - "+m[2].gsub(/_/," ")
end
require ‘/../test_helper’ puts "\n"
end
Class UserTest < Test::Unit::TestCase end
fixtures :users
Table 3 - Rake task that automatically runs all
# Replace this with your rest tests. tests[2]
def test_truth
assert true The rake task in Table 3 automatically handles all
end your tests in a single location. Running your RakeFile
end periodically while actively developing will provide you
feedback on your tests. What’s even better is that it will
Table 2 - Automated test script example run any tests created in the future; this follows the “don’t
repeat yourself” [DRY] methodology which is highly
Although this doesn’t generate any test cases for preached in the RoR community.[2]
you, it does provide the ground work to get you started.
At this point you now have access to your model from
the test script and you can begin designing test cases.
3.2 Test Examples 4 ActiveRecord and Security
Let’s take for example the case of handling a One of the key features of RoR is ActiveRecord.
password input field when a user registers with our ActiveRecord is a layer that sits between your models
application. There are a variety of scenarios that we and your database tables. This methodology is referred
would want to look out for: to as Object-Relational Mapping [ORM]. ActiveRecord
• Is the password more than 4 characters? eliminates the need to write any raw SQL queries against
• Is the field Nil? (Rubys equivalent to Null) your database. This makes all RoR applications
• Is the password the same as their username? completely database independent. More importantly it
These are pretty straight forward requirements and makes it more secure.
before we begin we can develop our test cases for them. One of the most exploited features that are difficult
to test against in today’s web applications are SQL
def test_these_passwords injections. A SQL injection is when a user inserts
assert !User.new("name","abc").is_password_safe? standard SQL into a web form, when the form is
assert !User.new("name","").is_password_safe? submitted the user is then returned more data, often data
assert !User.new("name","name").is_password_safe? that shouldn’t be seen by the user. ActiveRecord
assert User.new("name","JiEhf").is_password_safe? protects RoR applications against this attack. Any raw
end SQL that would need to developed could easily be done
inside a model method, protecting it from public access.
Table 4 - Example method containing test cases This doesn’t mean that RoR applications are 100%
protected against SQL injection attacks but it’s one less
Notice the beginning of the method is “test”. The security concern.
layout the test file is such that any method beginning Today’s more popular web development languages
with “test” as the first four letters will be run. You could such as PHP and Java use raw SQL queries for most all
include as many test methods as you would like inside a application that interact with a database. Because of the
single script and they will each be executed. At this potential threat, you are left with having to find a third
point we could then create our is_password_safe? party testing tool which can test for such threats. This is
method inside our controller which would test again each where RoR excels because of its inclusion of testing
of our cases. Running the test would produce the frameworks. But what the key issue is SQL injections
following output. are not a concern with a standard RoR application, but
advanced applications do need to beware.[4]
Started
. 4.1 Testing without ActiveRecord; quickly
Finished in 0.01 seconds.
Finished in 11.541093 seconds.
1 tests, 4 assertions, 0 failures, 0 errors
3001 tests, 5325 assertions, 0 failures, 0 errors
Table 5 - Test output
Table 6 – Very fast testing when removing
Because we were able to implement the correct ActiveRecord from the picture [5]
checks against the password inside our controller, our
four assertions passed and we could continue At Ruby Hoedown, a recent Ruby focused
development. If however we forgot to check for a conference; the concept of running tests without
password that is less than 4 characters we would have interacting with ActiveRecord was demonstrated. The
received a failure with a description containing the error speaker, Dan Manges, describes how they do their
and the line that it occurred at. At that point we could testing without hitting their database, the result is a
review our code and make the desired changes so our highly efficient set of tests that can perform very quickly
code passes our tests.[3] and without the expense of database transactions.
“Testing the ActiveRecord framework in addition to your
business logic is unnecessary - ActiveRecord has its own
suite of tests. Therefore, disconnecting from the database
allows you to test the business logic in isolation from the
persistence logic and have really fast tests.” [5] The As you can see in Table 7, simply creating an RJS
testing methodology is quite simple and Dan has template that’s named after an action in your controller
released the framework, UnitRecord, which is available will execute when triggered with a click on the page
at http://unit-test-ar.rubyforge.org/. being viewed. In the example, when the user clicks
“Add bar”, the RJS template inserts a new list item with
5 AJAX Without Headaches the text “Bar” at the end of the unordered list. It then
highlights the list element for three seconds; all without a
Despite being a functionality of browsers for many page refresh. Doing this by writing raw JavaScript could
years, Asynchronous JavaScript with XML [AJAX] has easily be dozens, if not hundreds lines of code but the
become the new fad when it comes to “Web 2.0” simplicity of RoR handles the hard work for you.
applications. The difficulty with AJAX is the complex
JavaScript it takes to execute it. The purpose of AJAX is 5.2 Testing RJS
to make a remote call to either POST or GET data
without refreshing the page you are visiting. All of this One benefit of the RoR community is the amount of
is done as separate connections by your browser in the plugins developed that can easily be integrated into any
background. application at any given time. Out of the box, RoR
Because of its popularity, there have been many cannot effectively test AJAX actions done within an RJS
AJAX frameworks popping up on the Internet. These template. However, a third party plugin, Another RJS
frameworks cut down the tedious JavaScript calls down Test System [ARTS] has become available that can test
to a few lines of code that almost anyone can understand. and verify your AJAX calls are returning the appropriate
RoR takes these frameworks one step further. With the data or rendering aspects of the page correctly.[7]
inclusion of Prototype.js, one of the most popular AJAX
frameworks available to date, RoR has dozens of def test_create_rjs
methods that are typically a single line of code that can xhr :post, :create, :post => {:title => "Yet Another Post", :body =>
perform very complex AJAX calls and visual effects. "This is yet another post"}
assert_rjs :insert_html, :bottom, 'posts'
5.1 RJS Templates assert_rjs :visual_effect, :highlight, "post_#{assigns(:post).id}"
end
The RoR approach to AJAX is through RJS
templates. These interact with your views to generate Table 8 - Verifying AJAX functionality with ARTS[7]
the necessary JavaScript to perform AJAX actions. The
inclusion of RJS templates within your application can ARTS has the functionality to test ~17 RJS functions and
easily make your application more enjoyable to use, because it is open source you could easily add new RJS
easier to navigate and a much more pleasurable tests to the suite. You can download ARTS at
experience on the eyes. http://thar.be/svn/projects/plugins/arts/.
References
[1] Curt Hibbs. What Is Ruby on Rails. 2005 ONLamp.com
http://www.onlamp.com/pub/a/onlamp/2005/10/13/what_is_rai
ls.html
[2] http://wiki.rubyonrails.org/rails/pages/HowToDoTestDriv
enDevelopmentInRails
[3] 37Signals. A Guide to Testing Rails.
http://manuals.rubyonrails.com/read/chapter/22
[4] 37Signals. Securing your Rails applications
http://manuals.rubyonrails.com/read/chapter/43
[5] Dan Manges. Rails: UnitRecord – Test Without the
Database http://www.dcmanges.com/blog/rails-unit-record-
test-without-the-database
[6] Cody Fauser - Rails RJS Templates
http://www.codyfauser.com/2005/11/20/rails-rjs-templates
[7] Guide: Test Driven Development with ARTS
http://glu.ttono.us/articles/2006/05/29/guide-test-driven-rjs-
with-arts
[8] About Ruby http://www.ruby-lang.org/en/about/
[9] Gregory Brown. Rails Testing: Not just for the paranoid
http://www.oreilly.de/artikel/2007/06/rails.html
[10] rcov: Code Coverage for Ruby
http://eigenclass.org/hiki.rb?rcov
[11] RSpec Home http://rspec.rubyforge.org/