lib/allure-cucumber/formatter.rb in allure-cucumber-0.4.4 vs lib/allure-cucumber/formatter.rb in allure-cucumber-0.5.0
- old
+ new
@@ -4,185 +4,200 @@
module AllureCucumber
class Formatter
include AllureCucumber::DSL
+
+ TEST_HOOK_NAMES_TO_IGNORE = ['Before hook', 'After hook']
+ POSSIBLE_STATUSES = ['passed', 'failed', 'pending', 'skipped', 'undefined']
+
def initialize(step_mother, io, options)
dir = Pathname.new(AllureCucumber::Config.output_dir)
FileUtils.rm_rf(dir)
+ FileUtils.mkdir_p(dir)
@tracker = AllureCucumber::FeatureTracker.create
+ @deferred_before_test_steps = []
+ @deferred_after_test_steps = []
end
+ # Start the test suite
def before_feature(feature)
- @has_background = false
feature_identifier = ENV['FEATURE_IDENTIFIER'] && "#{ENV['FEATURE_IDENTIFIER']} - "
@tracker.feature_name = "#{feature_identifier}#{feature.name.gsub(/\n/, " ")}"
- AllureRubyAdaptorApi::Builder.start_suite(@tracker.feature_name, :severity => :normal)
+ AllureRubyAdaptorApi::Builder.start_suite(@tracker.feature_name)
end
- def before_background(*args)
- @in_background = true
- @has_background = true
- @background_before_steps = []
- @background_after_steps = []
+ # Find sceanrio type
+ def before_feature_element(feature_element)
+ @scenario_outline = feature_element.instance_of?(Cucumber::Core::Ast::ScenarioOutline)
end
-
- def after_background(*args)
- @in_background = false
+
+ def scenario_name(keyword, name, *args)
+ scenario_name = (name.nil? || name == "") ? "Unnamed scenario" : name.gsub(/\n/, " ")
+ @scenario_outline ? @scenario_outline_name = scenario_name : @tracker.scenario_name = scenario_name
end
- def before_feature_element(feature_element)
- @scenario_outline = feature_element.instance_of?(Cucumber::Ast::ScenarioOutline)
+ def before_examples(*args)
+ @header_row = true
+ @row_count = 0
end
-
- def scenario_name(keyword, name, file_colon_line, source_indent)
- unless @scenario_outline
- @tracker.scenario_name = (name.nil? || name == "") ? "Unnamed scenario" : name.gsub(/\n/, " ")
- AllureRubyAdaptorApi::Builder.start_test(@tracker.feature_name, @tracker.scenario_name, :feature => @tracker.feature_name, :story => @tracker.scenario_name)
- @tracker.scenario_started_at = Time.now
- post_background_steps if @has_background
- else
- @scenario_outline_name = (name.nil? || name == "") ? "Unnamed scenario" : name.gsub(/\n/, " ")
- end
- end
+ # Start the test for normal scenarios
def before_steps(steps)
- @example_before_steps = []
- @example_after_steps = []
- @exception = nil
- end
-
- def before_step(step)
- unless step.background?
- unless @scenario_outline
- @tracker.step_name = step.name
- AllureRubyAdaptorApi::Builder.start_step(@tracker.feature_name, @tracker.scenario_name, @tracker.step_name)
- attach_multiline_arg(step.multiline_arg)
- else
- @example_before_steps << step
- end
- else
- @background_before_steps << step
+ if !@scenario_outline
+ start_test
end
end
-
- def after_step(step)
- unless step.background?
- unless @scenario_outline
- AllureRubyAdaptorApi::Builder.stop_step(@tracker.feature_name, @tracker.scenario_name, @tracker.step_name, step.status.to_sym)
- else
- @example_after_steps << step
- end
- else
- @background_after_steps << step
+
+ # Stop the test for normal scenarios
+ def after_steps(steps)
+ if !@scenario_outline
+ result = test_result(steps)
+ stop_test(result)
end
end
- def after_steps(steps)
- return if @in_background || @scenario_outline
- result = { :status => steps.status, :exception => steps.exception, :started_at => @tracker.scenario_started_at, :finished_at => Time.now }
- AllureRubyAdaptorApi::Builder.stop_test(@tracker.feature_name, @tracker.scenario_name, result)
+ # Start the test for scenario examples
+ def before_table_row(table_row)
+ if @scenario_outline && !@header_row && !@in_multiline_arg
+ @row_count += 1
+ @tracker.scenario_name = "Example #{@row_count} : #{@scenario_outline_name}"
+ start_test
+ end
end
- def before_examples(*args)
- @header_row = true
- @in_examples = true
- end
-
- def before_examples(*args)
- @header_row = true
- @in_examples = true
- end
-
- def before_outline_table(outline_table)
- headers = outline_table.headers
- rows = outline_table.rows
- @current_row = -1
- @table = []
- rows.each do |element|
- row_hash = {}
- element.each_with_index do |item, index|
- row_hash[headers[index]] = item
+ # Stop the test for scenario examples
+ def after_table_row(table_row)
+ unless @multiline_arg
+ if @scenario_outline && !@header_row
+ result = test_result(table_row)
+ stop_test(result)
end
- @table << row_hash
+ @header_row = false
end
end
- def before_table_row(table_row)
- return unless @in_examples
- unless @header_row
- @scenario_status = :passed
- @exception = nil
- @tracker.scenario_name = "#{@scenario_outline_name} Example: #{table_row.name}"
- AllureRubyAdaptorApi::Builder.start_test(@tracker.feature_name, @tracker.scenario_name, :feature => @tracker.feature_name, :story => @tracker.scenario_name)
- @tracker.scenario_started_at = Time.now
- post_background_steps if @has_background
- @current_row += 1
- @example_before_steps.each do |step|
- @tracker.step_name = transform_step_name_for_outline(step.name, @current_row)
- AllureRubyAdaptorApi::Builder.start_step(@tracker.feature_name, @tracker.scenario_name, @tracker.step_name)
- attach_multiline_arg(step.multiline_arg)
- end
+ def before_test_step(test_step)
+ if !TEST_HOOK_NAMES_TO_IGNORE.include?(test_step.name)
+ if @tracker.scenario_name
+ @tracker.step_name = test_step.name
+ start_step
+ else
+ @deferred_before_test_steps << {:step => test_step, :timestamp => Time.now}
+ end
end
end
- def after_table_row(table_row)
- return unless @in_examples or Cucumber::Ast::OutlineTable::ExampleRow === table_row
- unless @header_row
- @example_after_steps.each do |step|
- @tracker.step_name = transform_step_name_for_outline(step.name, @current_row)
- if table_row.status == :failed
- @exception = table_row.exception
- @scenario_status = :failed
- end
- AllureRubyAdaptorApi::Builder.stop_step(@tracker.feature_name, @tracker.scenario_name, @tracker.step_name, step.status.to_sym)
+ def after_test_step(test_step, result)
+ if !TEST_HOOK_NAMES_TO_IGNORE.include?(test_step.name)
+ if @tracker.scenario_name
+ status = step_status(result)
+ stop_step(status)
+ else
+ @deferred_after_test_steps << {:step => test_step, :result => result, :timestamp => Time.now}
end
- AllureRubyAdaptorApi::Builder.stop_test(@tracker.feature_name, @tracker.scenario_name, {:status => @scenario_status, :exception => @exception, :started_at => @tracker.scenario_started_at, :finished_at => Time.now })
end
- @header_row = false if @header_row
end
- def after_outline_table(*args)
- @in_examples = false
- end
-
+ # Stop the suite
def after_feature(feature)
AllureRubyAdaptorApi::Builder.stop_suite(@tracker.feature_name)
end
def after_features(features)
AllureRubyAdaptorApi::Builder.build!
end
+ def before_multiline_arg(multiline_arg)
+ @in_multiline_arg = true
+ # For background steps defer multiline attachment
+ if @tracker.scenario_name.nil?
+ @deferred_before_test_steps[-1].merge!({:multiline_arg => multiline_arg})
+ else
+ attach_multiline_arg_to_file(multiline_arg)
+ end
+ end
+
+ def after_multiline_arg(multiline_arg)
+ @in_multiline_arg = false
+ end
+
private
+
+ def step_status(result)
+ POSSIBLE_STATUSES.each do |status|
+ return cucumber_status_to_allure_status(status) if result.send("#{status}?")
+ end
+ end
- def transform_step_name_for_outline(step_name, row_num)
- transformed_name = ''
- @table[row_num].each do |k, v|
- transformed_name == '' ? transformed_name = step_name.gsub(k, v) : transformed_name = transformed_name.gsub(k,v)
+ def test_result(result)
+ status = cucumber_status_to_allure_status(result.status)
+ exception = status == 'failed' && result.exception.nil? ? Exception.new("Some steps were undefined") : result.exception
+ if exception
+ return {:status => status, :exception => exception}
+ else
+ return {:status => status}
end
- transformed_name
end
+
+ def cucumber_status_to_allure_status(status)
+ case status.to_s
+ when "undefined"
+ return "failed"
+ when "skipped"
+ return "pending"
+ else
+ return status.to_s
+ end
+ end
+
+ def attach_multiline_arg_to_file(multiline_arg)
+ dir = File.expand_path(AllureCucumber::Config.output_dir)
+ out_file = "#{dir}/#{UUID.new.generate}.txt"
+ File.open(out_file, "w+") { |file| file.write(multiline_arg.to_s.gsub(/\e\[(\d+)(;\d+)*m/,'')) }
+ attach_file("multiline_arg", File.open(out_file))
+ end
- def attach_multiline_arg(multiline_arg)
- if multiline_arg
- File.open('tmp_file.txt', 'w'){ |file| file.write(multiline_arg.to_s.gsub(/\e\[(\d+)(;\d+)*m/,'')) }
- attach_file("table", File.open('tmp_file.txt'))
+ def start_test
+ if @tracker.scenario_name
+ AllureRubyAdaptorApi::Builder.start_test(@tracker.feature_name, @tracker.scenario_name, :feature => @tracker.feature_name, :story => @tracker.scenario_name)
+ post_deferred_steps
end
end
- def post_background_steps
- @background_before_steps.each do |step|
- @tracker.step_name = "Background : #{step.name}"
- AllureRubyAdaptorApi::Builder.start_step(@tracker.feature_name, @tracker.scenario_name, @tracker.step_name)
- attach_multiline_arg(step.multiline_arg)
+ def post_deferred_steps
+ @deferred_before_test_steps.size.times do |index|
+ @tracker.step_name = @deferred_before_test_steps[index][:step].name
+ start_step
+ multiline_arg = @deferred_before_test_steps[index][:multiline_arg]
+ attach_multiline_arg_to_file(multiline_arg) if multiline_arg
+ if index < @deferred_after_test_steps.size
+ result = step_status(@deferred_after_test_steps[index][:result])
+ stop_step(result)
+ end
end
- @background_before_steps.each do |step|
- @tracker.step_name = "Background : #{step.name}"
- AllureRubyAdaptorApi::Builder.stop_step(@tracker.feature_name, @tracker.scenario_name, @tracker.step_name, step.status.to_sym)
- attach_multiline_arg(step.multiline_arg)
- end
end
+ def stop_test(result)
+ if @deferred_before_test_steps != []
+ result[:started_at] = @deferred_before_test_steps[0][:timestamp]
+ end
+ if @tracker.scenario_name
+ AllureRubyAdaptorApi::Builder.stop_test(@tracker.feature_name, @tracker.scenario_name, result)
+ @tracker.scenario_name = nil
+ @deferred_before_test_steps = []
+ @deferred_after_test_steps = []
+ end
+ end
+
+ def start_step(step_name = @tracker.step_name)
+ AllureRubyAdaptorApi::Builder.start_step(@tracker.feature_name, @tracker.scenario_name, step_name)
+ end
+
+ def stop_step(status, step_name = @tracker.step_name)
+ AllureRubyAdaptorApi::Builder.stop_step(@tracker.feature_name, @tracker.scenario_name, step_name, status)
+ end
+
end
end
+