Using Webrat assertions in your functional tests

written about 2 months ago |
4 comments

I’m tired of assert_select. The multi-parameter syntax is confusing and hard to follow, and the semantics aren’t clear. For example, in a test like this:

assert_select "div[class=note]" do
  assert_select "div[class=company_name]", company_name
end

Are we ensuring that there is at least one note div with a company name div, or that all note divs have a company name div? What is that second argument? Is it the text inside the company name div, the number of times that div should be there, or a replacement value for imbedded question marks (hint: all three).

Also, why are we specifying what type of element we see in our tests? In the days of jQuery and XPaths, the element types don’t matter nearly as much as they used to.

Webrat gets it right with assert_have_selector

assert_have_selector ".note .company_name:contains('#{company_name}')"

Much better! Same, consistent XPath selector syntax as jQuery, and much more concise to boot!

Webrat’s firmly aimed at integration testing. Nothing at all wrong with integration testing, but there’s also no reason to leave our functional tests behind.

Wanna use the Webrat assertions in your functional tests as well? Three easy steps:

  1. Require webrat
  2. Include the matchers module
  3. Add a response_body method to your testcase class

Here’s the snippet from my test/test_helper.rb file:

require 'webrat'
class ActionController::TestCase
  include Webrat::Matchers
  def response_body
    @response.body
  end
end

VoilĂ !

Comments

said about 2 months ago
Posted by author

Can’t you write the assert_select selector as “.note .company_name” as well? I know that assert_select uses the “.” for class and “#” for ID, and that it lets you compose selectors in a single line.

said about 2 months ago
Posted by author

@noel – Well, the documentation doesn’t give any examples of using assert_select that way, but it sure looks like you’re right. The following will work:

assert_select ".note .company_name", :text => company_name

Though, that still doesn’t address the main issue (compounds it, in fact): The API for assert_select tries to do too much with a single method call. I don’t think I’ve seen a method with as variable a signature as assert_select, and I’ve seen tons of developer confusion arise from it.

said about 2 months ago
Posted by author

I use this for my assert_select documentation: http://content.labnotes.org/assert_select/assert_select.html — I grant it’s way too complicated, but there’s a boatload of functionality there.

said about 2 months ago
Posted by author

Hear hear! I believe it’s also faster, using Nokogiri under the hood. This is just a witchcraft-like belief on my part, though.

I tried to add assert_have_selector to cheat last week but I still can’t access it from the command line. Needs more examples, too.

Leave a comment:

(click here for formatting tips)