cucumber 3.2.0 → 5.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +280 -19
- data/CONTRIBUTING.md +11 -25
- data/README.md +4 -5
- data/bin/cucumber +1 -1
- data/lib/autotest/cucumber_mixin.rb +46 -53
- data/lib/cucumber/cli/configuration.rb +5 -5
- data/lib/cucumber/cli/main.rb +12 -12
- data/lib/cucumber/cli/options.rb +90 -73
- data/lib/cucumber/cli/profile_loader.rb +49 -26
- data/lib/cucumber/configuration.rb +44 -29
- data/lib/cucumber/constantize.rb +2 -5
- data/lib/cucumber/deprecate.rb +31 -7
- data/lib/cucumber/errors.rb +5 -7
- data/lib/cucumber/events/envelope.rb +9 -0
- data/lib/cucumber/events/gherkin_source_parsed.rb +11 -0
- data/lib/cucumber/events/hook_test_step_created.rb +13 -0
- data/lib/cucumber/events/step_activated.rb +2 -1
- data/lib/cucumber/events/test_case_created.rb +13 -0
- data/lib/cucumber/events/test_case_ready.rb +12 -0
- data/lib/cucumber/events/test_step_created.rb +13 -0
- data/lib/cucumber/events/undefined_parameter_type.rb +10 -0
- data/lib/cucumber/events.rb +13 -6
- data/lib/cucumber/file_specs.rb +6 -6
- data/lib/cucumber/filters/activate_steps.rb +5 -3
- data/lib/cucumber/filters/broadcast_test_case_ready_event.rb +12 -0
- data/lib/cucumber/filters/prepare_world.rb +5 -9
- data/lib/cucumber/filters/quit.rb +1 -3
- data/lib/cucumber/filters/tag_limits/verifier.rb +2 -4
- data/lib/cucumber/filters.rb +1 -0
- data/lib/cucumber/formatter/ansicolor.rb +40 -45
- data/lib/cucumber/formatter/ast_lookup.rb +163 -0
- data/lib/cucumber/formatter/backtrace_filter.rb +9 -8
- data/lib/cucumber/formatter/console.rb +58 -66
- data/lib/cucumber/formatter/console_counts.rb +4 -9
- data/lib/cucumber/formatter/console_issues.rb +6 -3
- data/lib/cucumber/formatter/duration.rb +1 -1
- data/lib/cucumber/formatter/duration_extractor.rb +3 -1
- data/lib/cucumber/formatter/errors.rb +6 -0
- data/lib/cucumber/formatter/fanout.rb +2 -0
- data/lib/cucumber/formatter/html.rb +11 -598
- data/lib/cucumber/formatter/http_io.rb +43 -42
- data/lib/cucumber/formatter/ignore_missing_messages.rb +1 -1
- data/lib/cucumber/formatter/interceptor.rb +11 -30
- data/lib/cucumber/formatter/io.rb +46 -10
- data/lib/cucumber/formatter/json.rb +102 -116
- data/lib/cucumber/formatter/junit.rb +55 -55
- data/lib/cucumber/formatter/message.rb +22 -0
- data/lib/cucumber/formatter/message_builder.rb +255 -0
- data/lib/cucumber/formatter/pretty.rb +359 -153
- data/lib/cucumber/formatter/progress.rb +30 -32
- data/lib/cucumber/formatter/publish_banner_printer.rb +77 -0
- data/lib/cucumber/formatter/query/hook_by_test_step.rb +31 -0
- data/lib/cucumber/formatter/query/pickle_by_test.rb +26 -0
- data/lib/cucumber/formatter/query/pickle_step_by_test_step.rb +26 -0
- data/lib/cucumber/formatter/query/step_definitions_by_test_step.rb +40 -0
- data/lib/cucumber/formatter/query/test_case_started_by_test_case.rb +40 -0
- data/lib/cucumber/formatter/rerun.rb +22 -4
- data/lib/cucumber/formatter/stepdefs.rb +1 -2
- data/lib/cucumber/formatter/steps.rb +3 -4
- data/lib/cucumber/formatter/summary.rb +16 -8
- data/lib/cucumber/formatter/unicode.rb +15 -17
- data/lib/cucumber/formatter/url_reporter.rb +17 -0
- data/lib/cucumber/formatter/usage.rb +11 -10
- data/lib/cucumber/gherkin/data_table_parser.rb +17 -6
- data/lib/cucumber/gherkin/formatter/ansi_escapes.rb +13 -17
- data/lib/cucumber/gherkin/formatter/escaping.rb +2 -2
- data/lib/cucumber/gherkin/steps_parser.rb +17 -8
- data/lib/cucumber/glue/hook.rb +34 -11
- data/lib/cucumber/glue/invoke_in_world.rb +13 -18
- data/lib/cucumber/glue/proto_world.rb +42 -33
- data/lib/cucumber/glue/registry_and_more.rb +42 -12
- data/lib/cucumber/glue/snippet.rb +23 -22
- data/lib/cucumber/glue/step_definition.rb +42 -19
- data/lib/cucumber/glue/world_factory.rb +1 -1
- data/lib/cucumber/hooks.rb +11 -11
- data/lib/cucumber/multiline_argument/data_table/diff_matrices.rb +2 -2
- data/lib/cucumber/multiline_argument/data_table.rb +97 -64
- data/lib/cucumber/multiline_argument/doc_string.rb +1 -1
- data/lib/cucumber/multiline_argument.rb +4 -6
- data/lib/cucumber/platform.rb +3 -3
- data/lib/cucumber/rake/task.rb +16 -18
- data/lib/cucumber/rspec/disable_option_parser.rb +9 -8
- data/lib/cucumber/rspec/doubles.rb +3 -5
- data/lib/cucumber/running_test_case.rb +2 -53
- data/lib/cucumber/runtime/after_hooks.rb +8 -4
- data/lib/cucumber/runtime/before_hooks.rb +8 -4
- data/lib/cucumber/runtime/for_programming_languages.rb +4 -2
- data/lib/cucumber/runtime/step_hooks.rb +6 -2
- data/lib/cucumber/runtime/support_code.rb +13 -15
- data/lib/cucumber/runtime/user_interface.rb +6 -16
- data/lib/cucumber/runtime.rb +41 -58
- data/lib/cucumber/step_definition_light.rb +4 -3
- data/lib/cucumber/step_definitions.rb +2 -2
- data/lib/cucumber/step_match.rb +12 -11
- data/lib/cucumber/step_match_search.rb +2 -1
- data/lib/cucumber/term/ansicolor.rb +9 -9
- data/lib/cucumber/term/banner.rb +56 -0
- data/lib/cucumber/version +1 -1
- data/lib/cucumber.rb +1 -1
- metadata +253 -80
- data/lib/cucumber/formatter/cucumber.css +0 -286
- data/lib/cucumber/formatter/cucumber.sass +0 -247
- data/lib/cucumber/formatter/hook_query_visitor.rb +0 -42
- data/lib/cucumber/formatter/html_builder.rb +0 -121
- data/lib/cucumber/formatter/inline-js.js +0 -30
- data/lib/cucumber/formatter/jquery-min.js +0 -154
- data/lib/cucumber/formatter/json_pretty.rb +0 -11
- data/lib/cucumber/formatter/legacy_api/adapter.rb +0 -1028
- data/lib/cucumber/formatter/legacy_api/ast.rb +0 -394
- data/lib/cucumber/formatter/legacy_api/results.rb +0 -50
- data/lib/cucumber/formatter/legacy_api/runtime_facade.rb +0 -32
- data/lib/cucumber/step_argument.rb +0 -25
data/lib/cucumber/rake/task.rb
CHANGED
@@ -5,9 +5,7 @@ require 'cucumber/gherkin/formatter/ansi_escapes'
|
|
5
5
|
begin
|
6
6
|
# Support Rake > 0.8.7
|
7
7
|
require 'rake/dsl_definition'
|
8
|
-
# rubocop:disable Lint/HandleExceptions
|
9
8
|
rescue LoadError
|
10
|
-
# rubocop:enable Lint/HandleExceptions
|
11
9
|
end
|
12
10
|
|
13
11
|
module Cucumber
|
@@ -38,8 +36,8 @@ module Cucumber
|
|
38
36
|
attr_reader :args
|
39
37
|
|
40
38
|
def initialize(libs, cucumber_opts, feature_files)
|
41
|
-
raise 'libs must be an Array when running in-process' unless Array
|
42
|
-
libs.
|
39
|
+
raise 'libs must be an Array when running in-process' unless Array == libs.class
|
40
|
+
libs.reverse_each { |lib| $LOAD_PATH.unshift(lib) }
|
43
41
|
@args = (
|
44
42
|
cucumber_opts +
|
45
43
|
feature_files
|
@@ -65,11 +63,11 @@ module Cucumber
|
|
65
63
|
end
|
66
64
|
|
67
65
|
def load_path
|
68
|
-
[format('"
|
66
|
+
[format('"%<path>s"', path: @libs.join(File::PATH_SEPARATOR))]
|
69
67
|
end
|
70
68
|
|
71
69
|
def quoted_binary(cucumber_bin)
|
72
|
-
[format('"
|
70
|
+
[format('"%<path>s"', path: cucumber_bin)]
|
73
71
|
end
|
74
72
|
|
75
73
|
def use_bundler
|
@@ -98,9 +96,7 @@ module Cucumber
|
|
98
96
|
|
99
97
|
def run
|
100
98
|
sh cmd.join(' ') do |ok, res|
|
101
|
-
|
102
|
-
exit res.exitstatus
|
103
|
-
end
|
99
|
+
exit res.exitstatus unless ok
|
104
100
|
end
|
105
101
|
end
|
106
102
|
end
|
@@ -113,9 +109,9 @@ module Cucumber
|
|
113
109
|
|
114
110
|
# Extra options to pass to the cucumber binary. Can be overridden by the CUCUMBER_OPTS environment variable.
|
115
111
|
# It's recommended to pass an Array, but if it's a String it will be #split by ' '.
|
116
|
-
|
112
|
+
attr_reader :cucumber_opts
|
117
113
|
def cucumber_opts=(opts) #:nodoc:
|
118
|
-
@cucumber_opts = String
|
114
|
+
@cucumber_opts = String == opts.class ? opts.split(' ') : opts
|
119
115
|
end
|
120
116
|
|
121
117
|
# Whether or not to fork a new ruby interpreter. Defaults to true. You may gain
|
@@ -134,12 +130,16 @@ module Cucumber
|
|
134
130
|
# Note that this attribute has no effect if you don't run in forked mode.
|
135
131
|
attr_accessor :bundler
|
136
132
|
|
133
|
+
# Name of the running task
|
134
|
+
attr_reader :task_name
|
135
|
+
|
137
136
|
# Define Cucumber Rake task
|
138
137
|
def initialize(task_name = 'cucumber', desc = 'Run Cucumber features')
|
139
|
-
@task_name
|
138
|
+
@task_name = task_name
|
139
|
+
@desc = desc
|
140
140
|
@fork = true
|
141
141
|
@libs = ['lib']
|
142
|
-
@rcov_opts = %w
|
142
|
+
@rcov_opts = %w[--rails --exclude osx\/objc,gems\/]
|
143
143
|
yield self if block_given?
|
144
144
|
@binary = binary.nil? ? Cucumber::BINARY : File.expand_path(binary)
|
145
145
|
define_task
|
@@ -154,18 +154,16 @@ module Cucumber
|
|
154
154
|
|
155
155
|
def runner(_task_args = nil) #:nodoc:
|
156
156
|
cucumber_opts = [(ENV['CUCUMBER_OPTS'] ? ENV['CUCUMBER_OPTS'].split(/\s+/) : nil) || cucumber_opts_with_profile]
|
157
|
-
if
|
158
|
-
return ForkedCucumberRunner.new(libs, binary, cucumber_opts, bundler, feature_files)
|
159
|
-
end
|
157
|
+
return ForkedCucumberRunner.new(libs, binary, cucumber_opts, bundler, feature_files) if fork
|
160
158
|
InProcessCucumberRunner.new(libs, cucumber_opts, feature_files)
|
161
159
|
end
|
162
160
|
|
163
161
|
def cucumber_opts_with_profile #:nodoc:
|
164
|
-
Array(cucumber_opts).concat
|
162
|
+
Array(cucumber_opts).concat(Array(@profile).flat_map { |p| ['--profile', p] })
|
165
163
|
end
|
166
164
|
|
167
165
|
def feature_files #:nodoc:
|
168
|
-
make_command_line_safe(FileList[
|
166
|
+
make_command_line_safe(FileList[ENV['FEATURE'] || []])
|
169
167
|
end
|
170
168
|
|
171
169
|
def make_command_line_safe(list)
|
@@ -9,16 +9,17 @@ module Spec #:nodoc:
|
|
9
9
|
# will fail when running cucumber)
|
10
10
|
class OptionParser < ::OptionParser #:nodoc:
|
11
11
|
NEUTERED_RSPEC = Object.new
|
12
|
-
def NEUTERED_RSPEC.method_missing(
|
12
|
+
def NEUTERED_RSPEC.method_missing(_method, *_args) # rubocop:disable Style/MissingRespondToMissing
|
13
|
+
self || super
|
14
|
+
end
|
13
15
|
|
14
|
-
def self.method_added(
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
end
|
20
|
-
@__neutering_rspec = false
|
16
|
+
def self.method_added(method)
|
17
|
+
return if @__neutering_rspec
|
18
|
+
@__neutering_rspec = true
|
19
|
+
define_method(method) do |*_a|
|
20
|
+
NEUTERED_RSPEC
|
21
21
|
end
|
22
|
+
@__neutering_rspec = false
|
22
23
|
end
|
23
24
|
end
|
24
25
|
end
|
@@ -15,45 +15,12 @@ module Cucumber
|
|
15
15
|
# the passed / failed / undefined / skipped status of
|
16
16
|
# the test case.
|
17
17
|
#
|
18
|
-
# The test case might come from a regular Scenario or
|
19
|
-
# a Scenario outline. You can call the `#outline?`
|
20
|
-
# predicate to find out. If it's from an outline,
|
21
|
-
# you get a couple of extra methods.
|
22
18
|
module RunningTestCase
|
23
19
|
def self.new(test_case)
|
24
|
-
|
20
|
+
TestCase.new(test_case)
|
25
21
|
end
|
26
22
|
|
27
|
-
class
|
28
|
-
def initialize(test_case)
|
29
|
-
@test_case = test_case
|
30
|
-
test_case.describe_source_to(self)
|
31
|
-
end
|
32
|
-
|
33
|
-
def feature(feature)
|
34
|
-
end
|
35
|
-
|
36
|
-
def scenario(_scenario)
|
37
|
-
@factory = Scenario
|
38
|
-
end
|
39
|
-
|
40
|
-
def scenario_outline(_scenario)
|
41
|
-
@factory = ScenarioOutlineExample
|
42
|
-
end
|
43
|
-
|
44
|
-
def examples_table(examples_table)
|
45
|
-
end
|
46
|
-
|
47
|
-
def examples_table_row(row)
|
48
|
-
end
|
49
|
-
|
50
|
-
def running_test_case
|
51
|
-
@factory.new(@test_case)
|
52
|
-
end
|
53
|
-
end
|
54
|
-
private_constant :Builder
|
55
|
-
|
56
|
-
class Scenario < SimpleDelegator
|
23
|
+
class TestCase < SimpleDelegator
|
57
24
|
def initialize(test_case, result = Core::Test::Result::Unknown.new)
|
58
25
|
@test_case = test_case
|
59
26
|
@result = result
|
@@ -85,27 +52,9 @@ module Cucumber
|
|
85
52
|
tags.map &:name
|
86
53
|
end
|
87
54
|
|
88
|
-
def outline?
|
89
|
-
false
|
90
|
-
end
|
91
|
-
|
92
55
|
def with_result(result)
|
93
56
|
self.class.new(@test_case, result)
|
94
57
|
end
|
95
58
|
end
|
96
|
-
|
97
|
-
class ScenarioOutlineExample < Scenario
|
98
|
-
def outline?
|
99
|
-
true
|
100
|
-
end
|
101
|
-
|
102
|
-
def scenario_outline
|
103
|
-
self
|
104
|
-
end
|
105
|
-
|
106
|
-
def cell_values
|
107
|
-
source.last.values
|
108
|
-
end
|
109
|
-
end
|
110
59
|
end
|
111
60
|
end
|
@@ -3,23 +3,27 @@
|
|
3
3
|
module Cucumber
|
4
4
|
class Runtime
|
5
5
|
class AfterHooks
|
6
|
-
def initialize(hooks, scenario)
|
6
|
+
def initialize(id_generator, hooks, scenario, event_bus)
|
7
7
|
@hooks = hooks
|
8
8
|
@scenario = scenario
|
9
|
+
@id_generator = id_generator
|
10
|
+
@event_bus = event_bus
|
9
11
|
end
|
10
12
|
|
11
13
|
def apply_to(test_case)
|
12
14
|
test_case.with_steps(
|
13
|
-
test_case.test_steps + after_hooks
|
15
|
+
test_case.test_steps + after_hooks.reverse
|
14
16
|
)
|
15
17
|
end
|
16
18
|
|
17
19
|
private
|
18
20
|
|
19
|
-
def after_hooks
|
21
|
+
def after_hooks
|
20
22
|
@hooks.map do |hook|
|
21
23
|
action = ->(result) { hook.invoke('After', @scenario.with_result(result)) }
|
22
|
-
Hooks.after_hook(
|
24
|
+
hook_step = Hooks.after_hook(@id_generator.new_id, hook.location, &action)
|
25
|
+
@event_bus.hook_test_step_created(hook_step, hook)
|
26
|
+
hook_step
|
23
27
|
end
|
24
28
|
end
|
25
29
|
end
|
@@ -5,23 +5,27 @@ require 'cucumber/hooks'
|
|
5
5
|
module Cucumber
|
6
6
|
class Runtime
|
7
7
|
class BeforeHooks
|
8
|
-
def initialize(hooks, scenario)
|
8
|
+
def initialize(id_generator, hooks, scenario, event_bus)
|
9
9
|
@hooks = hooks
|
10
10
|
@scenario = scenario
|
11
|
+
@id_generator = id_generator
|
12
|
+
@event_bus = event_bus
|
11
13
|
end
|
12
14
|
|
13
15
|
def apply_to(test_case)
|
14
16
|
test_case.with_steps(
|
15
|
-
before_hooks
|
17
|
+
before_hooks + test_case.test_steps
|
16
18
|
)
|
17
19
|
end
|
18
20
|
|
19
21
|
private
|
20
22
|
|
21
|
-
def before_hooks
|
23
|
+
def before_hooks
|
22
24
|
@hooks.map do |hook|
|
23
25
|
action_block = ->(result) { hook.invoke('Before', @scenario.with_result(result)) }
|
24
|
-
Hooks.before_hook(
|
26
|
+
hook_step = Hooks.before_hook(@id_generator.new_id, hook.location, &action_block)
|
27
|
+
@event_bus.hook_test_step_created(hook_step, hook)
|
28
|
+
hook_step
|
25
29
|
end
|
26
30
|
end
|
27
31
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'forwardable'
|
4
|
-
require 'cucumber/core/
|
4
|
+
require 'cucumber/core/test/doc_string'
|
5
5
|
|
6
6
|
module Cucumber
|
7
7
|
class Runtime
|
@@ -15,11 +15,13 @@ module Cucumber
|
|
15
15
|
attr_reader :support_code
|
16
16
|
|
17
17
|
def initialize(support_code, user_interface)
|
18
|
-
@support_code
|
18
|
+
@support_code = support_code
|
19
|
+
@user_interface = user_interface
|
19
20
|
end
|
20
21
|
|
21
22
|
def_delegators :@user_interface,
|
22
23
|
:embed,
|
24
|
+
:attach,
|
23
25
|
:ask,
|
24
26
|
:puts,
|
25
27
|
:features_paths,
|
@@ -3,8 +3,10 @@
|
|
3
3
|
module Cucumber
|
4
4
|
class Runtime
|
5
5
|
class StepHooks
|
6
|
-
def initialize(hooks)
|
6
|
+
def initialize(id_generator, hooks, event_bus)
|
7
7
|
@hooks = hooks
|
8
|
+
@id_generator = id_generator
|
9
|
+
@event_bus = event_bus
|
8
10
|
end
|
9
11
|
|
10
12
|
def apply(test_steps)
|
@@ -18,7 +20,9 @@ module Cucumber
|
|
18
20
|
def after_step_hooks(test_step)
|
19
21
|
@hooks.map do |hook|
|
20
22
|
action = ->(*args) { hook.invoke('AfterStep', [args, test_step]) }
|
21
|
-
Hooks.after_step_hook(
|
23
|
+
hook_step = Hooks.after_step_hook(@id_generator.new_id, test_step, hook.location, &action)
|
24
|
+
@event_bus.hook_test_step_created(hook_step, hook)
|
25
|
+
hook_step
|
22
26
|
end
|
23
27
|
end
|
24
28
|
end
|
@@ -22,19 +22,15 @@ module Cucumber
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def step(step)
|
25
|
-
location = Core::
|
25
|
+
location = Core::Test::Location.of_caller
|
26
26
|
@support_code.invoke_dynamic_step(step[:text], multiline_arg(step, location))
|
27
27
|
end
|
28
28
|
|
29
29
|
def multiline_arg(step, location)
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
MultilineArgument.from(argument[:content], location, argument[:content_type])
|
35
|
-
else
|
36
|
-
MultilineArgument::DataTable.from(argument[:rows].map { |row| row[:cells].map { |cell| cell[:value] } })
|
37
|
-
end
|
30
|
+
if !step[:doc_string].nil?
|
31
|
+
MultilineArgument.from(step[:doc_string][:content], location, step[:doc_string][:content_type])
|
32
|
+
elsif !step[:data_table].nil?
|
33
|
+
MultilineArgument::DataTable.from(step[:data_table][:rows].map { |row| row[:cells].map { |cell| cell[:value] } })
|
38
34
|
else
|
39
35
|
MultilineArgument.from(nil)
|
40
36
|
end
|
@@ -62,8 +58,8 @@ module Cucumber
|
|
62
58
|
# Given I have 8 cukes in my belly
|
63
59
|
# Then I should not be thirsty
|
64
60
|
# })
|
65
|
-
def invoke_dynamic_steps(steps_text,
|
66
|
-
parser = Cucumber::Gherkin::StepsParser.new(StepInvoker.new(self),
|
61
|
+
def invoke_dynamic_steps(steps_text, iso_code, _location)
|
62
|
+
parser = Cucumber::Gherkin::StepsParser.new(StepInvoker.new(self), iso_code)
|
67
63
|
parser.parse(steps_text)
|
68
64
|
end
|
69
65
|
|
@@ -108,26 +104,28 @@ module Cucumber
|
|
108
104
|
def find_after_step_hooks(test_case)
|
109
105
|
scenario = RunningTestCase.new(test_case)
|
110
106
|
hooks = registry.hooks_for(:after_step, scenario)
|
111
|
-
StepHooks.new hooks
|
107
|
+
StepHooks.new(@configuration.id_generator, hooks, @configuration.event_bus)
|
112
108
|
end
|
113
109
|
|
114
110
|
def apply_before_hooks(test_case)
|
111
|
+
return test_case if test_case.test_steps.empty?
|
115
112
|
scenario = RunningTestCase.new(test_case)
|
116
113
|
hooks = registry.hooks_for(:before, scenario)
|
117
|
-
BeforeHooks.new(hooks, scenario).apply_to(test_case)
|
114
|
+
BeforeHooks.new(@configuration.id_generator, hooks, scenario, @configuration.event_bus).apply_to(test_case)
|
118
115
|
end
|
119
116
|
|
120
117
|
def apply_after_hooks(test_case)
|
118
|
+
return test_case if test_case.test_steps.empty?
|
121
119
|
scenario = RunningTestCase.new(test_case)
|
122
120
|
hooks = registry.hooks_for(:after, scenario)
|
123
|
-
AfterHooks.new(hooks, scenario).apply_to(test_case)
|
121
|
+
AfterHooks.new(@configuration.id_generator, hooks, scenario, @configuration.event_bus).apply_to(test_case)
|
124
122
|
end
|
125
123
|
|
126
124
|
def find_around_hooks(test_case)
|
127
125
|
scenario = RunningTestCase.new(test_case)
|
128
126
|
|
129
127
|
registry.hooks_for(:around, scenario).map do |hook|
|
130
|
-
Hooks.around_hook
|
128
|
+
Hooks.around_hook do |run_scenario|
|
131
129
|
hook.invoke('Around', scenario, &run_scenario)
|
132
130
|
end
|
133
131
|
end
|
@@ -7,14 +7,6 @@ module Cucumber
|
|
7
7
|
module UserInterface
|
8
8
|
attr_writer :visitor
|
9
9
|
|
10
|
-
# Output +messages+ alongside the formatted output.
|
11
|
-
# This is an alternative to using Kernel#puts - it will display
|
12
|
-
# nicer, and in all outputs (in case you use several formatters)
|
13
|
-
#
|
14
|
-
def puts(*messages)
|
15
|
-
@visitor.puts(*messages)
|
16
|
-
end
|
17
|
-
|
18
10
|
# Suspends execution and prompts +question+ to the console (STDOUT).
|
19
11
|
# An operator (manual tester) can then enter a line of text and hit
|
20
12
|
# <ENTER>. The entered text is returned, and both +question+ and
|
@@ -48,20 +40,18 @@ module Cucumber
|
|
48
40
|
# be a path to a file, or if it's an image it may also be a Base64 encoded image.
|
49
41
|
# The embedded data may or may not be ignored, depending on what kind of formatter(s) are active.
|
50
42
|
#
|
51
|
-
def
|
52
|
-
@visitor.
|
43
|
+
def attach(src, media_type)
|
44
|
+
@visitor.attach(src, media_type)
|
53
45
|
end
|
54
46
|
|
55
47
|
private
|
56
48
|
|
57
49
|
def mri_gets(timeout_seconds)
|
58
|
-
|
59
|
-
|
60
|
-
STDIN.gets
|
61
|
-
end
|
62
|
-
rescue Timeout::Error
|
63
|
-
nil
|
50
|
+
Timeout.timeout(timeout_seconds) do
|
51
|
+
STDIN.gets
|
64
52
|
end
|
53
|
+
rescue Timeout::Error
|
54
|
+
nil
|
65
55
|
end
|
66
56
|
|
67
57
|
def jruby_gets(timeout_seconds)
|
data/lib/cucumber/runtime.rb
CHANGED
@@ -1,9 +1,8 @@
|
|
1
|
-
# -*- coding: utf-8 -*-
|
2
1
|
# frozen_string_literal: true
|
3
2
|
|
4
3
|
require 'fileutils'
|
5
|
-
require 'multi_json'
|
6
4
|
require 'cucumber/configuration'
|
5
|
+
require 'cucumber/create_meta'
|
7
6
|
require 'cucumber/load_path'
|
8
7
|
require 'cucumber/formatter/duration'
|
9
8
|
require 'cucumber/file_specs'
|
@@ -11,6 +10,8 @@ require 'cucumber/filters'
|
|
11
10
|
require 'cucumber/formatter/fanout'
|
12
11
|
require 'cucumber/gherkin/i18n'
|
13
12
|
require 'cucumber/step_match_search'
|
13
|
+
require 'cucumber/messages'
|
14
|
+
require 'sys/uname'
|
14
15
|
|
15
16
|
module Cucumber
|
16
17
|
module FixRuby21Bug9285
|
@@ -19,8 +20,8 @@ module Cucumber
|
|
19
20
|
end
|
20
21
|
end
|
21
22
|
|
22
|
-
class FileException <
|
23
|
-
|
23
|
+
class FileException < RuntimeError
|
24
|
+
attr_reader :path
|
24
25
|
|
25
26
|
def initialize(original_exception, path)
|
26
27
|
super(original_exception)
|
@@ -31,7 +32,7 @@ module Cucumber
|
|
31
32
|
class FileNotFoundException < FileException
|
32
33
|
end
|
33
34
|
|
34
|
-
class FeatureFolderNotFoundException <
|
35
|
+
class FeatureFolderNotFoundException < RuntimeError
|
35
36
|
def initialize(path)
|
36
37
|
@path = path
|
37
38
|
end
|
@@ -54,7 +55,6 @@ module Cucumber
|
|
54
55
|
def initialize(configuration = Configuration.default)
|
55
56
|
@configuration = Configuration.new(configuration)
|
56
57
|
@support_code = SupportCode.new(self, @configuration)
|
57
|
-
@results = Formatter::LegacyApi::Results.new
|
58
58
|
end
|
59
59
|
|
60
60
|
# Allows you to take an existing runtime and change its configuration
|
@@ -65,6 +65,10 @@ module Cucumber
|
|
65
65
|
|
66
66
|
require 'cucumber/wire/plugin'
|
67
67
|
def run!
|
68
|
+
@configuration.notify :envelope, Cucumber::Messages::Envelope.new(
|
69
|
+
meta: Cucumber::CreateMeta.create_meta('cucumber-ruby', Cucumber::VERSION)
|
70
|
+
)
|
71
|
+
|
68
72
|
load_step_definitions
|
69
73
|
install_wire_plugin
|
70
74
|
fire_after_configuration_hook
|
@@ -72,7 +76,7 @@ module Cucumber
|
|
72
76
|
self.visitor = report
|
73
77
|
|
74
78
|
receiver = Test::Runner.new(@configuration.event_bus)
|
75
|
-
compile features, receiver, filters
|
79
|
+
compile features, receiver, filters, @configuration.event_bus
|
76
80
|
@configuration.notify :test_run_finished
|
77
81
|
end
|
78
82
|
|
@@ -84,14 +88,6 @@ module Cucumber
|
|
84
88
|
@configuration.dry_run?
|
85
89
|
end
|
86
90
|
|
87
|
-
def scenarios(status = nil)
|
88
|
-
@results.scenarios(status)
|
89
|
-
end
|
90
|
-
|
91
|
-
def steps(status = nil)
|
92
|
-
@results.steps(status)
|
93
|
-
end
|
94
|
-
|
95
91
|
def unmatched_step_definitions
|
96
92
|
@support_code.unmatched_step_definitions
|
97
93
|
end
|
@@ -107,13 +103,12 @@ module Cucumber
|
|
107
103
|
# Returns Ast::DocString for +string_without_triple_quotes+.
|
108
104
|
#
|
109
105
|
def doc_string(string_without_triple_quotes, content_type = '', _line_offset = 0)
|
110
|
-
|
111
|
-
Core::Ast::DocString.new(string_without_triple_quotes, content_type, location)
|
106
|
+
Core::Test::DocString.new(string_without_triple_quotes, content_type)
|
112
107
|
end
|
113
108
|
|
114
109
|
private
|
115
110
|
|
116
|
-
def fire_after_configuration_hook #:nodoc
|
111
|
+
def fire_after_configuration_hook #:nodoc:
|
117
112
|
@support_code.fire_hook(:after_configuration, @configuration)
|
118
113
|
end
|
119
114
|
|
@@ -143,14 +138,12 @@ module Cucumber
|
|
143
138
|
end
|
144
139
|
|
145
140
|
def initialize(path)
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
raise FeatureFolderNotFoundException.new(path)
|
153
|
-
end
|
141
|
+
@file = File.new(path)
|
142
|
+
set_encoding
|
143
|
+
rescue Errno::EACCES => e
|
144
|
+
raise FileNotFoundException.new(e, File.expand_path(path))
|
145
|
+
rescue Errno::ENOENT
|
146
|
+
raise FeatureFolderNotFoundException, path
|
154
147
|
end
|
155
148
|
|
156
149
|
def read
|
@@ -162,7 +155,7 @@ module Cucumber
|
|
162
155
|
def set_encoding
|
163
156
|
@file.each do |line|
|
164
157
|
if ENCODING_PATTERN =~ line
|
165
|
-
@file.set_encoding
|
158
|
+
@file.set_encoding Regexp.last_match(1)
|
166
159
|
break
|
167
160
|
end
|
168
161
|
break unless COMMENT_OR_EMPTY_LINE_PATTERN =~ line
|
@@ -171,16 +164,16 @@ module Cucumber
|
|
171
164
|
end
|
172
165
|
end
|
173
166
|
|
174
|
-
require 'cucumber/formatter/legacy_api/adapter'
|
175
|
-
require 'cucumber/formatter/legacy_api/runtime_facade'
|
176
|
-
require 'cucumber/formatter/legacy_api/results'
|
177
167
|
require 'cucumber/formatter/ignore_missing_messages'
|
178
168
|
require 'cucumber/formatter/fail_fast'
|
169
|
+
require 'cucumber/formatter/publish_banner_printer'
|
179
170
|
require 'cucumber/core/report/summary'
|
171
|
+
|
180
172
|
def report
|
181
173
|
return @report if @report
|
182
174
|
reports = [summary_report] + formatters
|
183
175
|
reports << fail_fast_report if @configuration.fail_fast?
|
176
|
+
reports << publish_banner_printer unless @configuration.publish_quiet?
|
184
177
|
@report ||= Formatter::Fanout.new(reports)
|
185
178
|
end
|
186
179
|
|
@@ -192,41 +185,32 @@ module Cucumber
|
|
192
185
|
@fail_fast_report ||= Formatter::FailFast.new(@configuration)
|
193
186
|
end
|
194
187
|
|
188
|
+
def publish_banner_printer
|
189
|
+
@publish_banner_printer ||= Formatter::PublishBannerPrinter.new(@configuration)
|
190
|
+
end
|
191
|
+
|
195
192
|
def formatters
|
196
193
|
@formatters ||=
|
197
|
-
@configuration.formatter_factories do |factory, formatter_options, path_or_io
|
198
|
-
create_formatter(factory, formatter_options, path_or_io
|
194
|
+
@configuration.formatter_factories do |factory, formatter_options, path_or_io|
|
195
|
+
create_formatter(factory, formatter_options, path_or_io)
|
199
196
|
end
|
200
197
|
end
|
201
198
|
|
202
|
-
def create_formatter(factory, formatter_options, path_or_io
|
203
|
-
if
|
204
|
-
if
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
return factory.new(@configuration.with_options(out_stream: path_or_io))
|
211
|
-
end
|
199
|
+
def create_formatter(factory, formatter_options, path_or_io)
|
200
|
+
if accept_options?(factory)
|
201
|
+
return factory.new(@configuration, formatter_options) if path_or_io.nil?
|
202
|
+
factory.new(@configuration.with_options(out_stream: path_or_io),
|
203
|
+
formatter_options)
|
204
|
+
else
|
205
|
+
return factory.new(@configuration) if path_or_io.nil?
|
206
|
+
factory.new(@configuration.with_options(out_stream: path_or_io))
|
212
207
|
end
|
213
|
-
results = Formatter::LegacyApi::Results.new
|
214
|
-
runtime_facade = Formatter::LegacyApi::RuntimeFacade.new(results, @support_code, @configuration)
|
215
|
-
formatter = factory.new(runtime_facade, path_or_io, cli_options)
|
216
|
-
Formatter::LegacyApi::Adapter.new(
|
217
|
-
Formatter::IgnoreMissingMessages.new(formatter),
|
218
|
-
results, @configuration
|
219
|
-
)
|
220
208
|
end
|
221
209
|
|
222
210
|
def accept_options?(factory)
|
223
211
|
factory.instance_method(:initialize).arity > 1
|
224
212
|
end
|
225
213
|
|
226
|
-
def legacy_formatter?(factory)
|
227
|
-
factory.instance_method(:initialize).arity > 2
|
228
|
-
end
|
229
|
-
|
230
214
|
def failure?
|
231
215
|
if @configuration.wip?
|
232
216
|
summary_report.test_cases.total_passed > 0
|
@@ -237,7 +221,7 @@ module Cucumber
|
|
237
221
|
public :failure?
|
238
222
|
|
239
223
|
require 'cucumber/core/test/filters'
|
240
|
-
def filters
|
224
|
+
def filters # rubocop:disable Metrics/AbcSize
|
241
225
|
tag_expressions = @configuration.tag_expressions
|
242
226
|
name_regexps = @configuration.name_regexps
|
243
227
|
tag_limits = @configuration.tag_limits
|
@@ -250,14 +234,13 @@ module Cucumber
|
|
250
234
|
# TODO: can we just use Glue::RegistryAndMore's step definitions directly?
|
251
235
|
step_match_search = StepMatchSearch.new(@support_code.registry.method(:step_matches), @configuration)
|
252
236
|
filters << Filters::ActivateSteps.new(step_match_search, @configuration)
|
253
|
-
@configuration.filters.each
|
254
|
-
filters << filter
|
255
|
-
end
|
237
|
+
@configuration.filters.each { |filter| filters << filter }
|
256
238
|
unless configuration.dry_run?
|
257
239
|
filters << Filters::ApplyAfterStepHooks.new(@support_code)
|
258
240
|
filters << Filters::ApplyBeforeHooks.new(@support_code)
|
259
241
|
filters << Filters::ApplyAfterHooks.new(@support_code)
|
260
242
|
filters << Filters::ApplyAroundHooks.new(@support_code)
|
243
|
+
filters << Filters::BroadcastTestCaseReadyEvent.new(@configuration)
|
261
244
|
filters << Filters::BroadcastTestRunStartedEvent.new(@configuration)
|
262
245
|
filters << Filters::Quit.new
|
263
246
|
filters << Filters::Retry.new(@configuration)
|
@@ -273,7 +256,7 @@ module Cucumber
|
|
273
256
|
end
|
274
257
|
|
275
258
|
def install_wire_plugin
|
276
|
-
Cucumber::Wire::Plugin.new(@configuration).install if @configuration.all_files_to_load.any? { |f| f =~
|
259
|
+
Cucumber::Wire::Plugin.new(@configuration, @support_code.registry).install if @configuration.all_files_to_load.any? { |f| f =~ /\.wire$/ }
|
277
260
|
end
|
278
261
|
|
279
262
|
def log
|