From 70db320df80e6327955d6581aa9622b250894e96 Mon Sep 17 00:00:00 2001 From: Matt Wynne Date: Fri, 22 Apr 2016 23:24:55 +0100 Subject: [PATCH 1/9] Integrate new core events --- cucumber.gemspec | 2 +- features/docs/api/listen_for_events.feature | 13 +- .../custom_formatter.feature | 32 +---- lib/cucumber/cli/configuration.rb | 1 + lib/cucumber/configuration.rb | 20 +-- lib/cucumber/events/after_test_case.rb | 25 ---- lib/cucumber/events/after_test_step.rb | 30 ---- lib/cucumber/events/before_test_case.rb | 18 --- lib/cucumber/events/before_test_step.rb | 23 --- lib/cucumber/events/bus.rb | 86 ----------- lib/cucumber/events/step_match.rb | 4 +- ...nished_testing.rb => test_run_finished.rb} | 5 +- lib/cucumber/filters/activate_steps.rb | 2 +- lib/cucumber/formatter/event_bus_report.rb | 38 ----- lib/cucumber/formatter/fail_fast.rb | 4 +- lib/cucumber/formatter/json.rb | 27 ++-- lib/cucumber/formatter/junit.rb | 22 ++- lib/cucumber/formatter/legacy_api/adapter.rb | 58 ++++---- lib/cucumber/formatter/rerun.rb | 31 ++-- lib/cucumber/formatter/usage.rb | 4 +- lib/cucumber/runtime.rb | 12 +- spec/cucumber/events/bus_spec.rb | 94 ------------- spec/cucumber/filters/activate_steps_spec.rb | 14 +- .../formatter/event_bus_report_spec.rb | 88 ------------ spec/cucumber/formatter/fail_fast_spec.rb | 9 +- .../formatter/legacy_api/adapter_spec.rb | 10 +- spec/cucumber/formatter/rerun_spec.rb | 133 +++++++++--------- spec/cucumber/formatter/spec_helper.rb | 14 +- 28 files changed, 192 insertions(+), 627 deletions(-) delete mode 100644 lib/cucumber/events/after_test_case.rb delete mode 100644 lib/cucumber/events/after_test_step.rb delete mode 100644 lib/cucumber/events/before_test_case.rb delete mode 100644 lib/cucumber/events/before_test_step.rb delete mode 100644 lib/cucumber/events/bus.rb rename lib/cucumber/events/{finished_testing.rb => test_run_finished.rb} (57%) delete mode 100644 lib/cucumber/formatter/event_bus_report.rb delete mode 100644 spec/cucumber/events/bus_spec.rb delete mode 100644 spec/cucumber/formatter/event_bus_report_spec.rb diff --git a/cucumber.gemspec b/cucumber.gemspec index a55095062e..b74dd41da9 100644 --- a/cucumber.gemspec +++ b/cucumber.gemspec @@ -10,7 +10,7 @@ Gem::Specification.new do |s| s.homepage = "http://cukes.info" s.platform = Gem::Platform::RUBY s.required_ruby_version = ">= 1.9.3" - s.add_dependency 'cucumber-core', '~> 1.4.0' + s.add_dependency 'cucumber-core', '~> 3.0' s.add_dependency 'builder', '>= 2.1.2' s.add_dependency 'diff-lcs', '>= 1.1.3' s.add_dependency 'gherkin', '~> 4.0' diff --git a/features/docs/api/listen_for_events.feature b/features/docs/api/listen_for_events.feature index c65683d40c..65d9b38d37 100644 --- a/features/docs/api/listen_for_events.feature +++ b/features/docs/api/listen_for_events.feature @@ -1,5 +1,8 @@ Feature: Listen for events + Cucumber's `config` object has an event bus that you can use to listen for + various events that happen during your test run. + Scenario: Step Matched Event Given a file named "features/test.feature" with: """ @@ -16,11 +19,10 @@ Feature: Listen for events """ AfterConfiguration do |config| io = config.out_stream - config.on_event Cucumber::Events::StepMatch do |event| + config.on_event Cucumber::Events::StepMatch do |test_step, step_match| io.puts "Success!" - io.puts "Event type: #{event.class}" - io.puts "Step name: #{event.test_step.name}" - io.puts "Source location: #{event.step_match.location}" + io.puts "Step name: #{test_step.name}" + io.puts "Source location: #{step_match.location}" end end """ @@ -28,7 +30,6 @@ Feature: Listen for events Then it should pass with: """ Success! - Event type: Cucumber::Events::StepMatch Step name: matching Source location: features/step_definitions/steps.rb:1 """ @@ -45,7 +46,7 @@ Feature: Listen for events """ AfterConfiguration do |config| io = config.out_stream - config.on_event Cucumber::Events::AfterTestStep do |event| + config.on_event Cucumber::Core::Events::TestStepFinished do |test_step, result| io.puts "YO" end end diff --git a/features/docs/extending_cucumber/custom_formatter.feature b/features/docs/extending_cucumber/custom_formatter.feature index 6f05de2c6a..cdfcb63203 100644 --- a/features/docs/extending_cucumber/custom_formatter.feature +++ b/features/docs/extending_cucumber/custom_formatter.feature @@ -19,8 +19,8 @@ Feature: Custom Formatter class Formatter def initialize(config) @io = config.out_stream - config.on_event Cucumber::Events::BeforeTestCase do |event| - print_test_case_name(event.test_case) + config.on_event :test_case_starting do |test_case| + print_test_case_name(test_case) end end @@ -41,34 +41,6 @@ Feature: Custom Formatter """ - Scenario: Implement v2.0 formatter methods - Note that this method is likely to be deprecated in favour of events - see above. - - Given a file named "features/support/custom_formatter.rb" with: - """ - module MyCustom - class Formatter - def initialize(config) - @io = config.out_stream - end - - def before_test_case(test_case) - feature = test_case.source.first - scenario = test_case.source.last - @io.puts feature.short_name.upcase - @io.puts " #{scenario.name.upcase}" - end - end - end - """ - When I run `cucumber features/f.feature --format MyCustom::Formatter` - Then it should pass with exactly: - """ - I'LL USE MY OWN - JUST PRINT ME - - """ - Scenario: Use the legacy API This is deprecated and should no longer be used. diff --git a/lib/cucumber/cli/configuration.rb b/lib/cucumber/cli/configuration.rb index cbd793529c..11b7f657d7 100644 --- a/lib/cucumber/cli/configuration.rb +++ b/lib/cucumber/cli/configuration.rb @@ -3,6 +3,7 @@ require 'cucumber/cli/rerun_file' require 'cucumber/constantize' require 'cucumber/core/gherkin/tag_expression' +require 'cucumber' module Cucumber module Cli diff --git a/lib/cucumber/configuration.rb b/lib/cucumber/configuration.rb index 5ffdd5e556..6b84edcd05 100644 --- a/lib/cucumber/configuration.rb +++ b/lib/cucumber/configuration.rb @@ -3,6 +3,7 @@ require 'cucumber/events' require 'forwardable' require 'cucumber/core/gherkin/tag_expression' +require 'cucumber' module Cucumber # The base class for configuring settings for a Cucumber run. @@ -20,12 +21,14 @@ def self.default # # @param event_id [Symbol, Class, String] Identifier for the type of event to subscribe to # @param handler_object [Object optional] an object to be called when the event occurs - # @yield [Object] Block to be called when th event occurs + # @yield [Object] Block to be called when the event occurs # @method on_event - def_instance_delegator :event_bus, :register, :on_event + def_instance_delegator :event_bus, :on, :on_event # @private - def_instance_delegator :event_bus, :notify + def notify(message, *args) + event_bus.send(message, *args) + end def initialize(user_options = {}) @options = default_options.merge(Cucumber::Hash(user_options)) @@ -216,6 +219,10 @@ def register_snippet_generator(generator) self end + def event_bus + @options[:event_bus] + end + private def default_options @@ -235,15 +242,10 @@ def default_options :snippets => true, :source => true, :duration => true, - :event_bus => Events::Bus.new(Cucumber::Events) + :event_bus => Core::Events::Bus.new(Cucumber::Events) } end - def event_bus - @options[:event_bus] - end - - def default_features_paths ["features"] end diff --git a/lib/cucumber/events/after_test_case.rb b/lib/cucumber/events/after_test_case.rb deleted file mode 100644 index b1ec8e6380..0000000000 --- a/lib/cucumber/events/after_test_case.rb +++ /dev/null @@ -1,25 +0,0 @@ -module Cucumber - module Events - - # Event fired after a test case has finished executing - class AfterTestCase - - # The test case that was just executed. - # - # @return [Cucumber::Core::Test::Case] - attr_reader :test_case - - # The result of executing the test case. - # - # @return [Cucumber::Core::Test::Result] - attr_reader :result - - # @private - def initialize(test_case, result) - @test_case, @result = test_case, result - end - - end - - end -end diff --git a/lib/cucumber/events/after_test_step.rb b/lib/cucumber/events/after_test_step.rb deleted file mode 100644 index 3d3af2c334..0000000000 --- a/lib/cucumber/events/after_test_step.rb +++ /dev/null @@ -1,30 +0,0 @@ -module Cucumber - module Events - - # Event fired after each test step has been executed - class AfterTestStep - - # The test case currently being executed. - # - # @return [Cucumber::Core::Test::Case] - attr_reader :test_case - - # The test step that was just executed. - # - # @return [Cucumber::Core::Test::Step] - attr_reader :test_step - - # The result of executing the test step. - # - # @return [Cucumber::Core::Test::Result] - attr_reader :result - - # @private - def initialize(test_case, test_step, result) - @test_case, @test_step, @result = test_case, test_step, result - end - - end - - end -end diff --git a/lib/cucumber/events/before_test_case.rb b/lib/cucumber/events/before_test_case.rb deleted file mode 100644 index e59168fa41..0000000000 --- a/lib/cucumber/events/before_test_case.rb +++ /dev/null @@ -1,18 +0,0 @@ -module Cucumber - module Events - - # Event fired before a test case is executed - class BeforeTestCase - - # The test case about to be executed. - # - # @return [Cucumber::Core::Test::Case] - attr_reader :test_case - - # @private - def initialize(test_case) - @test_case = test_case - end - end - end -end diff --git a/lib/cucumber/events/before_test_step.rb b/lib/cucumber/events/before_test_step.rb deleted file mode 100644 index 395f398849..0000000000 --- a/lib/cucumber/events/before_test_step.rb +++ /dev/null @@ -1,23 +0,0 @@ -module Cucumber - module Events - - # Event fired before a test step is executed - class BeforeTestStep - - # The test case currently being executed. - # - # @return [Cucumber::Core::Test::Case] - attr_reader :test_case - - # The test step about to be executed. - # - # @return [Cucumber::Core::Test::Step] - attr_reader :test_step - - # @private - def initialize(test_case, test_step) - @test_case, @test_step = test_case, test_step - end - end - end -end diff --git a/lib/cucumber/events/bus.rb b/lib/cucumber/events/bus.rb deleted file mode 100644 index 3f9abca670..0000000000 --- a/lib/cucumber/events/bus.rb +++ /dev/null @@ -1,86 +0,0 @@ -module Cucumber - module Events - - # Event bus - # - # Implements and in-process pub-sub events broadcaster allowing multiple observers - # to subscribe to different events that fire as your tests are executed. - # - # @private - class Bus - - def initialize(default_namespace) - @default_namespace = default_namespace.to_s - @handlers = {} - end - - # Register for an event - def register(event_id, handler_object = nil, &handler_proc) - handler = handler_proc || handler_object - raise ArgumentError.new("Please pass either an object or a handler block") unless handler - event_class = parse_event_id(event_id) - handlers_for(event_class) << handler - end - - # Broadcast an event - def notify(event) - handlers_for(event.class).each { |handler| handler.call(event) } - end - - private - - def handlers_for(event_class) - @handlers[event_class.to_s] ||= [] - end - - def parse_event_id(event_id) - case event_id - when Class - return event_id - when String - constantize(event_id) - else - constantize("#{@default_namespace}::#{camel_case(event_id)}") - end - end - - def camel_case(underscored_name) - underscored_name.to_s.split("_").map { |word| word.upcase[0] + word[1..-1] }.join - end - - # Thanks ActiveSupport - # (Only needed to support Ruby 1.9.3 and JRuby) - def constantize(camel_cased_word) - names = camel_cased_word.split('::') - - # Trigger a built-in NameError exception including the ill-formed constant in the message. - Object.const_get(camel_cased_word) if names.empty? - - # Remove the first blank element in case of '::ClassName' notation. - names.shift if names.size > 1 && names.first.empty? - - names.inject(Object) do |constant, name| - if constant == Object - constant.const_get(name) - else - candidate = constant.const_get(name) - next candidate if constant.const_defined?(name, false) - next candidate unless Object.const_defined?(name) - - # Go down the ancestors to check if it is owned directly. The check - # stops when we reach Object or the end of ancestors tree. - constant = constant.ancestors.inject do |const, ancestor| - break const if ancestor == Object - break ancestor if ancestor.const_defined?(name, false) - const - end - - # owner is in Object, so raise - constant.const_get(name, false) - end - end - end - - end - end -end diff --git a/lib/cucumber/events/step_match.rb b/lib/cucumber/events/step_match.rb index f82ab3ba79..9cb6cd113d 100644 --- a/lib/cucumber/events/step_match.rb +++ b/lib/cucumber/events/step_match.rb @@ -1,8 +1,10 @@ +require 'cucumber/core/events' + module Cucumber module Events # Event fired when a step is matched to a definition - class StepMatch + class StepMatch < Core::Event.new(:test_step, :step_match) # The test step that was matched. # diff --git a/lib/cucumber/events/finished_testing.rb b/lib/cucumber/events/test_run_finished.rb similarity index 57% rename from lib/cucumber/events/finished_testing.rb rename to lib/cucumber/events/test_run_finished.rb index ebe8ffb012..654c1f853e 100644 --- a/lib/cucumber/events/finished_testing.rb +++ b/lib/cucumber/events/test_run_finished.rb @@ -1,9 +1,10 @@ +require 'cucumber/core/events' + module Cucumber module Events # Event fired after aall test cases have finished executing - class FinishedTesting - end + TestRunFinished = Class.new(Core::Event.new) end end diff --git a/lib/cucumber/filters/activate_steps.rb b/lib/cucumber/filters/activate_steps.rb index 38a8194cae..d4fbcc2d05 100644 --- a/lib/cucumber/filters/activate_steps.rb +++ b/lib/cucumber/filters/activate_steps.rb @@ -43,7 +43,7 @@ def initialize(step_match_search, configuration, test_step) def result return NoStepMatch.new(test_step.source.last, test_step.name) unless matches.any? - configuration.notify Events::StepMatch.new(test_step, match) + configuration.notify :step_match, test_step, match return SkippingStepMatch.new if configuration.dry_run? match end diff --git a/lib/cucumber/formatter/event_bus_report.rb b/lib/cucumber/formatter/event_bus_report.rb deleted file mode 100644 index c2a5b40a4d..0000000000 --- a/lib/cucumber/formatter/event_bus_report.rb +++ /dev/null @@ -1,38 +0,0 @@ -module Cucumber - module Formatter - - # Adapter between Cucumber::Core::Test::Runner's Report API and - # Cucumber's event bus - class EventBusReport - attr_reader :config - private :config - - def initialize(config) - @config = config - end - - def before_test_case(test_case) - @config.notify Events::BeforeTestCase.new(test_case) - @test_case = test_case - end - - def before_test_step(test_step) - @config.notify Events::BeforeTestStep.new(@test_case, test_step) - end - - def after_test_step(test_step, result) - @config.notify Events::AfterTestStep.new(@test_case, test_step, result) - end - - def after_test_case(test_case, result) - @config.notify Events::AfterTestCase.new(test_case, result) - end - - def done - @config.notify Events::FinishedTesting.new - end - end - - end -end - diff --git a/lib/cucumber/formatter/fail_fast.rb b/lib/cucumber/formatter/fail_fast.rb index 2c36f29e8b..294be9e54f 100644 --- a/lib/cucumber/formatter/fail_fast.rb +++ b/lib/cucumber/formatter/fail_fast.rb @@ -7,8 +7,8 @@ module Formatter class FailFast def initialize(configuration) - configuration.on_event :after_test_case do |event| - Cucumber.wants_to_quit = true unless event.result.ok?(configuration.strict?) + configuration.on_event :test_case_finished do |test_case, result| + Cucumber.wants_to_quit = true unless result.ok?(configuration.strict?) end end diff --git a/lib/cucumber/formatter/json.rb b/lib/cucumber/formatter/json.rb index 45f29b029c..0ff2c886e7 100644 --- a/lib/cucumber/formatter/json.rb +++ b/lib/cucumber/formatter/json.rb @@ -11,17 +11,16 @@ class Json include Io def initialize(config) - config.on_event :before_test_case, &method(:on_before_test_case) - config.on_event :after_test_case, &method(:on_after_test_case) - config.on_event :before_test_step, &method(:on_before_test_step) - config.on_event :after_test_step, &method(:on_after_test_step) - config.on_event :finished_testing, &method(:on_finished_testing) @io = ensure_io(config.out_stream) @feature_hashes = [] + config.on_event :test_case_starting, &method(:on_before_test_case) + config.on_event :test_case_finished, &method(:on_after_test_case) + config.on_event :test_step_starting, &method(:on_before_test_step) + config.on_event :test_step_finished, &method(:on_after_test_step) + config.on_event :test_run_finished, &method(:on_test_run_finished) end - def on_before_test_case(event) - test_case = event.test_case + def on_before_test_case(test_case) builder = Builder.new(test_case) unless same_feature_as_previous_test_case?(test_case.feature) @feature_hash = builder.feature_hash @@ -38,8 +37,7 @@ def on_before_test_case(event) @any_step_failed = false end - def on_before_test_step(event) - test_step = event.test_step + def on_before_test_step(test_step) return if internal_hook?(test_step) hook_query = HookQueryVisitor.new(test_step) if hook_query.hook? @@ -56,20 +54,19 @@ def on_before_test_step(event) @step_hash = @step_or_hook_hash end - def on_after_test_step(event) - test_step = event.test_step - result = event.result.with_filtered_backtrace(Cucumber::Formatter::BacktraceFilter) + def on_after_test_step(test_step, result) + result = result.with_filtered_backtrace(Cucumber::Formatter::BacktraceFilter) return if internal_hook?(test_step) add_match_and_result(test_step, result) @any_step_failed = true if result.failed? end - def on_after_test_case(event) - result = event.result.with_filtered_backtrace(Cucumber::Formatter::BacktraceFilter) + def on_after_test_case(test_case, result) + result = result.with_filtered_backtrace(Cucumber::Formatter::BacktraceFilter) add_failed_around_hook(result) if result.failed? && !@any_step_failed end - def on_finished_testing(event) + def on_test_run_finished @io.write(MultiJson.dump(@feature_hashes, pretty: true)) end diff --git a/lib/cucumber/formatter/junit.rb b/lib/cucumber/formatter/junit.rb index 9b2dc8288f..083b43af86 100644 --- a/lib/cucumber/formatter/junit.rb +++ b/lib/cucumber/formatter/junit.rb @@ -18,10 +18,10 @@ def initialize(feature_file) end def initialize(config) - config.on_event :before_test_case, &method(:on_before_test_case) - config.on_event :after_test_case, &method(:on_after_test_case) - config.on_event :after_test_step, &method(:on_after_test_step) - config.on_event :finished_testing, &method(:on_finished_testing) + config.on_event :test_case_starting, &method(:on_before_test_case) + config.on_event :test_case_finished, &method(:on_after_test_case) + config.on_event :test_step_finished, &method(:on_after_test_step) + config.on_event :test_run_finished, &method(:on_finished_testing) @reportdir = ensure_dir(config.out_stream, "junit") @config = config @features_data = Hash.new { |h,k| h[k] = { @@ -35,8 +35,7 @@ def initialize(config) }} end - def on_before_test_case(event) - test_case = event.test_case + def on_before_test_case(test_case) unless same_feature_as_previous_test_case?(test_case.feature) start_feature(test_case.feature) end @@ -47,15 +46,14 @@ def on_before_test_case(event) @interceptederr = Interceptor::Pipe.wrap(:stderr) end - def on_after_test_step(event) + def on_after_test_step(test_step, result) return if @failing_step_source - @failing_step_source = event.test_step.source.last unless event.result.ok?(@config.strict?) + @failing_step_source = test_step.source.last unless result.ok?(@config.strict?) end - def on_after_test_case(event) - test_case = event.test_case - result = event.result.with_filtered_backtrace(Cucumber::Formatter::BacktraceFilter) + def on_after_test_case(test_case, result) + result = result.with_filtered_backtrace(Cucumber::Formatter::BacktraceFilter) test_case_name = NameBuilder.new(test_case) scenario = test_case_name.scenario_name scenario_designation = "#{scenario}#{test_case_name.name_suffix}" @@ -66,7 +64,7 @@ def on_after_test_case(event) Interceptor::Pipe.unwrap! :stderr end - def on_finished_testing(event) + def on_finished_testing @features_data.each { |file, data| end_feature(data) } end diff --git a/lib/cucumber/formatter/legacy_api/adapter.rb b/lib/cucumber/formatter/legacy_api/adapter.rb index da5be68591..378334e1a1 100644 --- a/lib/cucumber/formatter/legacy_api/adapter.rb +++ b/lib/cucumber/formatter/legacy_api/adapter.rb @@ -15,44 +15,36 @@ module LegacyApi def initialize(*) super @matches = collect_matches + config.on_event(:test_case_starting) do |test_case| + formatter.before_test_case(test_case) + printer.before_test_case(test_case) + end + config.on_event(:test_step_starting) do |test_step| + formatter.before_test_step(test_step) + printer.before_test_step(test_step) + end + config.on_event(:test_step_finished) do |test_step, result| + printer.after_test_step(test_step, result) + formatter.after_test_step(test_step, result.with_filtered_backtrace(Cucumber::Formatter::BacktraceFilter)) + end + config.on_event(:test_case_finished) do |test_case, result| + record_test_case_result(test_case, result) + printer.after_test_case(test_case, result) + formatter.after_test_case(test_case, result.with_filtered_backtrace(Cucumber::Formatter::BacktraceFilter)) + end + config.on_event(:test_run_finished) do + printer.after + formatter.done + end end - def_delegators :formatter, - :ask - - def_delegators :printer, - :embed - - def before_test_case(test_case) - formatter.before_test_case(test_case) - printer.before_test_case(test_case) - end - - def before_test_step(test_step) - formatter.before_test_step(test_step) - printer.before_test_step(test_step) - end - - def after_test_step(test_step, result) - printer.after_test_step(test_step, result) - formatter.after_test_step(test_step, result.with_filtered_backtrace(Cucumber::Formatter::BacktraceFilter)) - end - - def after_test_case(test_case, result) - record_test_case_result(test_case, result) - printer.after_test_case(test_case, result) - formatter.after_test_case(test_case, result.with_filtered_backtrace(Cucumber::Formatter::BacktraceFilter)) - end + def_delegators :formatter, :ask + def_delegators :printer, :embed def puts(*messages) printer.puts(messages) end - def done - printer.after - formatter.done - end - private def printer @@ -66,8 +58,8 @@ def record_test_case_result(test_case, result) def collect_matches result = {} - config.on_event(:step_match) do |event| - result[event.test_step.source.last] = event.step_match + config.on_event(:step_match) do |test_step, step_match| + result[test_step.source.last] = step_match end result end diff --git a/lib/cucumber/formatter/rerun.rb b/lib/cucumber/formatter/rerun.rb index 179bb57da4..ef18be9bb3 100644 --- a/lib/cucumber/formatter/rerun.rb +++ b/lib/cucumber/formatter/rerun.rb @@ -5,28 +5,23 @@ module Formatter class Rerun include Formatter::Io - def initialize(runtime, path_or_io, options) - @io = ensure_io(path_or_io) + def initialize(config) + @io = ensure_io(config.out_stream) + @config = config @failures = {} - @options = options - end - - def after_test_case(test_case, result) - return if result.ok?(@options[:strict]) - @failures[test_case.location.file] ||= [] - @failures[test_case.location.file] << test_case.location.line - end - - def done - return if @failures.empty? - @io.print file_failures.join(' ') - end - - [:before_test_case, :before_test_step, :after_test_step].each do |method| - define_method(method) { |*| } + config.on_event :test_case_finished do |test_case, result| + next if result.ok?(@config.strict?) + @failures[test_case.location.file] ||= [] + @failures[test_case.location.file] << test_case.location.line + end + config.on_event :test_run_finished do + next if @failures.empty? + @io.print file_failures.join(' ') + end end private + def file_failures @failures.map { |file, lines| [file, lines].join(':') } end diff --git a/lib/cucumber/formatter/usage.rb b/lib/cucumber/formatter/usage.rb index a8c74afacf..3bcbec947c 100644 --- a/lib/cucumber/formatter/usage.rb +++ b/lib/cucumber/formatter/usage.rb @@ -17,8 +17,8 @@ def initialize(runtime, path_or_io, options) @stepdef_to_match = Hash.new { |h, stepdef_key| h[stepdef_key] = [] } @total_duration = 0 @matches = {} - runtime.configuration.on_event :step_match do |event| - @matches[event.test_step.source] = event.step_match + runtime.configuration.on_event :step_match do |test_step, step_match| + @matches[test_step.source] = step_match end end diff --git a/lib/cucumber/runtime.rb b/lib/cucumber/runtime.rb index bcbe7db928..8981da8dd0 100644 --- a/lib/cucumber/runtime.rb +++ b/lib/cucumber/runtime.rb @@ -7,7 +7,6 @@ require 'cucumber/file_specs' require 'cucumber/filters' require 'cucumber/formatter/fanout' -require 'cucumber/formatter/event_bus_report' require 'cucumber/gherkin/i18n' require 'cucumber/step_match_search' @@ -63,8 +62,9 @@ def run! fire_after_configuration_hook self.visitor = report - receiver = Test::Runner.new(report) + receiver = Test::Runner.new(@configuration.event_bus) compile features, receiver, filters + @configuration.notify :test_run_finished end def features_paths @@ -169,17 +169,13 @@ def set_encoding require 'cucumber/core/report/summary' def report return @report if @report - reports = [summary_report, event_bus_report] + formatters + reports = [summary_report] + formatters reports << fail_fast_report if @configuration.fail_fast? @report ||= Formatter::Fanout.new(reports) end def summary_report - @summary_report ||= Core::Report::Summary.new - end - - def event_bus_report - @event_bus_report ||= Formatter::EventBusReport.new(@configuration) + @summary_report ||= Core::Report::Summary.new(@configuration.event_bus) end def fail_fast_report diff --git a/spec/cucumber/events/bus_spec.rb b/spec/cucumber/events/bus_spec.rb deleted file mode 100644 index 546103b801..0000000000 --- a/spec/cucumber/events/bus_spec.rb +++ /dev/null @@ -1,94 +0,0 @@ -require "cucumber/events/bus" - -module Cucumber - module Events - class TestEvent - end - - class AnotherTestEvent - end - - describe Bus do - let(:bus) { Bus.new(Cucumber::Events) } - let(:test_event) { TestEvent.new } - let(:another_test_event) { AnotherTestEvent.new } - - it "calls subscriber with event payload" do - received_payload = nil - bus.register(TestEvent) do |event| - received_payload = event - end - - bus.notify test_event - - expect(received_payload).to eq(test_event) - end - - it "does not call subscribers for other events" do - handler_called = false - bus.register(TestEvent) do |event| - handler_called = true - end - - bus.notify another_test_event - - expect(handler_called).to eq(false) - end - - it "broadcasts to multiple subscribers" do - received_events = [] - bus.register(TestEvent) do |event| - received_events << event - end - bus.register(TestEvent) do |event| - received_events << event - end - - bus.notify test_event - - expect(received_events.length).to eq 2 - expect(received_events).to all eq test_event - end - - it "allows subscription by string" do - received_payload = nil - bus.register('Cucumber::Events::TestEvent') do |event| - received_payload = event - end - - bus.notify test_event - - expect(received_payload).to eq(test_event) - end - - it "allows subscription by symbol (for events in the Cucumber::Events namespace)" do - received_payload = nil - bus.register(:test_event) do |event| - received_payload = event - end - - bus.notify test_event - - expect(received_payload).to eq(test_event) - end - - it "allows handlers that are objects with a `call` method" do - class MyHandler - attr_reader :received_payload - - def call(event) - @received_payload = event - end - end - - handler = MyHandler.new - bus.register(TestEvent, handler) - - bus.notify test_event - - expect(handler.received_payload).to eq test_event - end - - end - end -end diff --git a/spec/cucumber/filters/activate_steps_spec.rb b/spec/cucumber/filters/activate_steps_spec.rb index e0635ca945..1d46c52720 100644 --- a/spec/cucumber/filters/activate_steps_spec.rb +++ b/spec/cucumber/filters/activate_steps_spec.rb @@ -32,9 +32,10 @@ end it "notifies with a StepMatch event" do - expect(configuration).to receive(:notify) do |event| - expect(event.test_step.name).to eq 'a passing step' - expect(event.step_match).to eq step_match + expect(configuration).to receive(:notify) do |message, test_step, step_match| + expect(message).to eq :step_match + expect(test_step.name).to eq 'a passing step' + expect(step_match).to eq step_match end compile [doc], receiver, [filter] end @@ -111,9 +112,10 @@ end it "notifies with a StepMatch event" do - expect(configuration).to receive(:notify) do |event| - expect(event.test_step.name).to eq 'a passing step' - expect(event.step_match).to eq step_match + expect(configuration).to receive(:notify) do |message, test_step, step_match| + expect(message).to eq :step_match + expect(test_step.name).to eq 'a passing step' + expect(step_match).to eq step_match end compile [doc], receiver, [filter] end diff --git a/spec/cucumber/formatter/event_bus_report_spec.rb b/spec/cucumber/formatter/event_bus_report_spec.rb deleted file mode 100644 index 88aa53e852..0000000000 --- a/spec/cucumber/formatter/event_bus_report_spec.rb +++ /dev/null @@ -1,88 +0,0 @@ -require 'cucumber/configuration' -require 'cucumber/runtime' -require 'cucumber/formatter/spec_helper' -require 'cucumber/formatter/event_bus_report' - -module Cucumber - module Formatter - describe EventBusReport do - extend SpecHelperDsl - include SpecHelper - - context "With no options" do - let(:config) { Cucumber::Configuration.new } - - before(:each) do - @formatter = EventBusReport.new(config) - end - - describe "given a single feature" do - - describe "a scenario with a single passing step" do - define_feature <<-FEATURE - Feature: - Scenario: Test Scenario - Given passing - FEATURE - - define_steps do - Given(/pass/) {} - end - - it "emits a BeforeTestCase event" do - received_event = nil - config.on_event Cucumber::Events::BeforeTestCase do |event| - received_event = event - end - run_defined_feature - expect(received_event.test_case.name).to eq "Test Scenario" - end - - it "emits a BeforeTestStep event" do - received_event = nil - config.on_event Cucumber::Events::BeforeTestStep do |event| - received_event = event - end - run_defined_feature - expect(received_event.test_case.name).to eq "Test Scenario" - expect(received_event.test_step.name).to eq "passing" - end - - it "emits an AfterTestStep event with a passed result" do - received_event = nil - config.on_event Cucumber::Events::AfterTestStep do |event| - received_event = event - end - run_defined_feature - expect(received_event.test_case.name).to eq "Test Scenario" - expect(received_event.test_step.name).to eq "passing" - expect(received_event.result).to be_passed - end - - it "emits an AfterTestCase event with a passed result" do - received_event = nil - config.on_event Cucumber::Events::AfterTestCase do |event| - received_event = event - end - run_defined_feature - expect(received_event.test_case.name).to eq "Test Scenario" - expect(received_event.result).to be_passed - end - - it "emits a Done event when the test run is finished" do - received_event = nil - config.on_event Cucumber::Events::FinishedTesting do |event| - received_event = event - end - run_defined_feature - expect(received_event).not_to be_nil - end - end - end - end - end - end -end - - - diff --git a/spec/cucumber/formatter/fail_fast_spec.rb b/spec/cucumber/formatter/fail_fast_spec.rb index b5f417df52..c0b585da07 100644 --- a/spec/cucumber/formatter/fail_fast_spec.rb +++ b/spec/cucumber/formatter/fail_fast_spec.rb @@ -14,7 +14,6 @@ module Cucumber::Formatter let(:configuration) { Cucumber::Configuration.new } before { FailFast.new(configuration) } - let(:report) { EventBusReport.new(configuration) } context 'failing scenario' do before(:each) do @@ -36,7 +35,7 @@ module Cucumber::Formatter end it 'sets Cucumber.wants_to_quit' do - execute([@gherkin], report, [StandardStepActions.new]) + execute [@gherkin], [StandardStepActions.new], configuration.event_bus expect(Cucumber.wants_to_quit).to be true end end @@ -53,7 +52,7 @@ module Cucumber::Formatter end it 'doesn\'t set Cucumber.wants_to_quit' do - execute([@gherkin], report, [StandardStepActions.new]) + execute [@gherkin], [StandardStepActions.new], configuration.event_bus expect(Cucumber.wants_to_quit).to be_falsey end end @@ -70,7 +69,7 @@ module Cucumber::Formatter end it 'doesn\'t set Cucumber.wants_to_quit' do - execute([@gherkin], report, [StandardStepActions.new]) + execute [@gherkin], [StandardStepActions.new], configuration.event_bus expect(Cucumber.wants_to_quit).to be_falsey end @@ -78,7 +77,7 @@ module Cucumber::Formatter let(:configuration) { Cucumber::Configuration.new strict: true } it 'sets Cucumber.wants_to_quit' do - execute([@gherkin], report, [StandardStepActions.new]) + execute [@gherkin], [StandardStepActions.new], configuration.event_bus expect(Cucumber.wants_to_quit).to be_truthy end end diff --git a/spec/cucumber/formatter/legacy_api/adapter_spec.rb b/spec/cucumber/formatter/legacy_api/adapter_spec.rb index b8aee143ec..f501a9e3bc 100644 --- a/spec/cucumber/formatter/legacy_api/adapter_spec.rb +++ b/spec/cucumber/formatter/legacy_api/adapter_spec.rb @@ -13,9 +13,10 @@ module Formatter::LegacyApi include Core::Gherkin::Writer include Core - let(:report) { Adapter.new(formatter, runtime.results, runtime.configuration) } + let!(:report) { Adapter.new(formatter, runtime.results, runtime.configuration) } let(:formatter) { double('formatter').as_null_object } let(:runtime) { Runtime.new } + let(:events) { runtime.configuration.event_bus } let(:step_match_search) { SimpleStepDefinitionSearch.new } Failure = Class.new(StandardError) @@ -106,8 +107,9 @@ def after_hooks(source) end end, ] - runner = Core::Test::Runner.new(report) + runner = Core::Test::Runner.new(events) compile gherkin_docs, runner, default_filters + events.test_run_finished expect( formatter.legacy_messages ).to eq [ :before_features, :before_feature, @@ -2166,8 +2168,10 @@ def respond_to_missing?(name, include_private = false) end def execute_gherkin(filters = default_filters, &gherkin) - runner = Core::Test::Runner.new(report) + runner = Core::Test::Runner.new(events) compile [gherkin(&gherkin)], runner, filters + events.test_run_finished + self end def default_filters diff --git a/spec/cucumber/formatter/rerun_spec.rb b/spec/cucumber/formatter/rerun_spec.rb index 4dc839b1a7..fa7a2bd372 100644 --- a/spec/cucumber/formatter/rerun_spec.rb +++ b/spec/cucumber/formatter/rerun_spec.rb @@ -3,88 +3,93 @@ require 'cucumber/core/gherkin/writer' require 'cucumber/core/filter' require 'support/standard_step_actions' - -module Cucumber::Formatter - describe Rerun do - include Cucumber::Core::Gherkin::Writer - include Cucumber::Core - - # after_test_case - context 'when 2 scenarios fail in the same file' do - it 'Prints the locations of the failed scenarios' do - gherkin = gherkin('foo.feature') do - feature do - scenario do - step 'failing' - end - - scenario do - step 'failing' - end - - scenario do - step 'passing' +require 'cucumber/configuration' + +module Cucumber + module Formatter + describe Rerun do + include Cucumber::Core::Gherkin::Writer + include Cucumber::Core + + let(:config) { Cucumber::Configuration.new(out_stream: io) } + let(:io) { StringIO.new } + + # after_test_case + context 'when 2 scenarios fail in the same file' do + it 'Prints the locations of the failed scenarios' do + gherkin = gherkin('foo.feature') do + feature do + scenario do + step 'failing' + end + + scenario do + step 'failing' + end + + scenario do + step 'passing' + end end end - end - io = StringIO.new - report = Rerun.new(double, io, {}) - - execute [gherkin], report, [StandardStepActions.new] + Rerun.new(config) + execute [gherkin], [StandardStepActions.new], config.event_bus + config.event_bus.test_run_finished - expect( io.string ).to eq 'foo.feature:3:6' + expect( io.string ).to eq 'foo.feature:3:6' + end end - end - context 'with failures in multiple files' do - it 'prints the location of the failed scenarios in each file' do - foo = gherkin('foo.feature') do - feature do - scenario do - step 'failing' - end - - scenario do - step 'failing' - end - - scenario do - step 'passing' + context 'with failures in multiple files' do + it 'prints the location of the failed scenarios in each file' do + foo = gherkin('foo.feature') do + feature do + scenario do + step 'failing' + end + + scenario do + step 'failing' + end + + scenario do + step 'passing' + end end end - end - bar = gherkin('bar.feature') do - feature do - scenario do - step 'failing' + bar = gherkin('bar.feature') do + feature do + scenario do + step 'failing' + end end end - end - io = StringIO.new - report = Rerun.new(double, io, {}) + Rerun.new(config) + execute [foo, bar], [StandardStepActions.new], config.event_bus + config.event_bus.test_run_finished - execute [foo, bar], report, [StandardStepActions.new] - - expect(io.string).to eq 'foo.feature:3:6 bar.feature:3' + expect(io.string).to eq 'foo.feature:3:6 bar.feature:3' + end end - end - context 'when there are no failing scenarios' do - it 'prints nothing' do - gherkin = gherkin('foo.feature') do - feature do - scenario do - step 'passing' + context 'when there are no failing scenarios' do + it 'prints nothing' do + gherkin = gherkin('foo.feature') do + feature do + scenario do + step 'passing' + end end end - end - io = StringIO.new - report = Rerun.new(double, io, {}) + Rerun.new(config) + execute [gherkin], [StandardStepActions.new], config.event_bus + config.event_bus.test_run_finished - execute [gherkin], report, [StandardStepActions.new] + expect(io.string).to eq '' + end end end end diff --git a/spec/cucumber/formatter/spec_helper.rb b/spec/cucumber/formatter/spec_helper.rb index 83da11a8ad..cd80e139f9 100644 --- a/spec/cucumber/formatter/spec_helper.rb +++ b/spec/cucumber/formatter/spec_helper.rb @@ -21,7 +21,7 @@ def run_defined_feature define_steps actual_runtime.visitor = report - receiver = Test::Runner.new(report) + receiver = Test::Runner.new(events) filters = [ Filters::ActivateSteps.new( StepMatchSearch.new(actual_runtime.support_code.ruby.method(:step_matches), actual_runtime.configuration), @@ -34,17 +34,13 @@ def run_defined_feature Filters::PrepareWorld.new(actual_runtime) ] compile [gherkin_doc], receiver, filters - end - - require 'cucumber/formatter/event_bus_report' - def event_bus_report - @event_bus_report ||= Formatter::EventBusReport.new(actual_runtime.configuration) + events.test_run_finished end require 'cucumber/formatter/legacy_api/adapter' def report @report ||= LegacyApi::Adapter.new( - Fanout.new([@formatter, event_bus_report]), + Fanout.new([@formatter]), actual_runtime.results, actual_runtime.configuration) end @@ -66,6 +62,10 @@ def actual_runtime @runtime ||= Runtime.new(options) end + def events + actual_runtime.configuration.event_bus + end + def define_steps return unless step_defs = self.class.step_defs rb = runtime.support_code.ruby From 0408815f86ec73a82741231b27d9da80ab202044 Mon Sep 17 00:00:00 2001 From: Matt Wynne Date: Fri, 6 May 2016 13:57:33 +0100 Subject: [PATCH 2/9] Update to latest core events API changes --- features/docs/api/listen_for_events.feature | 12 +++++------ .../custom_formatter.feature | 6 +++--- lib/cucumber/configuration.rb | 2 +- lib/cucumber/events.rb | 9 +++++++- lib/cucumber/formatter/fail_fast.rb | 3 ++- lib/cucumber/formatter/json.rb | 14 ++++++++----- lib/cucumber/formatter/junit.rb | 11 ++++++---- lib/cucumber/formatter/legacy_api/adapter.rb | 21 +++++++++++-------- lib/cucumber/formatter/rerun.rb | 3 ++- lib/cucumber/formatter/usage.rb | 3 ++- 10 files changed, 52 insertions(+), 32 deletions(-) diff --git a/features/docs/api/listen_for_events.feature b/features/docs/api/listen_for_events.feature index 65d9b38d37..afb19e05c2 100644 --- a/features/docs/api/listen_for_events.feature +++ b/features/docs/api/listen_for_events.feature @@ -19,10 +19,10 @@ Feature: Listen for events """ AfterConfiguration do |config| io = config.out_stream - config.on_event Cucumber::Events::StepMatch do |test_step, step_match| + config.on_event :step_match do |event| io.puts "Success!" - io.puts "Step name: #{test_step.name}" - io.puts "Source location: #{step_match.location}" + io.puts "Step name: #{event.test_step.name}" + io.puts "Source location: #{event.step_match.location}" end end """ @@ -46,14 +46,14 @@ Feature: Listen for events """ AfterConfiguration do |config| io = config.out_stream - config.on_event Cucumber::Core::Events::TestStepFinished do |test_step, result| - io.puts "YO" + config.on_event :test_step_finished do |event| + io.puts event.result.passed? end end """ When I run `cucumber` Then it should pass with: """ - YO + true """ diff --git a/features/docs/extending_cucumber/custom_formatter.feature b/features/docs/extending_cucumber/custom_formatter.feature index cdfcb63203..6788ecca20 100644 --- a/features/docs/extending_cucumber/custom_formatter.feature +++ b/features/docs/extending_cucumber/custom_formatter.feature @@ -19,8 +19,8 @@ Feature: Custom Formatter class Formatter def initialize(config) @io = config.out_stream - config.on_event :test_case_starting do |test_case| - print_test_case_name(test_case) + config.on_event :test_case_starting do |event| + print_test_case_name(event.test_case) end end @@ -71,7 +71,7 @@ Feature: Custom Formatter """ Scenario: Use both old and new - You can use a specific shim to opt-in to both APIs at once. + You can both APIs at once, for now Given a file named "features/support/custom_mixed_formatter.rb" with: """ diff --git a/lib/cucumber/configuration.rb b/lib/cucumber/configuration.rb index 6b84edcd05..ce174b6b01 100644 --- a/lib/cucumber/configuration.rb +++ b/lib/cucumber/configuration.rb @@ -242,7 +242,7 @@ def default_options :snippets => true, :source => true, :duration => true, - :event_bus => Core::Events::Bus.new(Cucumber::Events) + :event_bus => Core::Events::Bus.new(Core::Events.registry.merge(Cucumber::Events.registry)) } end diff --git a/lib/cucumber/events.rb b/lib/cucumber/events.rb index c4d6043cff..59a3935d38 100644 --- a/lib/cucumber/events.rb +++ b/lib/cucumber/events.rb @@ -1,3 +1,5 @@ +Dir[File.dirname(__FILE__) + '/events/*.rb'].map(&method(:require)) + module Cucumber # Events tell you what's happening while Cucumber runs your features. @@ -14,7 +16,12 @@ module Cucumber # end # end module Events + def self.registry + Core::Events.build_registry( + StepMatch, + TestRunFinished, + ) + end end end -Dir[File.dirname(__FILE__) + '/events/*.rb'].map(&method(:require)) diff --git a/lib/cucumber/formatter/fail_fast.rb b/lib/cucumber/formatter/fail_fast.rb index 294be9e54f..d3ece67ca9 100644 --- a/lib/cucumber/formatter/fail_fast.rb +++ b/lib/cucumber/formatter/fail_fast.rb @@ -7,7 +7,8 @@ module Formatter class FailFast def initialize(configuration) - configuration.on_event :test_case_finished do |test_case, result| + configuration.on_event :test_case_finished do |event| + test_case, result = *event.attributes Cucumber.wants_to_quit = true unless result.ok?(configuration.strict?) end end diff --git a/lib/cucumber/formatter/json.rb b/lib/cucumber/formatter/json.rb index 0ff2c886e7..5171e0e7d2 100644 --- a/lib/cucumber/formatter/json.rb +++ b/lib/cucumber/formatter/json.rb @@ -20,7 +20,8 @@ def initialize(config) config.on_event :test_run_finished, &method(:on_test_run_finished) end - def on_before_test_case(test_case) + def on_before_test_case(event) + test_case = event.test_case builder = Builder.new(test_case) unless same_feature_as_previous_test_case?(test_case.feature) @feature_hash = builder.feature_hash @@ -37,7 +38,8 @@ def on_before_test_case(test_case) @any_step_failed = false end - def on_before_test_step(test_step) + def on_before_test_step(event) + test_step = event.test_step return if internal_hook?(test_step) hook_query = HookQueryVisitor.new(test_step) if hook_query.hook? @@ -54,19 +56,21 @@ def on_before_test_step(test_step) @step_hash = @step_or_hook_hash end - def on_after_test_step(test_step, result) + def on_after_test_step(event) + test_step, result = *event.attributes result = result.with_filtered_backtrace(Cucumber::Formatter::BacktraceFilter) return if internal_hook?(test_step) add_match_and_result(test_step, result) @any_step_failed = true if result.failed? end - def on_after_test_case(test_case, result) + def on_after_test_case(event) + test_case, result = *event.attributes result = result.with_filtered_backtrace(Cucumber::Formatter::BacktraceFilter) add_failed_around_hook(result) if result.failed? && !@any_step_failed end - def on_test_run_finished + def on_test_run_finished(event) @io.write(MultiJson.dump(@feature_hashes, pretty: true)) end diff --git a/lib/cucumber/formatter/junit.rb b/lib/cucumber/formatter/junit.rb index 083b43af86..367bf0c3ff 100644 --- a/lib/cucumber/formatter/junit.rb +++ b/lib/cucumber/formatter/junit.rb @@ -35,7 +35,8 @@ def initialize(config) }} end - def on_before_test_case(test_case) + def on_before_test_case(event) + test_case = event.test_case unless same_feature_as_previous_test_case?(test_case.feature) start_feature(test_case.feature) end @@ -46,13 +47,15 @@ def on_before_test_case(test_case) @interceptederr = Interceptor::Pipe.wrap(:stderr) end - def on_after_test_step(test_step, result) + def on_after_test_step(event) + test_step, result = *event.attributes return if @failing_step_source @failing_step_source = test_step.source.last unless result.ok?(@config.strict?) end - def on_after_test_case(test_case, result) + def on_after_test_case(event) + test_case, result = *event.attributes result = result.with_filtered_backtrace(Cucumber::Formatter::BacktraceFilter) test_case_name = NameBuilder.new(test_case) scenario = test_case_name.scenario_name @@ -64,7 +67,7 @@ def on_after_test_case(test_case, result) Interceptor::Pipe.unwrap! :stderr end - def on_finished_testing + def on_finished_testing(event) @features_data.each { |file, data| end_feature(data) } end diff --git a/lib/cucumber/formatter/legacy_api/adapter.rb b/lib/cucumber/formatter/legacy_api/adapter.rb index 378334e1a1..a1eb3d5281 100644 --- a/lib/cucumber/formatter/legacy_api/adapter.rb +++ b/lib/cucumber/formatter/legacy_api/adapter.rb @@ -15,19 +15,21 @@ module LegacyApi def initialize(*) super @matches = collect_matches - config.on_event(:test_case_starting) do |test_case| - formatter.before_test_case(test_case) - printer.before_test_case(test_case) + config.on_event(:test_case_starting) do |event| + formatter.before_test_case(event.test_case) + printer.before_test_case(event.test_case) end - config.on_event(:test_step_starting) do |test_step| - formatter.before_test_step(test_step) - printer.before_test_step(test_step) + config.on_event(:test_step_starting) do |event| + formatter.before_test_step(event.test_step) + printer.before_test_step(event.test_step) end - config.on_event(:test_step_finished) do |test_step, result| + config.on_event(:test_step_finished) do |event| + test_step, result = *event.attributes printer.after_test_step(test_step, result) formatter.after_test_step(test_step, result.with_filtered_backtrace(Cucumber::Formatter::BacktraceFilter)) end - config.on_event(:test_case_finished) do |test_case, result| + config.on_event(:test_case_finished) do |event| + test_case, result = *event.attributes record_test_case_result(test_case, result) printer.after_test_case(test_case, result) formatter.after_test_case(test_case, result.with_filtered_backtrace(Cucumber::Formatter::BacktraceFilter)) @@ -58,7 +60,8 @@ def record_test_case_result(test_case, result) def collect_matches result = {} - config.on_event(:step_match) do |test_step, step_match| + config.on_event(:step_match) do |event| + test_step, step_match = *event.attributes result[test_step.source.last] = step_match end result diff --git a/lib/cucumber/formatter/rerun.rb b/lib/cucumber/formatter/rerun.rb index ef18be9bb3..430636cea1 100644 --- a/lib/cucumber/formatter/rerun.rb +++ b/lib/cucumber/formatter/rerun.rb @@ -9,7 +9,8 @@ def initialize(config) @io = ensure_io(config.out_stream) @config = config @failures = {} - config.on_event :test_case_finished do |test_case, result| + config.on_event :test_case_finished do |event| + test_case, result = *event.attributes next if result.ok?(@config.strict?) @failures[test_case.location.file] ||= [] @failures[test_case.location.file] << test_case.location.line diff --git a/lib/cucumber/formatter/usage.rb b/lib/cucumber/formatter/usage.rb index 3bcbec947c..27d5d7f7a0 100644 --- a/lib/cucumber/formatter/usage.rb +++ b/lib/cucumber/formatter/usage.rb @@ -17,7 +17,8 @@ def initialize(runtime, path_or_io, options) @stepdef_to_match = Hash.new { |h, stepdef_key| h[stepdef_key] = [] } @total_duration = 0 @matches = {} - runtime.configuration.on_event :step_match do |test_step, step_match| + runtime.configuration.on_event :step_match do |event| + test_step, step_match = *event.attributes @matches[test_step.source] = step_match end end From cc8824dc8941dfd4b03c16b1fa16e830da033ce3 Mon Sep 17 00:00:00 2001 From: Matt Wynne Date: Mon, 9 May 2016 23:59:25 +0100 Subject: [PATCH 3/9] Fix for renamed bus --- lib/cucumber/configuration.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/cucumber/configuration.rb b/lib/cucumber/configuration.rb index ce174b6b01..8554e794aa 100644 --- a/lib/cucumber/configuration.rb +++ b/lib/cucumber/configuration.rb @@ -1,6 +1,7 @@ require 'cucumber/constantize' require 'cucumber/cli/rerun_file' require 'cucumber/events' +require 'cucumber/core/event_bus' require 'forwardable' require 'cucumber/core/gherkin/tag_expression' require 'cucumber' @@ -242,7 +243,7 @@ def default_options :snippets => true, :source => true, :duration => true, - :event_bus => Core::Events::Bus.new(Core::Events.registry.merge(Cucumber::Events.registry)) + :event_bus => Core::EventBus.new(Core::Events.registry.merge(Cucumber::Events.registry)) } end From d9852e0d8b6ef6c2eb23f9bb9dbb7c9f06b43782 Mon Sep 17 00:00:00 2001 From: Matt Wynne Date: Fri, 20 May 2016 19:41:26 +0100 Subject: [PATCH 4/9] Fix core version --- cucumber.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cucumber.gemspec b/cucumber.gemspec index b74dd41da9..fd8b0bacbc 100644 --- a/cucumber.gemspec +++ b/cucumber.gemspec @@ -10,7 +10,7 @@ Gem::Specification.new do |s| s.homepage = "http://cukes.info" s.platform = Gem::Platform::RUBY s.required_ruby_version = ">= 1.9.3" - s.add_dependency 'cucumber-core', '~> 3.0' + s.add_dependency 'cucumber-core', '~> 2.0' s.add_dependency 'builder', '>= 2.1.2' s.add_dependency 'diff-lcs', '>= 1.1.3' s.add_dependency 'gherkin', '~> 4.0' From 8e91cd913d3fdf05d468f32a0771d127294bd5be Mon Sep 17 00:00:00 2001 From: Matt Wynne Date: Fri, 20 May 2016 19:51:11 +0100 Subject: [PATCH 5/9] Update retry filter to work with new events API --- lib/cucumber/filters/retry.rb | 5 ++- spec/cucumber/filters/retry_spec.rb | 47 ++++++++++++++++------------- 2 files changed, 28 insertions(+), 24 deletions(-) diff --git a/lib/cucumber/filters/retry.rb b/lib/cucumber/filters/retry.rb index 3017bd7727..ed421de001 100644 --- a/lib/cucumber/filters/retry.rb +++ b/lib/cucumber/filters/retry.rb @@ -1,14 +1,13 @@ require 'cucumber/core/filter' require 'cucumber/running_test_case' -require 'cucumber/events/bus' -require 'cucumber/events/after_test_case' +require 'cucumber/events' module Cucumber module Filters class Retry < Core::Filter.new(:configuration) def test_case(test_case) - configuration.on_event(:after_test_case) do |event| + configuration.on_event(:test_case_finished) do |event| next unless retry_required?(test_case, event) test_case_counts[test_case] += 1 diff --git a/spec/cucumber/filters/retry_spec.rb b/spec/cucumber/filters/retry_spec.rb index f9e94823a1..74500277f5 100644 --- a/spec/cucumber/filters/retry_spec.rb +++ b/spec/cucumber/filters/retry_spec.rb @@ -22,29 +22,22 @@ it { is_expected.to respond_to(:with_receiver) } it { is_expected.to respond_to(:done) } - context "general" do - before(:each) do - filter.with_receiver(receiver) - end - - it "registers the :after_test_case event" do - expect(configuration).to receive(:on_event).with(:after_test_case) - filter.test_case(test_case) - end - end - context "passing test case" do + let(:result) { Cucumber::Core::Test::Result::Passed.new(0) } + it "describes the test case once" do - expect(test_case).to receive(:describe_to).with(receiver) - filter.test_case(test_case) - configuration.notify(pass) + expect(receiver).to receive(:test_case).with(test_case).once + test_case.describe_to filter + configuration.notify :test_case_finished, test_case, result end end - context "failing test case" do + context "consistently failing test case" do + let(:result) { Cucumber::Core::Test::Result::Failed.new(0, StandardError.new) } + it "describes the test case the specified number of times" do expect(receiver).to receive(:test_case) {|test_case| - configuration.notify(fail) + configuration.notify :test_case_finished, test_case, result }.exactly(3).times filter.test_case(test_case) @@ -54,10 +47,16 @@ context "flaky test cases" do context "a little flaky" do + let(:results) { + [ + Cucumber::Core::Test::Result::Failed.new(0, StandardError.new), + Cucumber::Core::Test::Result::Passed.new(0) + ] + } + it "describes the test case twice" do - results = [fail, pass] expect(receiver).to receive(:test_case) {|test_case| - configuration.notify(results.shift) + configuration.notify :test_case_finished, test_case, results.shift }.exactly(2).times filter.test_case(test_case) @@ -65,11 +64,17 @@ end context "really flaky" do - it "describes the test case 3 times" do - results = [fail, fail, pass] + let(:results) { + [ + Cucumber::Core::Test::Result::Failed.new(0, StandardError.new), + Cucumber::Core::Test::Result::Failed.new(0, StandardError.new), + Cucumber::Core::Test::Result::Passed.new(0) + ] + } + it "describes the test case 3 times" do expect(receiver).to receive(:test_case) {|test_case| - configuration.notify(results.shift) + configuration.notify :test_case_finished, test_case, results.shift }.exactly(3).times filter.test_case(test_case) From 3f41ac4d70be32c6598a6eda46ade414f73a4903 Mon Sep 17 00:00:00 2001 From: Matt Wynne Date: Sat, 21 May 2016 15:12:34 +0100 Subject: [PATCH 6/9] Make event parsable by yardoc --- lib/cucumber/events/test_run_finished.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/cucumber/events/test_run_finished.rb b/lib/cucumber/events/test_run_finished.rb index 654c1f853e..5e8d3efdd3 100644 --- a/lib/cucumber/events/test_run_finished.rb +++ b/lib/cucumber/events/test_run_finished.rb @@ -3,8 +3,9 @@ module Cucumber module Events - # Event fired after aall test cases have finished executing - TestRunFinished = Class.new(Core::Event.new) + # Event fired after all test cases have finished executing + class TestRunFinished < Core::Event.new + end end end From 633cb1445310f5d9b104278293381ade97dfa6d8 Mon Sep 17 00:00:00 2001 From: Matt Wynne Date: Sat, 21 May 2016 15:20:24 +0100 Subject: [PATCH 7/9] Improve docs a bit --- lib/cucumber/events.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/cucumber/events.rb b/lib/cucumber/events.rb index 59a3935d38..043b3333d6 100644 --- a/lib/cucumber/events.rb +++ b/lib/cucumber/events.rb @@ -5,16 +5,17 @@ module Cucumber # Events tell you what's happening while Cucumber runs your features. # # They're designed to be read-only, appropriate for writing formatters and other - # output tools. If you need to be able to influence the result of a scenario, use a hook instead. + # output tools. If you need to be able to influence the result of a scenario, use a {RbSupport::RbDsl hook} instead. # # To subscribe to an event, use {Cucumber::Configuration#on_event} # # @example # AfterConfiguration do |config| - # config.on_event :after_test_step do |event| + # config.on_event :test_case_finished do |event| # puts event.result # end # end + # module Events def self.registry Core::Events.build_registry( From b93a30b4ed7adb3ae5c6c66fb6e68b475d3ea9df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Rasmusson?= Date: Sun, 29 May 2016 16:20:58 +0200 Subject: [PATCH 8/9] Consistently use event_bus to refer to a EventBus object. --- spec/cucumber/formatter/spec_helper.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/cucumber/formatter/spec_helper.rb b/spec/cucumber/formatter/spec_helper.rb index cd80e139f9..f9d4e96c29 100644 --- a/spec/cucumber/formatter/spec_helper.rb +++ b/spec/cucumber/formatter/spec_helper.rb @@ -21,7 +21,7 @@ def run_defined_feature define_steps actual_runtime.visitor = report - receiver = Test::Runner.new(events) + receiver = Test::Runner.new(event_bus) filters = [ Filters::ActivateSteps.new( StepMatchSearch.new(actual_runtime.support_code.ruby.method(:step_matches), actual_runtime.configuration), @@ -34,7 +34,7 @@ def run_defined_feature Filters::PrepareWorld.new(actual_runtime) ] compile [gherkin_doc], receiver, filters - events.test_run_finished + event_bus.test_run_finished end require 'cucumber/formatter/legacy_api/adapter' @@ -62,7 +62,7 @@ def actual_runtime @runtime ||= Runtime.new(options) end - def events + def event_bus actual_runtime.configuration.event_bus end From becc6d49c40f352467a6b2562c5ad49a8b5e6b44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Rasmusson?= Date: Mon, 6 Jun 2016 14:01:42 +0200 Subject: [PATCH 9/9] Name the method called on events after the event name. --- lib/cucumber/formatter/json.rb | 16 ++++++++-------- lib/cucumber/formatter/junit.rb | 16 ++++++++-------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/lib/cucumber/formatter/json.rb b/lib/cucumber/formatter/json.rb index 5171e0e7d2..310d218eee 100644 --- a/lib/cucumber/formatter/json.rb +++ b/lib/cucumber/formatter/json.rb @@ -13,14 +13,14 @@ class Json def initialize(config) @io = ensure_io(config.out_stream) @feature_hashes = [] - config.on_event :test_case_starting, &method(:on_before_test_case) - config.on_event :test_case_finished, &method(:on_after_test_case) - config.on_event :test_step_starting, &method(:on_before_test_step) - config.on_event :test_step_finished, &method(:on_after_test_step) + config.on_event :test_case_starting, &method(:on_test_case_starting) + config.on_event :test_case_finished, &method(:on_test_case_finished) + config.on_event :test_step_starting, &method(:on_test_step_starting) + config.on_event :test_step_finished, &method(:on_test_step_finished) config.on_event :test_run_finished, &method(:on_test_run_finished) end - def on_before_test_case(event) + def on_test_case_starting(event) test_case = event.test_case builder = Builder.new(test_case) unless same_feature_as_previous_test_case?(test_case.feature) @@ -38,7 +38,7 @@ def on_before_test_case(event) @any_step_failed = false end - def on_before_test_step(event) + def on_test_step_starting(event) test_step = event.test_step return if internal_hook?(test_step) hook_query = HookQueryVisitor.new(test_step) @@ -56,7 +56,7 @@ def on_before_test_step(event) @step_hash = @step_or_hook_hash end - def on_after_test_step(event) + def on_test_step_finished(event) test_step, result = *event.attributes result = result.with_filtered_backtrace(Cucumber::Formatter::BacktraceFilter) return if internal_hook?(test_step) @@ -64,7 +64,7 @@ def on_after_test_step(event) @any_step_failed = true if result.failed? end - def on_after_test_case(event) + def on_test_case_finished(event) test_case, result = *event.attributes result = result.with_filtered_backtrace(Cucumber::Formatter::BacktraceFilter) add_failed_around_hook(result) if result.failed? && !@any_step_failed diff --git a/lib/cucumber/formatter/junit.rb b/lib/cucumber/formatter/junit.rb index 367bf0c3ff..6075ba015e 100644 --- a/lib/cucumber/formatter/junit.rb +++ b/lib/cucumber/formatter/junit.rb @@ -18,10 +18,10 @@ def initialize(feature_file) end def initialize(config) - config.on_event :test_case_starting, &method(:on_before_test_case) - config.on_event :test_case_finished, &method(:on_after_test_case) - config.on_event :test_step_finished, &method(:on_after_test_step) - config.on_event :test_run_finished, &method(:on_finished_testing) + config.on_event :test_case_starting, &method(:on_test_case_starting) + config.on_event :test_case_finished, &method(:on_test_case_finished) + config.on_event :test_step_finished, &method(:on_test_step_finished) + config.on_event :test_run_finished, &method(:on_test_run_finished) @reportdir = ensure_dir(config.out_stream, "junit") @config = config @features_data = Hash.new { |h,k| h[k] = { @@ -35,7 +35,7 @@ def initialize(config) }} end - def on_before_test_case(event) + def on_test_case_starting(event) test_case = event.test_case unless same_feature_as_previous_test_case?(test_case.feature) start_feature(test_case.feature) @@ -47,14 +47,14 @@ def on_before_test_case(event) @interceptederr = Interceptor::Pipe.wrap(:stderr) end - def on_after_test_step(event) + def on_test_step_finished(event) test_step, result = *event.attributes return if @failing_step_source @failing_step_source = test_step.source.last unless result.ok?(@config.strict?) end - def on_after_test_case(event) + def on_test_case_finished(event) test_case, result = *event.attributes result = result.with_filtered_backtrace(Cucumber::Formatter::BacktraceFilter) test_case_name = NameBuilder.new(test_case) @@ -67,7 +67,7 @@ def on_after_test_case(event) Interceptor::Pipe.unwrap! :stderr end - def on_finished_testing(event) + def on_test_run_finished(event) @features_data.each { |file, data| end_feature(data) } end