Vous êtes sur la page 1sur 6

SWE 5411 (NG) Florida Institute of Technology Summer 2007

Ruby on Rails or: How I Learned to Stop Worrying and


Love Web Application Testing
Matthew Williams
Department of Computer Sciences
Florida Institute of Technology
mwilli02@fit.edu

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/.

View: 6 Code coverage


<h1 id='header'>RJS Template Test</h1>
<ul id='list'> Code coverage is an integral part of software testing.
<li>Foo</li> With a simple glimpse you can determine how much of
</ul> your code is being tested against and provide you per file
<%= link_to_remote("Add bar",:url =>{ :action => :add }) %> test information with detailed information on what lines
Action: in each of your files are being hit the most.
def add Like many of the plugins previously mentioned,
end rcov, an open source tool for Ruby code coverage can be
add.rjs implemented into your RoR application very easily. It
page.insert_html :bottom, 'list', provides a great amount of detail on your application.
content_tag("li", "Bar") Some of the detail provided is total lines of code per file,
page.visual_effect :highlight, 'list', :duration => 3 total coverage and code coverage. With the tool you are
able to drill down into each file where you’re presented
Table 7 - RJS template example with a nicely formatted and color coded version of the
file containing highlighted code that is being called in
most often see in other languages such as J2EE or PHP,
it provides immediate access to almost any database
management system and it comes with a full testing
framework. Many applications are moving from the
desktop and straight to the web. With more capabilities
being added to web browsers and more bandwidth
available to the average user, there isn’t much that can be
done on the desktop that can’t be done on the web. This
is why that developers need to embrace software
development strategies that you would normally see in
use for any given desktop application and apply those
same rules to the web.
Figure 1 - Sample rcov output [10] When dealing with web applications you need to
assume that the user is completely clueless, or that it’s
completely the other way around and the user is more
tests and corresponding number counts for how many advanced than they need to be. Either of these cases
times that specific line is hit.[10] could lead to poorly entered data in your forms or
Rcov is freely available at various forms of exploitation. Following standard
http://eigenclass.org/hiki.rb?rcov and can immediately development practices and using a test driven
be implemented into any existing RoR application so development methodology will prevent these users from
you can instantly get code coverage information for your breaking your application, resulting in a rich and
existing tests or to keep track as you develop tests. flawless user experience.
Large companies like Oracle are even almost
completely abandoning the desktop altogether. They
7 Beyond Bundled Test Frameworks have recently embraced J2EE for developing application
front ends and they have even begun publishing tutorials
The integrated test suite is certainly not everything on using Oracle with RoR, exposing the option to their
and the kitchen sink as far as testing frameworks go. customers as an alternative to J2EE.
With RoR as active as it is, many wanted an even better Companies like Sun and Apple are noticing the
solution. And so, RSpec was born. As described on its importance of RoR as well. Sun now supports full RoR
website, RSpec is “a framework which provides development in their IDE, NetBeans. Developers have
programmers with a Domain Specific Language to even gone as far as to port the Ruby interpreter to Java
describe the behavior of Ruby code with readable, which is now allowing RoR applications to run on a
executable examples that guide you in the design process standard Tomcat server with little to no extra
and serve well as both documentation and tests.”[11] configuration. Apple will be including RoR in their next
RSpec is for the advanced RoR developer or those revision of the OS X Operating System, Leopard.
who might not be satisfied with the included testing Despite the advancement of many programming
framework. Test cases are extremely literal and anyone languages, there will almost always be a need for
joining the development team could easily determine designing test cases. As projects grow and grow, code
what the test is for and why. can become more difficult to maintain and simple
changes could easily interfere with the functionality of
it "should return the top item when sent #peek" do another area of the application. Having tests in place
@stack.peek.should == @last_item_added will prevent these scenarios from happening.
end Lastly, the development of these applications is no
longer done by computer scientists or those with
Table 9 - Example RSpec test case[11] technology related backgrounds. The technologies have
so vastly grown that just about anyone can pick up a
8 Summary book and start developing. But not having that
background and software development mindset can
RoR is redefining the way developers write web easily flaw their applications. What RoR has done to
applications. It is removing the bloat that you would web development will ultimately revolutionize it, if it
hasn’t already done so. With only three years of
exposure and a growing user base who are becoming
more educated, we can only hope to see an increase in
bug free web applications in the future, all thanks to the
testing capabilities and elegance of RoR.

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/

Vous aimerez peut-être aussi