Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle output from hooks appropriately #732

Merged
merged 2 commits into from
Sep 11, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions features/docs/formatters/json_formatter.feature
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,17 @@ Feature: JSON output formatter
Given I embed data directly

"""
And a file named "features/out_scenario_out_scenario_outline.feature" with:
"""
Feature:
Scenario:
Given this step passes
Scenario Outline:
Given this step <status>
Examples:
| status |
| passes |
"""

# Need to investigate why this won't pass in-process. error_message doesn't get det?
@spawn
Expand Down Expand Up @@ -647,3 +658,39 @@ Feature: JSON output formatter
]

"""
@spawn
Scenario: handle output from hooks
Given a file named "features/step_definitions/output_steps.rb" with:
"""
Before do
puts "Before hook 1"
embed "src", "mime_type", "label"
end

Before do
puts "Before hook 2"
embed "src", "mime_type", "label"
end

AfterStep do
puts "AfterStep hook 1"
embed "src", "mime_type", "label"
end

AfterStep do
puts "AfterStep hook 2"
embed "src", "mime_type", "label"
end

After do
puts "After hook 1"
embed "src", "mime_type", "label"
end

After do
puts "After hook 2"
embed "src", "mime_type", "label"
end
"""
When I run `cucumber --format json features/out_scenario_out_scenario_outline.feature`
Then it should pass
128 changes: 128 additions & 0 deletions features/docs/output_from_hooks.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
Feature: Hook output feature

Calls to puts and embed in hook, should be passed to the formatters.

Background:
Given the standard step definitions

Scenario: Output from hooks
Given a file named "features/test.feature" with:
"""
Feature:
Scenario:
Given this step passes
Scenario Outline:
Given this step <status>
Examples:
| status |
| passes |
"""
And a file named "features/step_definitions/output_steps.rb" with:
"""
Before do
puts "Before hook 1"
embed "src", "mime_type", "label"
end

Before do
puts "Before hook 2"
embed "src", "mime_type", "label"
end

AfterStep do
puts "AfterStep hook 1"
embed "src", "mime_type", "label"
end

AfterStep do
puts "AfterStep hook 2"
embed "src", "mime_type", "label"
end

After do
puts "After hook 1"
embed "src", "mime_type", "label"
end

After do
puts "After hook 2"
embed "src", "mime_type", "label"
end
"""
When I run `cucumber -f debug`
Then the stderr should not contain anything
Then it should pass with:
"""
before_features
before_feature
before_tags
after_tags
feature_name
before_feature_element
before_tags
after_tags
scenario_name
puts
embed
puts
embed
before_steps
before_step
before_step_result
step_name
after_step_result
after_step
puts
embed
puts
embed
after_steps
puts
embed
puts
embed
after_feature_element
before_feature_element
before_tags
after_tags
scenario_name
before_steps
before_step
before_step_result
step_name
after_step_result
after_step
after_steps
before_examples_array
before_examples
examples_name
before_outline_table
before_table_row
before_table_cell
table_cell_value
after_table_cell
after_table_row
puts
embed
puts
embed
before_table_row
before_table_cell
table_cell_value
after_table_cell
after_table_row
puts
embed
puts
embed
puts
embed
puts
embed
after_outline_table
after_examples
after_examples_array
after_feature_element
after_feature
after_features
"""
4 changes: 4 additions & 0 deletions lib/cucumber/formatter/debug.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ def method_missing(name, *args)
@indent += 2 if name.to_s =~ /^before/
end

def puts(*args)
print("puts")
end

private

def print(text)
Expand Down
27 changes: 25 additions & 2 deletions lib/cucumber/formatter/gherkin_formatter_adapter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ def initialize(gherkin_formatter, print_empty_match, options)
@gf = gherkin_formatter
@print_empty_match = print_empty_match
@options = options
@delayed_messages = []
@delayed_embeddings = []
end

def before_feature(feature)
Expand All @@ -19,10 +21,12 @@ def before_feature(feature)

def before_background(background)
@outline = false
@before_steps = true
@gf.background(background.gherkin_statement)
end

def before_feature_element(feature_element)
@before_steps = true
case(feature_element)
when Core::Ast::Scenario
@outline = false
Expand Down Expand Up @@ -65,6 +69,8 @@ def scenario_name(keyword, name, file_colon_line, source_indent)
def before_step(step)
unless @outline and @options[:expand]
@gf.step(step.gherkin_statement)
pass_delayed_output
@before_steps = false
else
if @in_instantiated_scenario
@current_step_hash = to_hash(step.gherkin_statement)
Expand Down Expand Up @@ -114,6 +120,8 @@ def step_name(keyword, step_match, status, source_indent, background, file_colon
@current_step_hash['line'],
@current_step_hash['rows'],
@current_step_hash['doc_string']))
pass_delayed_output
@before_steps = false
@gf.match(@current_match)
@gf.result(@current_result)
end
Expand Down Expand Up @@ -159,11 +167,19 @@ def embed(file, mime_type, label)
if defined?(JRUBY_VERSION)
data = data.to_java_bytes
end
@gf.embedding(mime_type, data)
unless @before_steps
@gf.embedding(mime_type, data)
else
@delayed_embeddings.push [mime_type, data]
end
end

def puts(message)
@gf.write(message)
unless @before_steps
@gf.write(message)
else
@delayed_messages.push message
end
end

private
Expand All @@ -175,6 +191,13 @@ def to_hash(gherkin_statement)
gherkin_statement.to_hash
end
end

def pass_delayed_output
@delayed_messages.each { |message| @gf.write(message) }
@delayed_embeddings.each { |embed_data| @gf.embedding(embed_data[0], embed_data[1]) }
@delayed_messages = []
@delayed_embeddings = []
end
end
end
end
41 changes: 28 additions & 13 deletions lib/cucumber/reports/legacy_formatter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -220,29 +220,41 @@ def after_test_step(test_step, result)
def after_test_case(*args)
if current_test_step_source.step_result.nil?
switch_step_container
@delayed_messages = []
@delayed_embeddings = []
end

# messages and embedding should already have been handled, but just in case...
@delayed_messages.each { |message| formatter.puts(message) }
@delayed_embeddings.each { |embedding| embedding.send_to_formatter(formatter) }
@delayed_messages = []
@delayed_embeddings = []

@child.after_test_case
@previous_test_case_background = @current_test_case_background
@previous_test_case_scenario_outline = current_test_step_source.scenario_outline
end

def before_hook(location, result)
@before_hook_results << Legacy::Ast::HookResult.new(LegacyResultBuilder.new(result))
@before_hook_results << Legacy::Ast::HookResult.new(LegacyResultBuilder.new(result), @delayed_messages, @delayed_embeddings)
@delayed_messages = []
@delayed_embeddings = []
end

def after_hook(location, result)
# if the scenario has no steps, we can hit this before we've created the scenario printer
# ideally we should call switch_step_container in before_step_step
switch_step_container if !@child
@child.after_hook Legacy::Ast::HookResult.new(LegacyResultBuilder.new(result))
@child.after_hook Legacy::Ast::HookResult.new(LegacyResultBuilder.new(result), @delayed_messages, @delayed_embeddings)
@delayed_messages = []
@delayed_embeddings = []
end

def after_step_hook(hook, result)
line = StepBacktraceLine.new(current_test_step_source.step)
@child.after_step_hook LegacyResultBuilder.new(result).
append_to_exception_backtrace(line)
@child.after_step_hook Legacy::Ast::HookResult.new(LegacyResultBuilder.new(result).
append_to_exception_backtrace(line), @delayed_messages, @delayed_embeddings)
@delayed_messages = []
@delayed_embeddings = []

end

def background(node, *)
Expand Down Expand Up @@ -417,7 +429,7 @@ def before
end

def after_step_hook(result)
result.describe_exception_to formatter
result.accept formatter
end

def step_invocation(step_invocation, source)
Expand Down Expand Up @@ -485,7 +497,7 @@ def step_invocation(step_invocation, source)
end

def after_step_hook(result)
result.describe_exception_to formatter
result.accept formatter
end

def after_test_case(*args)
Expand Down Expand Up @@ -726,7 +738,8 @@ class TableRowPrinterBase < Struct.new(:formatter, :node, :before_hook_results)
include PrintsAfterHooks

def after_step_hook(result)
@after_step_hook_result = result
@after_step_hook_result ||= []
@after_step_hook_result.push result
end

def after_test_case(*args)
Expand Down Expand Up @@ -791,7 +804,7 @@ def after
formatter.after_table_cell(value)
end
formatter.after_table_row(legacy_table_row)
@after_step_hook_result.describe_exception_to formatter if @after_step_hook_result
@after_step_hook_result.each { |result| result.accept formatter } if @after_step_hook_result
after_hook_results.accept(formatter)
@done = true
self
Expand Down Expand Up @@ -826,7 +839,7 @@ def step_invocation(step_invocation, source)
def after
return if @done
@child.after if @child
@after_step_hook_result.describe_exception_to formatter if @after_step_hook_result
@after_step_hook_result.each { |result| result.accept formatter } if @after_step_hook_result
after_hook_results.accept(formatter)
@done = true
self
Expand Down Expand Up @@ -1057,13 +1070,15 @@ def accept(formatter)
end

class HookResult
def initialize(result)
@result = result
def initialize(result, messages, embeddings)
@result, @messages, @embeddings = result, messages, embeddings
@already_accepted = false
end

def accept(formatter)
unless @already_accepted
@messages.each { |message| formatter.puts(message) }
@embeddings.each { |embedding| embedding.send_to_formatter(formatter) }
@result.describe_exception_to(formatter)
@already_accepted = true
end
Expand Down