/  6
 
 
Ruby on Rails or: How I Learned to Stop Worrying andLove Web Application Testing
Matthew Williams
Department of Computer SciencesFlorida Institute of Technology
mwilli02@fit.edu 
 Ruby on Rails [RoR], a fairly new web development  framework that utilizes the MVC design pattern, includesa very important and powerful set of testing tools. RoR pushes the developer to use these tools by automaticallygenerating test files which can be immediately used todesign test cases with. A feature like this is what sets RoR apart from aging web technologies. With more and more applications being ported to the web, it is time tobegin treating them like true applications which meansextensive testing.
Keywords
: Web Development, Ruby, Ruby on Rails,Testing Frameworks, Web Testing
1.
 
Introduction
Ruby on Rails [RoR], an accidental webdevelopment framework developed by 37Signals(http://www.37signals.com), has gained much popularitysince its conception in 2004. The term accidental is usedbecause unlike many frameworks which are built fromthe ground up, RoR was extracted from a 37Signalsproduct called Basecamp. The developers at 37Signalsdecided to build their own development toolset whilebuilding Basecamp and when the application wascomplete, they discovered that the framework couldeasily be extracted and used by any web application andthen open sourced it under the MIT license.[1]The main focus of RoR is convention overconfiguration. In most cases you’re doing 80% of whateveryone else is doing and the other 20% is what makesyou stand out. The developers built RoR because thereweren’t any tools available at the time that couldaccomplish their tasks in such a way that it would makethem happy. Developers who are happy and who enjoydeveloping in the environment they are in will producegreat things.RoR was developed with a lot of tasks in mind. Onespecific functionality that you don’t always find in otherframeworks, but you do in RoR, is the inclusion of automated test functionality.
Note:
Ruby code ahead!
1.1
 
All thanks to Ruby
RoR as you might be able to guess is built on top of the Ruby programming language. It’s an interpretivelanguage that was developed in Japan in 1995. It isheavily influenced by older languages such as Lisp,ADA and Perl. It’s also a very beautiful and elegantlanguage, words you don’t often see when describing aprogramming language. 37Signals choose to build Railson top of Ruby for these reasons. Ruby is alsocompletely object oriented. Everything you encounter inRuby can be treated as an object which makes it verypowerful and very easy to use, not to mention veryreadable.[8]Ruby comes standard with testing libraries.Test/unit provides extensive unit testing and shares manyof the same attributes as other unit testing frameworksavailable for other programming languages. Not onlyare you able to develop extensive unit tests but you areopen to functional testing and integration testing as well.Unit testing will generally be to test the logicthroughout your application. Calculations andvalidations will most often be the most prevalent in yourtests as they are easy to develop to get your applicationtests growing.Functional tests will be used against yourcontrollers. You may have methods to post form data orgenerate session data, with RoR you can easily generatefunctional tests to verify they work.Integration testing ties everything together. Onceyou have core functionality in your application, you can
SWE 5411 (NG) Florida Institute of Technology Summer 2007
 
 
 write integration tests to check against variousscenarios.[9]Because all of this capability is a part of everystandard Ruby install, it is available to your RoRapplication. Ruby is the key factor in making this allhappen.
2.
 
Automated
File Generation
RoR does a great amount of file generation. Using avariety of scripts, you can easily build your applicationwhile RoR maintains all of your files in a standardizeddirectory structure. This not only helps out withreadability but also helps from applications going awryon the developer.
$ruby script/generate model user exists app/models/ exists test/unit/ exists test/fixtures/ create app/models/user.rbcreate test/unit/users_test.rbcreate test/fixtures/users.yml
 
Table 1 - Automated file generation example
2.1
 
Automated Test Generation
One of the crucial files generated in
Table 1
is theusers_test.rb file. RoR does its best to enforce gooddevelopment habits, one of which is a large focus ontesting. Each model in your application has acorresponding test file.
require ‘/../test_helper’Class UserTest < Test::Unit::TestCase fixtures :users# Replace this with your rest tests.def test_truthassert trueend end 
 
Table 2 - Automated test script example
Although this doesn’t generate any test cases foryou, it does provide the ground work to get you started.At this point you now have access to your model fromthe test script and you can begin designing test cases.
3
 
Ruby on Rails and Test DrivenDevelopment
RoR is very much considered a great platform fortest driven development [TDD]. Before you even beginwriting code, you can start writing your test cases atwhich then you can start coding your controller in such away that it will pass all your tests. Many developersadopt a very agile programming methodology basedaround the automated tests. By using such a simplemethodology as not committing modified code to aversion control system until that code passes all of itstests. In doing so you’re maintaining a bug free branchof your application that other developers can work off of.
3.1
 
Automating Tests with Rake
Another benefit of RoR is the inclusion of Rake, theRuby equivalent of Make. Rake will allow you toautomate many redundant tasks. These tasks could bebasic database maintenance or backups or moreimportantly, running tests.
task :runtests dotests = FileList['test/**/*_test.rb']tests.each do |file|m = %r".*/([^/].*)_test.rb".match(file) puts m[1]+" should:\n"test_definitions = File::readlines(file).select {|line| line =~ /.*def test.*/}test_definitions.each do |definition|m = %r"test_(should_)?(.*)".match(definition) puts " - "+m[2].gsub(/_/," ")end  puts "\n"end end 
 
Table 3 - Rake task that automatically runs alltests[2]
The rake task in
Table 3
automatically handles allyour tests in a single location. Running your RakeFileperiodically while actively developing will provide youfeedback on your tests. What’s even better is that it willrun any tests created in the future; this follows the “don’trepeat yourself” [DRY] methodology which is highlypreached in the RoR community.[2]
 
 
3.2
 
Test Examples
Let’s take for example the case of handling apassword input field when a user registers with ourapplication. There are a variety of scenarios that wewould want to look out for:
 
Is the password more than 4 characters?
 
Is the field Nil? (Rubys equivalent to Null)
 
Is the password the same as their username?These are pretty straight forward requirements andbefore we begin we can develop our test cases for them.
def test_these_passwordsassert !User.new("name","abc").is_password_safe?assert !User.new("name","").is_password_safe?assert !User.new("name","name").is_password_safe?assert User.new("name","JiEhf").is_password_safe?end 
 
Table 4 - Example method containing test cases
Notice the beginning of the method is “test”. Thelayout the test file is such that any method beginningwith “test” as the first four letters will be run. You couldinclude as many test methods as you would like inside asingle script and they will each be executed. At thispoint we could then create our is_password_safe?method inside our controller which would test again eachof our cases. Running the test would produce thefollowing output.
Started .Finished in 0.01 seconds.1 tests, 4 assertions, 0 failures, 0 errors
 
Table 5 - Test output
Because we were able to implement the correctchecks against the password inside our controller, ourfour assertions passed and we could continuedevelopment. If however we forgot to check for apassword that is less than 4 characters we would havereceived a failure with a description containing the errorand the line that it occurred at. At that point we couldreview our code and make the desired changes so ourcode passes our tests.[3]
4
 
ActiveRecord and Security
One of the key features of RoR is ActiveRecord.ActiveRecord is a layer that sits between your modelsand your database tables. This methodology is referredto as Object-Relational Mapping [ORM]. ActiveRecordeliminates the need to write any raw SQL queries againstyour database. This makes all RoR applicationscompletely database independent. More importantly itmakes it more secure.One of the most exploited features that are difficultto test against in today’s web applications are SQLinjections. A SQL injection is when a user insertsstandard SQL into a web form, when the form issubmitted the user is then returned more data, often datathat shouldn’t be seen by the user. ActiveRecordprotects RoR applications against this attack. Any rawSQL that would need to developed could easily be doneinside a model method, protecting it from public access.This doesn’t mean that RoR applications are 100%protected against SQL injection attacks but it’s one lesssecurity concern.Today’s more popular web development languagessuch as PHP and Java use raw SQL queries for most allapplication that interact with a database. Because of thepotential threat, you are left with having to find a thirdparty testing tool which can test for such threats. This iswhere RoR excels because of its inclusion of testingframeworks. But what the key issue is SQL injectionsare not a concern with a standard RoR application, butadvanced applications do need to beware.[4]
4.1
 
Testing without ActiveRecord; quickly
Finished in 11.541093 seconds.3001 tests, 5325 assertions, 0 failures, 0 errors
 
Table 6 – Very fast testing when removingActiveRecord from the picture [5]
At Ruby Hoedown, a recent Ruby focusedconference; the concept of running tests withoutinteracting with ActiveRecord was demonstrated. Thespeaker, Dan Manges, describes how they do theirtesting without hitting their database, the result is ahighly efficient set of tests that can perform very quicklyand without the expense of database transactions.
Testing the ActiveRecord framework in addition to your business logic is unnecessary - ActiveRecord has its ownsuite of tests. Therefore, disconnecting from the databaseallows you to test the business logic in isolation from the

Share & Embed

More from this user

Add a Comment

Characters: ...

George Ulmerleft a comment

Great article, but I didn't find the part about stopping worrying and loving testing.

sathiya_rockstarleft a comment

wow a nice title man - Mr Strangelove You are a rails Stanley Kubrick