Automated Javascript Rails Testing

22 Jan 2008

On my last project we did some javascript unit testing in browser using the unittest.js library from scriptaculous, but because it’s kind of a pain to set up and integrate into your build, I didn’t get it working on my current job. Which makes me a bad person. However, Dr Nic Williams has made yours and my life easier with his javascript_test plugin for rails. Now I can type:

ruby script/generate javascript_test fancy_javascript_file

And get a fancy_javascript_file_test.html to test my fancy_javascript_file.js. It’s all set up to go right at the javascript file. Just open the html file in a browser and it runs the tests. The sweet doctor explains it all better than me so go check out his site.

What I want to talk about is trying to integrate this into your Cruise Control build. The first problem we faced is that the tasks that come with the plugin don’t close the tabs created in the browser. So after 10-20 builds, you’re going to have way too many tabs and some memory problems. My teammate Toby Tripp came up with this:

def teardown
applescript «-EOS if macos?
tell application “System Events”
tell process “Firefox”
set frontmost to true
click menu item “Close Tab” of menu “File” of menu bar 1
end tell
end tell
EOS
end

This code snippet goes inside

class FirefoxBrowser < Browser

inside the plugins/javascript_test/lib/javascript_test.rb file. We could have just killed Firefox but we needed to play nice in case any other builds were using Firefox at that moment (we test with Selenium to use Firefox to click through the app).

Now all you have to do is change the position of the browser.teardown call in that same file in the ‘define’ method. By default, teardown is called just before the end of the block created by

@browsers.each do browser

But I want it to get called after every test so you can put it just before the end of the block created by:

@tests.each do test

So that the end result looks like this:

def define
trap(“INT”) { @server.shutdown }
t = Thread.new { @server.start }

# run all combinations of browsers and tests  
@browsers.each do |browser|  
  if browser.supported?  
    browser.setup  
    @tests.each do |test|  
      browser.visit(" http://localhost:4711#{test}?resultsURL=http://localhost:4711/results&t=" + ("%.6f" % Time.now.to_f))  
      result = @queue.pop  
      puts "#{test} on #{browser}: #{result}"  
      @result = false unless result == 'SUCCESS'  
      browser.teardown  
    end  
  else  
    puts "Skipping #{browser}, not supported on this OS"  
  end  
  # browser.teardown  
end  
 @server.shutdown  
 t.join      end  

You can see by the comment where the teardown used to be. So now when you run your test the tabs will close when finished. In my next post I’ll talk about how to fail the build when the javascript tests fail.

Oh, and I’d like to thank Mike Ward for turning me on to javascript unit testing in the first place.