Archive for December 2009

 
 

Follow table links in cucumber

On a page you’ll quite often have a table like the following

Book Author  
Harry Potter and half blood prince J.K. Rowling Delete
The Cuckoo’s Egg: Tracking a Spy Through the Maze of Computer Espionage Cliff Stoll Delete

In your cucumber steps you want to say

Given I am on the books page
When I follow the "Delete" link for "Harry Potter and half blood prince"
Then ...

Out of the box webrat doesn’t have a step that will allow you to do this. Let’s create one that will do the job

When /^I follow the "([^\"]*)" link for "([^\"]*)"$/ do |link, cell_value|
  within "//*[.//text()='#{cell_value}' and .//a[text()='#{link}']]" do |scope|
   scope.click_link link
 end
end

This works great, it even works outside tables, the step will work so long as the text and link have a common parent in the dom. Just one problem, for this step to work webrat needs to understand xpath selectors. Here’s a little monkey patch that will get it working in webrat 0.6.0.

#lib/webrat_extensions.rb
module Webrat
  class Scope
    protected
      def scoped_dom
        begin
          @scope.dom.css(@selector).first
        rescue Nokogiri::CSS::SyntaxError, Nokogiri::XML::XPath::SyntaxError => e
          begin
            @scope.dom.xpath(@selector).first
          rescue Nokogiri::XML::XPath::SyntaxError
            raise e
          end
        end
      end
  end
end

Once you’ve added the patch our new webrat step will work. As a bonus you also get to use xpath selectors anywhere you use css selectors.

rcov for cucumber and shoulda

There seems to be a lot of bad info out there about this. It’s really quite simple, you just have to make use of the built in tasks provided by cucumber and rcov. The following task definitions will generate coverage reports for cucumber features and rails tests in coverage.features and converage.tests respectively. You’ll also get the overviews for the same reports at the command line when you run the tasks.

require 'cucumber/rake/task'
require 'rcov/rcovtask'

namespace :rcov do

  rcov_opts = ['-T','--exclude /Library/Ruby/Site/*,.rip/*,gems/*,rcov*,features/step_definitions/webrat_steps.rb']

  desc 'Measures cucumber coverage'
  Cucumber::Rake::Task.new(:features) do |t|
    t.rcov = true
    t.rcov_opts = rcov_opts
    t.rcov_opts << '-o coverage.features'
  end

  desc 'Measures shoulda coverage'
  Rcov::RcovTask.new(:tests) do |t|
    t.libs << 'test'
    t.test_files = FileList['test/unit/*_test.rb','test/functional/*_test.rb','test/unit/helpers/*_test.rb']
    t.rcov_opts = rcov_opts
    t.output_dir = "coverage.tests"
  end

  desc 'Measures all coverage'
  task :all do
    ["features", "tests"].each{ |task| Rake::Task["rcov:#{task}"].invoke }
  end
end