#!/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