At one of the projects in BEKK we’re using Watir extensively to verify that the web application is working as expected. We’re using RSpec to drive Watir.
Every now and then the Watir specs fail (either on a developer machine or on the Continuous Integration machine). For each failure we want to know what HTML the browser had, and what the browser looked like at the time of failure. Knowing this makes the process of hunting down the cause much easier, because it gives us more context information.
Watir comes with built-in support for screenshots via Watir::ScreenCapture, but it is a really nasty hack so we didn’t want to use that. We also wanted a nice-looking HTML report for all the specs, with a screenshot of the browser (and a link to the HTML) for each of the failing specs.
About the same time as I released Win32::Screenshot, Luke Redpath contributed a much improved HTML report for RSpec. (The RSpec website has some more examples of passing and failing specs).
Getting screenshots into the RSpec HTML reports is quite easy. First, in the spec’s teardown we have to take a screenshot and store it in a file with a unique name. (I’ve simplified the code a little here to illustrate the technique – the full code is available in RSpec’s svn). Let’s start with the spec:
context "Google's search page" do
setup do
@browser.goto('http://www.google.com')
end
specify "should find rspec's home page when I search for rspec" do
@browser.text_field(:name, "q").set("rspec")
@browser.button(:name, "btnG").click
@browser.contains_text("rspec.rubyforge.org").should_not_be nil # should_contain_text is RSpec sugar
end
specify "should find rspec's home page when I search for 'better than fudge' (will probably fail)" do
@browser.text_field(:name, "q").set("better than fudge")
@browser.button(:name, "btnG").click
@browser.contains_text("rspec.rubyforge.org").should_not_be nil
end
specify "should not find Ali G when I search for respec" do
@browser.text_field(:name, "q").set("respec")
@browser.button(:name, "btnG").click
@browser.contains_text("Ali G").should_be nil
end
teardown do
# Take the screenshot
width, height, bmp = Win32::Screenshot.foreground
img = Magick::Image.from_blob(bmp)[0]
# dir and spec number are defined outside
img_path = "#{dir}/#{spec_number}.png"
img.write(img_path)
# Get the HTML from Watir and save it too
File.open("#{dir}/#{spec_number}.html", "w") {|io| io.write(browser.html)}
end
end
RSpec will output a HTML report when you run it with —format html, but it doesn’t link to images or the HTML source. We have to write a little extension to RSpec’s default HTML formatter:
class WebTestHtmlFormatter < Spec::Runner::Formatter::HtmlFormatter
def extra_failure_content
@output.puts ""
@output.puts ""
end
end
Finally we have to tell RSpec (which is driving Watir via our specs) to use our WebTestHtmlFormatter when it runs the specs:
spec --require web_test_html_formatter.rb --format WebTestHtmlFormatter
The astute reader might have noticed that in the clickable screenshot above I have a Safari window and not an Internet Explorer one. The fact is, you can use this very same technique on a Mac, using Dave Hoover’s SafariWatir. The only difference is that you’ll use OS X’ built-in screencapture command to take the screenshots.
If you want to try this out, install the latest RSpec (0.7.4 or later). Then check out RSpec with subversion and peek inside vendor/web_spec. (The path within the repository may change soon).