diff --git a/History.txt b/History.txt index a54442edb75..80cc6b79214 100644 --- a/History.txt +++ b/History.txt @@ -3,6 +3,7 @@ With this release you can package your formatters in RubyGems. === New features +* New --expand option. This will print Scenario Outlines once for each Example row - with values expanded. (Aslak Hellesøy) * New aliases for Vietnamese (Ngoc Dao) * Automatic require of custom formatters. --require is no longer needed to load them, and they can be in Ruby gems. (Aslak Hellesøy) * Lazy loading of built-in formatters. Should improve startup time a little bit. diff --git a/Manifest.txt b/Manifest.txt index e62e8d3fa52..765fb43592a 100644 --- a/Manifest.txt +++ b/Manifest.txt @@ -243,6 +243,7 @@ features/cucumber_cli_diff_disabled.feature features/cucumber_cli_outlines.feature features/custom_formatter.feature features/exclude_files.feature +features/expand.feature features/junit_formatter.feature features/multiline_names.feature features/rake_task.feature diff --git a/features/expand.feature b/features/expand.feature new file mode 100644 index 00000000000..b1164e9fb9b --- /dev/null +++ b/features/expand.feature @@ -0,0 +1,42 @@ +Feature: --expand option + In order to make it easier to writhe certain editor plugins + and also for some people to understand scenarios, Cucumber + should expand examples in outlines. + + Background: + Given a standard Cucumber project directory structure + And a file named "features/expand_me.feature" with: + """ + Feature: submit guess + Scenario Outline: submit guess + Given the secret code is + When I guess + Then the mark should be + + Examples: all colors correct + | code | guess | mark | + | r g y c | r g y c | bbbb | + | r g y c | r g c y | bbww | + """ + + Scenario: Expand the outline + When I run cucumber -i -q --expand features/expand_me.feature + Then the output should contain + """ + Feature: submit guess + + Scenario Outline: submit guess + Given the secret code is + When I guess + Then the mark should be + + Examples: all colors correct + Scenario Outline: submit guess + Given the secret code is r g y c + When I guess r g y c + Then the mark should be bbbb + Scenario Outline: submit guess + Given the secret code is r g y c + When I guess r g c y + Then the mark should be bbww + """ \ No newline at end of file diff --git a/lib/cucumber/ast/outline_table.rb b/lib/cucumber/ast/outline_table.rb index c156cbe11c7..ead3b5f1317 100644 --- a/lib/cucumber/ast/outline_table.rb +++ b/lib/cucumber/ast/outline_table.rb @@ -10,7 +10,11 @@ def initialize(raw, scenario_outline) def accept(visitor) cells_rows.each_with_index do |row, n| - visitor.visit_table_row(row) + if(visitor.options[:expand]) + row.accept(visitor) + else + visitor.visit_table_row(row) + end end nil end @@ -35,6 +39,10 @@ def example_rows cells_rows[1..-1] end + def expand_scenario(visitor, row) + @scenario_outline.expand_name(visitor, row) + end + class ExampleCells < Cells def create_step_invocations!(scenario_outline) @step_invocations = scenario_outline.step_invocations(self) @@ -47,6 +55,10 @@ def skip_invoke! end def accept(visitor) + visitor.options[:expand] ? accept_expand(visitor) : accept_plain(visitor) + end + + def accept_plain(visitor) if header? @cells.each do |cell| cell.status = :skipped_param @@ -66,6 +78,20 @@ def accept(visitor) end end + def accept_expand(visitor) + if header? + else + visitor.step_mother.before_and_after(self) do + @table.expand_scenario(visitor, self) + @step_invocations.each do |step_invocation| + step_invocation.invoke(visitor.step_mother, visitor.options) + @exception ||= step_invocation.exception + step_invocation.visit_step_results(visitor) + end + end + end + end + def accept_hook?(hook) @table.accept_hook?(hook) end diff --git a/lib/cucumber/ast/scenario_outline.rb b/lib/cucumber/ast/scenario_outline.rb index c155e485fe8..b493336826b 100644 --- a/lib/cucumber/ast/scenario_outline.rb +++ b/lib/cucumber/ast/scenario_outline.rb @@ -61,6 +61,10 @@ def each_example_row(&proc) end end + def expand_name(visitor, row) + visitor.visit_scenario_name(@keyword, @name, file_colon_line(row.line), 0) + end + def to_sexp sexp = [:scenario_outline, @keyword, @name] comment = @comment.to_sexp diff --git a/lib/cucumber/ast/step.rb b/lib/cucumber/ast/step.rb index f768f2ef5d0..01c85411d57 100644 --- a/lib/cucumber/ast/step.rb +++ b/lib/cucumber/ast/step.rb @@ -51,7 +51,7 @@ def first_match(visitor) step_match = visitor.step_mother.step_match(name, @name) rescue nil return step_match if step_match end - NoStepMatch.new(self) + NoStepMatch.new(self, @name) end def to_sexp diff --git a/lib/cucumber/ast/step_invocation.rb b/lib/cucumber/ast/step_invocation.rb index 1ab9e9c5426..4572d6a1f98 100644 --- a/lib/cucumber/ast/step_invocation.rb +++ b/lib/cucumber/ast/step_invocation.rb @@ -20,6 +20,10 @@ def skip_invoke! def accept(visitor) invoke(visitor.step_mother, visitor.options) + visit_step_results(visitor) + end + + def visit_step_results(visitor) @step.visit_step_result(visitor, @step_match, @multiline_arg, @status, @exception, @background) end @@ -51,11 +55,11 @@ def find_step_match!(step_mother) rescue Undefined => e failed(e, true) status!(:undefined) - @step_match = NoStepMatch.new(@step) + @step_match = NoStepMatch.new(@step, @name) rescue Ambiguous => e failed(e, false) status!(:failed) - @step_match = NoStepMatch.new(@step) + @step_match = NoStepMatch.new(@step, @name) end step_mother.step_visited(self) end diff --git a/lib/cucumber/cli/configuration.rb b/lib/cucumber/cli/configuration.rb index f47f01387ce..914c006123b 100644 --- a/lib/cucumber/cli/configuration.rb +++ b/lib/cucumber/cli/configuration.rb @@ -149,6 +149,9 @@ def parse!(args) opts.on("-g", "--guess", "Guess best match for Ambiguous steps.") do @options[:guess] = true end + opts.on("-x", "--expand", "Expand Scenario Outline Tables in output.") do + @options[:expand] = true + end opts.on("--no-diff", "Disable diff output on failing expectations.") do @options[:diff_enabled] = false end diff --git a/lib/cucumber/step_match.rb b/lib/cucumber/step_match.rb index 4f6434cd629..8d2ff77d4d7 100644 --- a/lib/cucumber/step_match.rb +++ b/lib/cucumber/step_match.rb @@ -33,12 +33,13 @@ def text_length class NoStepMatch attr_reader :step_definition - def initialize(step) + def initialize(step, name) @step = step + @name = name end def format_args(format) - @step.name + @name end def file_colon_line