Hi Tony, This would be a good addition to the advanced examples and frameworks on the wiki if you'd like to add it there: http://wiki.openqa.org/display/WTR/Examples
Charley Baker blog: http://blog.charleybaker.org/ Lead Developer, Watir, http://wtr.rubyforge.org QA Architect, Gap Inc Direct On Fri, Jul 17, 2009 at 7:53 AM, Tony <ynot...@gmail.com> wrote: > > Hi Dylan, > > I had modified the code .. and am not sure where to copy and paste > it ... > Iam including the whole source code for the modified ci reporter - > > To use this remove the require for ci_reporter and require the > modified file. > The usage remains the same .... > set the env variable ENV['CI_REPORTS'] = the folder where the reports > need to be stored. > The file also changes the report file slightly to include multiple > test classes that were run. > > require 'delegate' > require 'stringio' > require 'fileutils' > require 'test/unit' > require 'test/unit/ui/console/testrunner' > require 'ClassAttr' > > module YNOT > module YNOTE > > class OutputCapture < DelegateClass(IO) > # Start capturing IO, using the given block to assign self to > the proper IO global. > def initialize(io, &assign) > super > @delegate_io = io > @captured_io = StringIO.new > @assign_block = assign > @assign_block.call self > end > > # Finalize the capture and reset to the original IO object. > def finish > @assign_block.call @delegate_io > @captured_io.string > end > > # setup tee methods > %w(<< print printf putc puts write).each do |m| > module_eval(<<-EOS, __FILE__, __LINE__) > def #{m}(*args, &block) > @delegate_io.send(:#{m}, *args, &block) > @captured_io.send(:#{m}, *args, &block) > end > EOS > end > end > > > # Basic structure representing the running of a test suite. Used > to time tests and store results. > class TestSuite < Struct.new > (:name, :tests, :time, :failures, :errors, :assertions, :passed) > attr_accessor :testcases > attr_accessor :stdout, :stderr > def initialize(name) > super(name.to_s) # RSpec passes a "description" object instead > of a string > @testcases = [] > end > > # Starts timing the test suite. > def start > @start = Time.now > unless ENV['CI_CAPTURE'] == "off" > @capture_out = OutputCapture.new($stdout) {|io| $stdout = > io } > @capture_err = OutputCapture.new($stderr) {|io| $stderr = > io } > end > end > > # Finishes timing the test suite. > def finish > self.tests = testcases.size > self.time = Time.now - @start > #self.failures = testcases.inject(0) {|sum,tc| sum += > tc.failures.select{|f| f.failure? }.size } > self.failures = 0 > testcases.each { |tc| > self.failures += 1 if tc.failure? > } > self.errors = testcases.inject(0) {|sum,tc| sum += > tc.failures.select{|f| f.error? }.size } > #### > self.passed =0 > testcases.each { |tc| > self.passed += 1 if !(tc.failure? || tc.error?) > } > #puts "PASSED WAS - #{self.passed}" > #### > self.stdout = @capture_out.finish if @capture_out > self.stderr = @capture_err.finish if @capture_err > end > > # Creates the xml builder instance used to create the report xml > document. > def create_builder > require 'rubygems' > gem 'builder' > require 'builder' > # :escape_attrs is obsolete in a newer version, but should do > no harm > Builder::XmlMarkup.new(:indent => 2, :escape_attrs => true) > end > > # Creates an xml string containing the test suite results. > def to_xml > builder = create_builder > # more recent version of Builder doesn't need the escaping > def builder.trunc!(txt) > txt.sub(/\n.*/m, '...') > end > #builder.instruct! > attrs = {} > each_pair {|k,v| attrs[k] = builder.trunc!(v.to_s) unless > v.nil? || v.to_s.empty? } > builder.testsuite(attrs) do > @testcases.each do |tc| > tc.to_xml(builder) > end > builder.tag! "system-out" do > builder.cdata! self.stdout > end > builder.tag! "system-err" do > builder.cdata! self.stderr > end > end > end > > end > > > class TestCase < Struct.new(:name, :time, :assertions) > attr_accessor :failures > > def initialize(*args) > super > @failures = [] > end > > # Starts timing the test. > def start > @start = Time.now > end > > # Finishes timing the test. > def finish > #self.time = Time.now - @start > self.time = (Time.now - @start).to_i # roundoff the time to an > integer > end > > # Returns non-nil if the test failed. > def failure? > !failures.empty? && failures.detect {|f| f.failure? } > end > > # Returns non-nil if the test had an error. > def error? > !failures.empty? && failures.detect {|f| f.error? } > end > > # Writes xml representing the test result to the provided > builder. > def to_xml(builder) > attrs = {} > each_pair {|k,v| attrs[k] = builder.trunc!(v.to_s) unless > v.nil? || v.to_s.empty?} > builder.testcase(attrs) do > failures.each do |failure| > > # - This is where the type of failure is checked .. error > or failure > if failure.kind_of?(YNOT::YNOTE::TestUnitFailure) > builder.failure(:type => builder.trunc! > (failure.name), :message => builder.trunc!(failure.message)) do > builder.text!(failure.message + " (#{failure.name}) > \n") > builder.text!(failure.location) > end > else > > builder.error(:type => builder.trunc! > (failure.name), :message => builder.trunc!(failure.message)) do > builder.text!(failure.message + " (#{failure.name}) > \n") > builder.text!(failure.location) > end > end > > end > end > end > > end > > class ReportManager > @@current_suites = Array.new() > class_attr_accessor(:current_suites) > def initialize(prefix) > @basedir = ENV['CI_REPORTS'] || File.expand_path("#{Dir.getwd}/ > #{prefix.downcase}/reports") > @basename = "#...@basedir}/#{prefix.upcase}" > FileUtils.mkdir_p(@basedir) > end > > def write_report(suite) > File.open("#...@basename}-#{suite.name.gsub(/[^a-zA-Z0-9]+/, > '-')}.xml", "w") do |f| > f << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" > f << suite.to_xml > end > end > > # will do runtime reporting > def write_newreport_allsuites() > File.open("#...@basename}-#{"MYREPORTFILE".gsub(/[^a-zA-Z0-9]+/, > '-')}.xml", "w") do |f| > f << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<tests>\n" > ReportManager.current_suites.each { |st| > f << st.to_xml > } > f << "</tests>" > end > end > > end > > class Failure > def self.new(fault) > fault.kind_of?(Test::Unit::Failure) ? TestUnitFailure.new > (fault) : TestUnitError.new(fault) > end > end > > # Wrapper around a <code>Test::Unit</code> error to be used by the > test suite to interpret results. > class TestUnitError > def initialize(fault) > @fault = fault > end > def failure?() false end > def error?() true end > def name() @fault.exception.class.name end > def message() @fault.exception.message end > def location() @fault.exception.backtrace.join("\n") end > end > > # Wrapper around a <code>Test::Unit</code> failure to be used by > the test suite to interpret results. > class TestUnitFailure > def initialize(fault) > @fault = fault > end > def failure?() true end > def error?() false end > def name() Test::Unit::AssertionFailedError.name end > def message() @fault.message end > def location() @fault.location.join("\n") end > end > > # Replacement Mediator that adds listeners to capture the results > of the <code>Test::Unit</code> runs. > class TestUnit < Test::Unit::UI::TestRunnerMediator > def initialize(suite, report_mgr = nil) > super(suite) > @report_manager = report_mgr || ReportManager.new("test") > add_listener(Test::Unit::UI::TestRunnerMediator::STARTED, > &method(:started)) > add_listener(Test::Unit::TestCase::STARTED, &method > (:test_started)) > add_listener(Test::Unit::TestCase::FINISHED, &method > (:test_finished)) > add_listener(Test::Unit::TestResult::FAULT, &method(:fault)) > add_listener(Test::Unit::UI::TestRunnerMediator::FINISHED, > &method(:finished)) > end > > def started(result) > @suite_result = result > @last_assertion_count = 0 > @current_suite = nil > @unknown_count = 0 > @result_assertion_count = 0 > end > > def test_started(name) > test_name, suite_name = extract_names(name) > unless @current_suite && @current_suite.name == suite_name > finish_suite > start_suite(suite_name) > end > start_test(test_name) > end > > def test_finished(name) > finish_test > end > > def fault(fault) > tc = @current_suite.testcases.last > tc.failures << Failure.new(fault) > end > > def finished(elapsed_time) > finish_suite > end > > private > def extract_names(name) > match = name.match(/(.*)\(([^)]*)\)/) > if match > [match[1], match[2]] > else > @unknown_count += 1 > [name, "unknown...@unknown_count}"] > end > end > > def start_suite(suite_name) > @current_suite = TestSuite.new(suite_name) > @current_suite.start > ReportManager.current_suites << @current_suite > =begin > @current_suite = TestSuite.new(suite_name) > @current_suite.start > =end > end > > def finish_suite > if @current_suite > @current_suite.finish > @current_suite.assertions = @suite_result.assertion_count - > @last_assertion_count > @last_assertion_count = @suite_result.assertion_count > ##### remove this after you make the changes > ###...@report_manager.write_report(@current_suite) #old > report -- creates a xmlfile for each class > ################################ > #...@report_manager.write_newreport(@current_suites) > @report_manager.write_newreport_allsuites() > end > end > > def start_test(test_name) > tc = TestCase.new(test_name) > tc.start > @current_suite.testcases << tc > > #=begin --- This is written for returning results in runtime.. after > each testcase is run... when running only name will be present > @current_suite.assertions = @suite_result.assertion_count - > @last_assertion_count > @last_assertion_count = @suite_result.assertion_count > ####...@report_manager.write_report(@current_suite) #old > report -- creates a xmlfile for each class > @report_manager.write_newreport_allsuites() > #...@report_manager.write_newreport_testcaselevel > (@current_suites) > #...@report_manager.write_newreport(@current_suites) > #=end > end > > def finish_test > tc = @current_suite.testcases.last > tc.finish > tc.assertions = @suite_result.assertion_count - > @result_assertion_count > @result_assertion_count = @suite_result.assertion_count > @report_manager.write_newreport_allsuites() > end > end > > end > end > > > module Test #:nodoc:all > module Unit > module UI > module Console > class TestRunner > def create_mediator(suite) > # swap in our custom mediator > return YNOT::YNOTE::TestUnit.new(suite) > end > end > end > end > end > end > > If this doesnt work ... i could mail you the whole file. > > Thanks, > Tony > > > --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Watir General" group. To post to this group, send email to watir-general@googlegroups.com Before posting, please read the following guidelines: http://wiki.openqa.org/display/WTR/Support To unsubscribe from this group, send email to watir-general-unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/watir-general -~----------~----~----~----~------~----~------~--~---