I use FIT and HTMLUnit during the day for really, truly testing my web application. At night, when I transform myself into a Ruby monster, it's RSpec and Hpricot (the "enjoyable" HTML parser). I had tried before with assert_select
, but I ended up with a zillion nested with_tag
statements that didn't help my digestion.
At work, we have written a little bit of transformation so that the tables we see in our FIT tests look pretty similar to the tables we are testing in our application. I wanted to do the same with RSpec so it would look like this:
table = doc.search("//table[@id='invitations']").first
table.should_match([
[ "email", "sent", "accepted", "login" ],
[ "foo@bar", "2008-02-10", "2008-02-16", "foobar" ],
[ "yoyo@toto", "2008-02-15", "2008-02-17", "yoyo" ],
[ "will@not.accept", "2008-02-15", "", "" ],
])
The following little bit of code does the job (I dropped it into my spec_helper)
module Hpricot
class Elem
def should_match(array)
array.each_with_index { |row_data, row_index|
if (row_index == 0)
cell_tag = "th"
row = 1
else
cell_tag = "td"
row = row_index
end
row_data.each_with_index { |cell_text, column_index|
q = "//tr[#{row}]/#{cell_tag}[#{column_index + 1}]"
self.search(q).inner_html.strip.should == cell_text
}
}
end
end
end
This is a really basic solution ... there's lots of work before I can use it to test attributes and nested markup in an equally readable way. And it assumes the first row is in a <thead>
and contains <th>
elements; and that the remainder is under a <tbody>
element (this is how Markaby generates markup (it also happens to be correct, if you have a header row)).
I'm a total Hpricot n00b
, so there's probably a better way to implement this, but I'm enjoying it for now ... please let me know if you have a better way :)