From 455fa3674f66a26458c6185aa93216844352825a Mon Sep 17 00:00:00 2001 From: Derek Ekins Date: Mon, 18 Jul 2011 10:29:50 +0100 Subject: [PATCH] results directory is now relative to directory tests are executed in --- lib/hydra/cucumber/partial_html.rb | 635 +-------------------- lib/hydra/listener/cucumber_html_report.rb | 96 +--- lib/hydra/runner.rb | 4 +- 3 files changed, 20 insertions(+), 715 deletions(-) diff --git a/lib/hydra/cucumber/partial_html.rb b/lib/hydra/cucumber/partial_html.rb index 3763e2a..3b06a25 100644 --- a/lib/hydra/cucumber/partial_html.rb +++ b/lib/hydra/cucumber/partial_html.rb @@ -3,642 +3,21 @@ require 'cucumber/formatter/html' module Hydra module Formatter class PartialHtml < Cucumber::Formatter::Html - # - # def initialize(step_mother, path_or_io, options) - # @io = ensure_io(path_or_io, "html") - # @step_mother = step_mother - # @options = options - # @buffer = {} - # @builder = create_builder(@io) - # @feature_number = 0 - # @scenario_number = 0 - # @step_number = 0 - # @header_red = nil - # @delayed_messages = [] - # @img_id = 0 - # end - # - # def embed(src, mime_type, label) - # case(mime_type) - # when /^image\/(png|gif|jpg|jpeg)/ - # embed_image(src, label) - # end - # end - # - # def embed_image(src, label) - # id = "img_#{@img_id}" - # @img_id += 1 - # @builder.span(:class => 'embed') do |pre| - # pre << %{#{label}
  - # } - # end - # end - # - # def before_features(features) - - #@step_count = get_step_count(features) - # - ## - #@builder.declare!( - # :DOCTYPE, - # :html, - # :PUBLIC, - # '-//W3C//DTD XHTML 1.0 Strict//EN', - # 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd' - #) - # - #@builder << '' - # @builder.head do - # @builder.meta(:content => 'text/html;charset=utf-8') - # @builder.title 'Cucumber' - # inline_css - # inline_js - #end - #@builder << '' - #@builder << "" - #@builder << '
' - #@builder.div(:id => 'cucumber-header') do - # @builder.div(:id => 'label') do - # @builder.h1('Cucumber Features') - # end - # @builder.div(:id => 'summary') do - # @builder.p('',:id => 'totals') - # @builder.p('',:id => 'duration') - # @builder.div(:id => 'expand-collapse') do - # @builder.p('Expand All', :id => 'expander') - # @builder.p('Collapse All', :id => 'collapser') - # end - # end - #end + # we do not want the default implementation as we will write our own header end def after_features(features) - #print_stats(features) - #@builder << '
' - #@builder << '' - #@builder << '' + # we do not want the default implementation as we will write our own footer end - # - # def before_feature(feature) - # @exceptions = [] - # @builder << '
' - # end - # - # def after_feature(feature) - # @builder << '
' - # end - # - # def before_comment(comment) - # @builder << '
'
-  #    end
-  #
-  #    def after_comment(comment)
-  #      @builder << '
' - # end - # - # def comment_line(comment_line) - # @builder.text!(comment_line) - # @builder.br - # end - # - # def after_tags(tags) - # @tag_spacer = nil - # end - # - # def tag_name(tag_name) - # @builder.text!(@tag_spacer) if @tag_spacer - # @tag_spacer = ' ' - # @builder.span(tag_name, :class => 'tag') - # end - # - # def feature_name(keyword, name) - # lines = name.split(/\r?\n/) - # return if lines.empty? - # @builder.h2 do |h2| - # @builder.span(keyword + ': ' + lines[0], :class => 'val') - # end - # @builder.p(:class => 'narrative') do - # lines[1..-1].each do |line| - # @builder.text!(line.strip) - # @builder.br - # end - # end - # end - # - # def before_background(background) - # @in_background = true - # @builder << '
' - # end - # - # def after_background(background) - # @in_background = nil - # @builder << '
' - # end - # - # def background_name(keyword, name, file_colon_line, source_indent) - # @listing_background = true - # @builder.h3 do |h3| - # @builder.span(keyword, :class => 'keyword') - # @builder.text!(' ') - # @builder.span(name, :class => 'val') - # end - # end - # - # def before_feature_element(feature_element) - # @scenario_number+=1 - # @scenario_red = false - # css_class = { - # Ast::Scenario => 'scenario', - # Ast::ScenarioOutline => 'scenario outline' - # }[feature_element.class] - # @builder << "
" - # end - # - # def after_feature_element(feature_element) - # @builder << '
' - # @open_step_list = true - # end - # - # def scenario_name(keyword, name, file_colon_line, source_indent) - # @builder.span(:class => 'scenario_file') do - # @builder << file_colon_line - # end - # @listing_background = false - # @builder.h3(:id => "scenario_#{@scenario_number}") do - # @builder.span(keyword + ':', :class => 'keyword') - # @builder.text!(' ') - # @builder.span(name, :class => 'val') - # end - # end - # - # def before_outline_table(outline_table) - # @outline_row = 0 - # @builder << '' - # end - # - # def after_outline_table(outline_table) - # @builder << '
' - # @outline_row = nil - # end - # - # def before_examples(examples) - # @builder << '
' - # end - # - # def after_examples(examples) - # @builder << '
' - # end - # - # def examples_name(keyword, name) - # @builder.h4 do - # @builder.span(keyword, :class => 'keyword') - # @builder.text!(' ') - # @builder.span(name, :class => 'val') - # end - # end - # - # def before_steps(steps) - # @builder << '
    ' - # end - # - # def after_steps(steps) - # @builder << '
' - # end - # - # def before_step(step) - # @step_id = step.dom_id - # @step_number += 1 - # @step = step - # end - # + def after_step(step) - #move_progress + # need an alterantive way of incrementing progress/outputing stats end - # - # def before_step_result(keyword, step_match, multiline_arg, status, exception, source_indent, background) - # @step_match = step_match - # @hide_this_step = false - # if exception - # if @exceptions.include?(exception) - # @hide_this_step = true - # return - # end - # @exceptions << exception - # end - # if status != :failed && @in_background ^ background - # @hide_this_step = true - # return - # end - # @status = status - # return if @hide_this_step - # set_scenario_color(status) - # @builder << "
  • " - # end - # - # def after_step_result(keyword, step_match, multiline_arg, status, exception, source_indent, background) - # return if @hide_this_step - # # print snippet for undefined steps - # if status == :undefined - # step_multiline_class = @step.multiline_arg ? @step.multiline_arg.class : nil - # @builder.pre do |pre| - # pre << @step_mother.snippet_text(@step.actual_keyword,step_match.instance_variable_get("@name") || '',step_multiline_class) - # end - # end - # @builder << '
  • ' - # print_messages - # end - # - # def step_name(keyword, step_match, status, source_indent, background) - # @step_matches ||= [] - # background_in_scenario = background && !@listing_background - # @skip_step = @step_matches.index(step_match) || background_in_scenario - # @step_matches << step_match - # - # unless @skip_step - # build_step(keyword, step_match, status) - # end - # end - # - # def exception(exception, status) - # build_exception_detail(exception) - # end - # - # def extra_failure_content(file_colon_line) - # @snippet_extractor ||= SnippetExtractor.new - # "
    #{@snippet_extractor.snippet(file_colon_line)}
    " - # end - # - # def before_multiline_arg(multiline_arg) - # return if @hide_this_step || @skip_step - # if Ast::Table === multiline_arg - # @builder << '' - # end - # end - # - # def after_multiline_arg(multiline_arg) - # return if @hide_this_step || @skip_step - # if Ast::Table === multiline_arg - # @builder << '
    ' - # end - # end - # - # def doc_string(string) - # return if @hide_this_step - # @builder.pre(:class => 'val') do |pre| - # @builder << string.gsub("\n", ' ') - # end - # end - # - # - # def before_table_row(table_row) - # @row_id = table_row.dom_id - # @col_index = 0 - # return if @hide_this_step - # @builder << "" - # end - # - # def after_table_row(table_row) - # return if @hide_this_step - # print_table_row_messages - # @builder << '' - # if table_row.exception - # @builder.tr do - # @builder.td(:colspan => @col_index.to_s, :class => 'failed') do - # @builder.pre do |pre| - # pre << format_exception(table_row.exception) - # end - # end - # end - # set_scenario_color_failed - # end - # if @outline_row - # @outline_row += 1 - # end - # @step_number += 1 - # move_progress - # end - # - # def table_cell_value(value, status) - # return if @hide_this_step - # - # @cell_type = @outline_row == 0 ? :th : :td - # attributes = {:id => "#{@row_id}_#{@col_index}", :class => 'step'} - # attributes[:class] += " #{status}" if status - # build_cell(@cell_type, value, attributes) - # set_scenario_color(status) - # @col_index += 1 - # end - # - # def puts(message) - # @delayed_messages << message - # #@builder.pre(message, :class => 'message') - # end - # - # def print_messages - # return if @delayed_messages.empty? - # - # #@builder.ol do - # @delayed_messages.each do |ann| - # @builder.li(:class => 'step message') do - # @builder << ann - # end - # end - # #end - # empty_messages - # end - # - # def print_table_row_messages - # return if @delayed_messages.empty? - # - # @builder.td(:class => 'message') do - # @builder << @delayed_messages.join(", ") - # end - # empty_messages - # end - # - # def empty_messages - # @delayed_messages = [] - # end - # - # protected - # - # def build_exception_detail(exception) - # backtrace = Array.new - # @builder.div(:class => 'message') do - # message = exception.message - # if defined?(RAILS_ROOT) && message.include?('Exception caught') - # matches = message.match(/Showing (.+)<\/i>(?:.+)#(\d+)/) - # backtrace += ["#{RAILS_ROOT}/#{matches[1]}:#{matches[2]}"] - # message = message.match(/([^(\/)]+)<\//m)[1] - # end - # @builder.pre do - # @builder.text!(message) - # end - # end - # @builder.div(:class => 'backtrace') do - # @builder.pre do - # backtrace = exception.backtrace - # backtrace.delete_if { |x| x =~ /\/gems\/(cucumber|rspec)/ } - # @builder << backtrace_line(backtrace.join("\n")) - # end - # end - # extra = extra_failure_content(backtrace) - # @builder << extra unless extra == "" - # end - # - # def set_scenario_color(status) - # if status == :undefined or status == :pending - # set_scenario_color_pending - # end - # if status == :failed - # set_scenario_color_failed - # end - # end - # - # def set_scenario_color_failed - # @builder.script do - # @builder.text!("makeRed('cucumber-header');") unless @header_red - # @header_red = true - # @builder.text!("makeRed('scenario_#{@scenario_number}');") unless @scenario_red - # @scenario_red = true - # end - # end - # - # def set_scenario_color_pending - # @builder.script do - # @builder.text!("makeYellow('cucumber-header');") unless @header_red - # @builder.text!("makeYellow('scenario_#{@scenario_number}');") unless @scenario_red - # end - # end - # - # def get_step_count(features) - # count = 0 - # features = features.instance_variable_get("@features") - # features.each do |feature| - # #get background steps - # if feature.instance_variable_get("@background") - # background = feature.instance_variable_get("@background") - # background.init - # background_steps = background.instance_variable_get("@steps").instance_variable_get("@steps") - # count += background_steps.size - # end - # #get scenarios - # feature.instance_variable_get("@feature_elements").each do |scenario| - # scenario.init - # #get steps - # steps = scenario.instance_variable_get("@steps").instance_variable_get("@steps") - # count += steps.size - # - # #get example table - # examples = scenario.instance_variable_get("@examples_array") - # unless examples.nil? - # examples.each do |example| - # example_matrix = example.instance_variable_get("@outline_table").instance_variable_get("@cell_matrix") - # count += example_matrix.size - # end - # end - # - # #get multiline step tables - # steps.each do |step| - # multi_arg = step.instance_variable_get("@multiline_arg") - # next if multi_arg.nil? - # matrix = multi_arg.instance_variable_get("@cell_matrix") - # count += matrix.size unless matrix.nil? - # end - # end - # end - # return count - # end - # - # def build_step(keyword, step_match, status) - # step_name = step_match.format_args(lambda{|param| %{#{param}}}) - # @builder.div(:class => 'step_name') do |div| - # @builder.span(keyword, :class => 'keyword') - # @builder.span(:class => 'step val') do |name| - # name << h(step_name).gsub(/<span class="(.*?)">/, '').gsub(/<\/span>/, '') - # end - # end - # - # step_file = step_match.file_colon_line - # step_file.gsub(/^([^:]*\.rb):(\d*)/) do - # if ENV['TM_PROJECT_DIRECTORY'] - # step_file = "#{$1}:#{$2} " - # end - # end - # - # @builder.div(:class => 'step_file') do |div| - # @builder.span do - # @builder << step_file - # end - # end - # end - # - # def build_cell(cell_type, value, attributes) - # @builder.__send__(cell_type, attributes) do - # @builder.div do - # @builder.span(value,:class => 'step param') - # end - # end - # end - # - # def inline_css - # @builder.style(:type => 'text/css') do - # @builder << File.read(File.dirname(__FILE__) + '/cucumber.css') - # end - # end - # - # def inline_js - # @builder.script(:type => 'text/javascript') do - # @builder << inline_jquery - # @builder << inline_js_content - # end - # end - # - # def inline_jquery - # File.read(File.dirname(__FILE__) + '/jquery-min.js') - # end - # - # def inline_js_content - # <<-EOF - # - #SCENARIOS = "h3[id^='scenario_']"; - # - #$(document).ready(function() { - # $(SCENARIOS).css('cursor', 'pointer'); - # $(SCENARIOS).click(function() { - # $(this).siblings().toggle(250); - # }); - # - # $("#collapser").css('cursor', 'pointer'); - # $("#collapser").click(function() { - # $(SCENARIOS).siblings().hide(); - # }); - # - # $("#expander").css('cursor', 'pointer'); - # $("#expander").click(function() { - # $(SCENARIOS).siblings().show(); - # }); - #}) - # - #function moveProgressBar(percentDone) { - # $("cucumber-header").css('width', percentDone +"%"); - #} - #function makeRed(element_id) { - # $('#'+element_id).css('background', '#C40D0D'); - # $('#'+element_id).css('color', '#FFFFFF'); - #} - #function makeYellow(element_id) { - # $('#'+element_id).css('background', '#FAF834'); - # $('#'+element_id).css('color', '#000000'); - #} - # - # EOF - # end - # - def move_progress - #@builder << " " + + def percent_done + 0 end - # - # def percent_done - # result = 100.0 - # if @step_count != 0 - # result = ((@step_number).to_f / @step_count.to_f * 1000).to_i / 10.0 - # end - # result - # end - # - # def format_exception(exception) - # (["#{exception.message}"] + exception.backtrace).join("\n") - # end - # - # def backtrace_line(line) - # line.gsub(/\A([^:]*\.(?:rb|feature|haml)):(\d*).*\z/) do - # if ENV['TM_PROJECT_DIRECTORY'] - # "#{$1}:#{$2} " - # else - # line - # end - # end - # end - # - # def print_stats(features) - # @builder << "" - # @builder << "" - # end - # - # def print_stat_string(features) - # string = String.new - # string << dump_count(@step_mother.scenarios.length, "scenario") - # scenario_count = print_status_counts{|status| @step_mother.scenarios(status)} - # string << scenario_count if scenario_count - # string << "
    " - # string << dump_count(@step_mother.steps.length, "step") - # step_count = print_status_counts{|status| @step_mother.steps(status)} - # string << step_count if step_count - # end - # - # def print_status_counts - # counts = [:failed, :skipped, :undefined, :pending, :passed].map do |status| - # elements = yield status - # elements.any? ? "#{elements.length} #{status.to_s}" : nil - # end.compact - # return " (#{counts.join(', ')})" if counts.any? - # end - # - # def dump_count(count, what, state=nil) - # [count, state, "#{what}#{count == 1 ? '' : 's'}"].compact.join(" ") - # end - # - # def create_builder(io) - # OrderedXmlMarkup.new(:target => io, :indent => 0) - # end - # - # class SnippetExtractor #:nodoc: - # class NullConverter; def convert(code, pre); code; end; end #:nodoc: - # begin; require 'syntax/convertors/html'; @@converter = Syntax::Convertors::HTML.for_syntax "ruby"; rescue LoadError => e; @@converter = NullConverter.new; end - # - # def snippet(error) - # raw_code, line = snippet_for(error[0]) - # highlighted = @@converter.convert(raw_code, false) - # highlighted << "\n# gem install syntax to get syntax highlighting" if @@converter.is_a?(NullConverter) - # post_process(highlighted, line) - # end - # - # def snippet_for(error_line) - # if error_line =~ /(.*):(\d+)/ - # file = $1 - # line = $2.to_i - # [lines_around(file, line), line] - # else - # ["# Couldn't get snippet for #{error_line}", 1] - # end - # end - # - # def lines_around(file, line) - # if File.file?(file) - # lines = File.open(file).read.split("\n") - # min = [0, line-3].max - # max = [line+1, lines.length-1].min - # selected_lines = [] - # selected_lines.join("\n") - # lines[min..max].join("\n") - # else - # "# Couldn't get snippet for #{file}" - # end - # end - # - # def post_process(highlighted, offending_line) - # new_lines = [] - # highlighted.split("\n").each_with_index do |line, i| - # new_line = "#{offending_line+i-2}#{line}" - # new_line = "#{new_line}" if i == 2 - # new_lines << new_line - # end - # new_lines.join("\n") - # end - # - # end end end end diff --git a/lib/hydra/listener/cucumber_html_report.rb b/lib/hydra/listener/cucumber_html_report.rb index f1c4bfd..61349dd 100644 --- a/lib/hydra/listener/cucumber_html_report.rb +++ b/lib/hydra/listener/cucumber_html_report.rb @@ -3,64 +3,39 @@ module Hydra #:nodoc: module Listener #:nodoc: # Output a textual report at the end of testing class CucumberHtmlReport < Hydra::Listener::Abstract - ## Initialize a new report - #def testing_begin(files) - # @report = { } - #end - # - ## Log the start time of a file - #def file_begin(file) - # @report[file] ||= { } - # @report[file]['start'] = Time.now.to_f - #end - # - ## Log the end time of a file and compute the file's testing - ## duration - #def file_end(file, output) - # @report[file]['end'] = Time.now.to_f - # @report[file]['duration'] = @report[file]['end'] - @report[file]['start'] - #end - # output the report def testing_end CombineHtml.new.generate - - - #@output.close end end class CombineHtml def initialize - @io = File.open('/home/derek/out/report.html', "w") + @results_path = File.join(Dir.pwd, 'results') + @io = File.open(File.join(@results_path, 'report.html'), "w") @builder = create_builder(@io) end def generate - puts "write header" before_features - - puts "combine" - combine_features - - puts "write footer" - - after_features @io.flush @io.close - puts "finished" + + FileUtils.rm_r File.join(@results_path, 'features') + end + + def wait_for_two_seconds_while_files_are_written + sleep 2 end def combine_features - sleep 10 - Dir.glob('/home/derek/out/features/*.html').each do |feature| - puts "Reading #{feature}" + wait_for_two_seconds_while_files_are_written + Dir.glob(File.join(@results_path, 'features/*.html')).each do |feature| File.open( feature, "rb") do |f| f.each_line do |line| - puts line @builder << line end end @@ -68,7 +43,6 @@ module Hydra #:nodoc: end def before_features - # @builder.declare!( :DOCTYPE, @@ -104,7 +78,6 @@ module Hydra #:nodoc: end def after_features - print_stats @builder << '' @builder << '' @builder << '' @@ -165,55 +138,6 @@ module Hydra #:nodoc: EOF end - def move_progress - end - - def percent_done - result = 100.0 - result - end - - def format_exception(exception) - (["#{exception.message}"] + exception.backtrace).join("\n") - end - - def backtrace_line(line) - line.gsub(/\A([^:]*\.(?:rb|feature|haml)):(\d*).*\z/) do - if ENV['TM_PROJECT_DIRECTORY'] - "#{$1}:#{$2} " - else - line - end - end - end - - def print_stats - #@builder << "" - #@builder << "" - end - - def print_stat_string(features) - string = String.new - string << dump_count(@step_mother.scenarios.length, "scenario") - scenario_count = print_status_counts{|status| @step_mother.scenarios(status)} - string << scenario_count if scenario_count - string << "
    " - string << dump_count(@step_mother.steps.length, "step") - step_count = print_status_counts{|status| @step_mother.steps(status)} - string << step_count if step_count - end - - def print_status_counts - counts = [:failed, :skipped, :undefined, :pending, :passed].map do |status| - elements = yield status - elements.any? ? "#{elements.length} #{status.to_s}" : nil - end.compact - return " (#{counts.join(', ')})" if counts.any? - end - - def dump_count(count, what, state=nil) - [count, state, "#{what}#{count == 1 ? '' : 's'}"].compact.join(" ") - end def create_builder(io) Cucumber::Formatter::OrderedXmlMarkup.new(:target => io, :indent => 0) diff --git a/lib/hydra/runner.rb b/lib/hydra/runner.rb index 2621a1a..155f2ad 100644 --- a/lib/hydra/runner.rb +++ b/lib/hydra/runner.rb @@ -170,8 +170,10 @@ module Hydra #:nodoc: cuke_formatter = Cucumber::Formatter::Hydra.new( @cuke_runtime, hydra_response, @cuke_configuration.options ) + results_directory = "#{Dir.pwd}/results/features" + FileUtils.mkdir_p results_directory html_formatter = Hydra::Formatter::PartialHtml.new( - @cuke_runtime, "/home/derek/out/features/#{file.split('/').last}#{Time.now.strftime('%H%M%S')}.html", @cuke_configuration.options + @cuke_runtime, "#{results_directory}/#{file.split('/').last}#{Time.now.strftime('%H%M%S')}.html", @cuke_configuration.options ) cuke_runner ||= Cucumber::Ast::TreeWalker.new(