#!/usr/bin/env ruby
# :title:Selenium Screenshot Helper
# = Name
# Selenium Screenshot Helper
#
# = Description
#
# Simply requiring this file in a Test::Unit test case, will cause
# every call to "assert" to capture a screenshot. No configuration is
# required other than including this module.
#
# Note that only the plain "assert" method is overridden (eg,
# screenshots will not be captured if you use assert_not,
# assert_equal, etc).
require "rubygems"
require "test/unit"
require "selenium/client"
module ScreenshotHelper
# == Save a screenshot to the log/png/ directory
#
# Screenshots are saved in log/png/ and a long entry noting the
# screenshot was taken, is written to log/test.log. Both of those
# paths are relative to the execution path.
#
# Note that this script does not create the log/ nor log/png/
# directories, and an error will be thrown unless they exist.
#
# File names will be a time-stamp plus the url of the page, less the
# protocol, with dots and slashes replaced by underscores, and all
# other alphanumerics removed.
#
# === IMPORTANT: Screenshots and proxyInjection mode
#
# @selenium.capture_entire_page_screenshot is not supported in proxy
# injection mode. In that case I have to use the much inferior
# capture_screenshot, which WILL NOT WORK if Firefox is in the
# background when the test runs.
#
# That is, when taking screenshots in proxy injection mode, the test
# suite cannot run in the background.
def screenshot
working_directory = File.expand_path($0).gsub /#{Regexp.escape $0}/, ''
if (PLATFORM.match /cygwin/)
working_directory = working_directory.gsub %r{/cygdrive/c/}, 'c:/'
end
url_as_filename = @selenium.location.gsub(%r{http.*://}, "").gsub(%r{[/.]}, "_").gsub(/[^A-Za-z0-9_.]/, "")
method_name = self.name.gsub /\(.*/, ''
klass_name = self.name.match(/\((.*)\)/)[1]
# TODO print the assertion count instead of the file name
filepath = "#{working_directory}log/png/#{klass_name}__#{method_name}__#{url_as_filename}__#{Time.now.to_i}.png"
if (@selenium.browser_string.match /\*pifirefox/)
@selenium.window_maximize
@selenium.capture_screenshot(filepath)
else
warn "working directory is #{working_directory}}"
@selenium.capture_entire_page_screenshot(filepath, "")
end
# TODO log entry should be a subroutine
method_identifier = "#{method_name}_#{klass_name}"
log = File.open "#{working_directory}log/test.log", "a"
log.write "#{Time.now.utc.localtime}: #{self.name}: screenshot: #{filepath}"
end
end
# == Assertions that take screenshots
#
# Override assert method of Test::Unit to add capturing screenshot,
# so that a screenshot is automatically captured just before any
# assert is made.
class Test::Unit::TestCase
include ScreenshotHelper
define_method(:assert) do
screenshot
super
end
end