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).
This is very nice. And Luke did a beautiful job on the HTML output.
It’s also great to see that you have a blog now. I just can’t get enough of rSpec!
Any idea how to implement this with Selenium?
You can do this with the SeleniumRC Ruby bindings. Essentially it gives Selenium a Watir-like API that allows you to drive the browser from Ruby.
If you have already invested in lots of HTML-style Selenium tests, you may be able to hack Selenium-RC so that it can push those HTML tests up to the browser (if it doesn’t support that already – I’m not sure).
Another option could be to hack Selenium to send a HTTP request to a screenshot server. This is a tiny HTTP server that takes screenshots when you hit it with /foreground or /desktop – there is an example in Win32::Screenshot’s subversion.
And if that doesn’t work for you, use your imagination ;-)
Sweet. The HTML output with the screenshot is especially nice. But about RSpec: It would be nice to improve on the diagnostic message “nil should not be nil”. Is that at all possible?
Johannes: Anything is possible!
The same topic has come up before – see the mail thread that starts here
You’re welcome to submit an RFE, patch or whatever for this.
meekish, I’ve done some work to integrate Rails and SeleniumRC.
http://svn.viney.net.nz/things/rails/plugins/selenium_jelly/
Hey Boss, how about grabbing screenshots that can be used by the customer as documentation (integrating all shots in a nice PDF would be the next step)
Hey Boss, how about grabbing screenshots that can be used by the customer as documentation (integrating all shots in a nice PDF would be the next step)
This produces a file of 1996kB,
that MSPaint displays as blank. It’s got a BMP header, but the rest of the file is Hex 00’s
Any ideas why ?
How can i start to write a program. Pls exolain me.
I have these specilities. 1. Watir 2.wet
Please give one example program to take screenshot of any web page
How to use this? I could not get to your example. Can you post some Full Examples?. I just keep getting the error undefined method `context’ for main:Object (NoMethodError). My whole day is gone
Shaun