Using RCov with a remote server or mechanize

Here at workbooks, we use a number of different testing techniques including server-based unit and rspec testing and client-based selenium testing.

To power our ExtJS interface, requests to our RESTFul API with a specific extension reply with an ExtJS compatible JSON object. In order to test if the JSON coming back is what we expect, we wrote a test helper for rspec which uses mechanize to make HTTP requests and a JSON parser to analyse the response against known key/value pairs.

Like many, we wanted to be able to determine the effectiveness of our tests in various areas of our code base and also integrate this into our continuous integration system so we have a constant indicator of whether we are testing new code. The best way to do this is using RCov.

We soon found that when we ran our rspec tests using RCov, that the code paths were not being marked as executed. After a little thinking; we realised that our rspec tests were not invoking the ruby code directly because of our mechanize implementation. A quick google search later revealed that you can also run script/server through rcov – an ideal solution:


rcov script/server -o log/coverage --rails

We modified our cruise control rake task to run up the server using the snippet above and ensured that the coverage report gets put in the log directory (as our custom build artifacts are published from the contents of the log directory). The end result being, that for every build; we now have a rcov report for our tests.

It’s also worth noting that we use the report aggregation feature of rcov (not shown in the example for clarity), as the server is only started for the mechanize/client-side based tests. Model and controller unit testing etc is run without a need for the server.

Undefined local variable or method ` ‘

Ever had this little nugget of information? Lets play spot the difference…

Example 1
def my_method(args) # :nodoc:

Example 2
def my_method(args) # :nodoc:

You will notice that there is no apparent difference, which is why I couldn’t work out why one line of code ran, and one caused an error. Anyway, to cut a long story short, I found a unicode character on the line that wasn’t working – and that unicode character didn’t have a corresponding variable or method!

So, Chris’ Thursday Tip is to turn on invisible characters in TextMate (View -> Show Invisibles ⌥⌘I).

Including developer notes as part of your cruisecontrol.rb task

So we can stay on top of our TODOs, FIXMEs and CHANGEs, we include the “notes” rake task output as one of the custom build artifacts. As I haven’t found a better way to pipe the output of invoked rake tasks, we redirect stdout into a file.

Add to your cruise.rake file:

orig_stdout = $stdout
$stdout = File.new('log/developer_notes.log', 'w+')
Rake::Task['notes'].invoke
$stdout = orig_stdout

And ensure that all .log files within the log/ directory are copied to the custom build artifacts by adding the following into your cruise_config.rb

Project.configure do |project|
  project.log_publisher.globs = ['log/*.log']
end

Running remote rdebug in client-server mode

I’m still trying to get rdebug to debug my script/server on a remote machine from Textmate and still no luck.  However, I had another play with rdebug and have finally managed to get the client-server mode working. I never managed to find any blog posts that worked for me, so hopefully this will work for you!

On the server (from your Rails application root directory)
rdebug -sw ./script/server

On your local machine
rdebug -c -hIP.ADDRESS.OF.SERVER

Just as a reference I’m running ruby-debug 0.10.1 as a gem on OS X 10.5.4.