cucumber 2.0.0.beta.3 → 2.0.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/.travis.yml +3 -3
- data/History.md +131 -32
- data/Rakefile +0 -2
- data/cucumber.gemspec +4 -3
- data/examples/i18n/ht/Rakefile +6 -0
- data/examples/i18n/ht/features/adisyon.feature +17 -0
- data/examples/i18n/ht/features/divizyon.feature +10 -0
- data/examples/i18n/ht/features/step_definitions/kalkilatris_steps.rb +25 -0
- data/examples/i18n/ht/lib/kalkilatris.rb +14 -0
- data/examples/tcl/features/step_definitions/fib_steps.rb +1 -1
- data/features/docs/cli/dry_run.feature +48 -0
- data/features/docs/cli/exclude_files.feature +1 -2
- data/features/docs/cli/run_specific_scenarios.feature +28 -66
- data/features/docs/cli/strict_mode.feature +24 -1
- data/features/docs/defining_steps/nested_steps.feature +49 -0
- data/features/docs/defining_steps/skip_scenario.feature +31 -2
- data/features/docs/defining_steps/snippets.feature +15 -0
- data/features/docs/exception_in_after_step_hook.feature +1 -1
- data/features/docs/exception_in_around_hook.feature +80 -0
- data/features/docs/extending_cucumber/custom_filter.feature +29 -0
- data/features/docs/extending_cucumber/custom_formatter.feature +65 -7
- data/features/docs/formatters/debug_formatter.feature +24 -17
- data/features/docs/formatters/json_formatter.feature +65 -1
- data/features/docs/formatters/junit_formatter.feature +40 -0
- data/features/docs/formatters/pretty_formatter.feature +42 -0
- data/features/docs/formatters/rerun_formatter.feature +3 -2
- data/features/docs/getting_started.feature +1 -1
- data/features/docs/{wire_protocol_erb.feature → wire_protocol/erb_configuration.feature} +2 -2
- data/features/docs/wire_protocol/handle_unexpected_response.feature +30 -0
- data/features/docs/wire_protocol/invoke_message.feature +216 -0
- data/features/docs/wire_protocol/readme.md +26 -0
- data/features/docs/wire_protocol/snippets_message.feature +51 -0
- data/features/docs/wire_protocol/step_matches_message.feature +81 -0
- data/features/docs/{wire_protocol_table_diffing.feature → wire_protocol/table_diffing.feature} +1 -0
- data/features/docs/{wire_protocol_tags.feature → wire_protocol/tags.feature} +1 -0
- data/features/docs/{wire_protocol_timeouts.feature → wire_protocol/timeouts.feature} +1 -0
- data/features/docs/work_in_progress.feature +1 -1
- data/features/docs/writing_support_code/after_hooks.feature +24 -0
- data/features/docs/writing_support_code/around_hooks.feature +31 -0
- data/features/docs/writing_support_code/before_hook.feature +7 -3
- data/features/docs/writing_support_code/tagged_hooks.feature +44 -6
- data/features/lib/step_definitions/wire_steps.rb +18 -1
- data/features/lib/support/fake_wire_server.rb +10 -7
- data/lib/cucumber/cli/configuration.rb +6 -11
- data/lib/cucumber/cli/main.rb +2 -2
- data/lib/cucumber/cli/options.rb +8 -1
- data/lib/cucumber/cli/profile_loader.rb +1 -1
- data/lib/cucumber/core_ext/instance_exec.rb +1 -1
- data/lib/cucumber/encoding.rb +5 -0
- data/lib/cucumber/errors.rb +8 -0
- data/lib/cucumber/file_specs.rb +3 -1
- data/lib/cucumber/filters/activate_steps.rb +33 -0
- data/lib/cucumber/filters/apply_after_hooks.rb +9 -0
- data/lib/cucumber/filters/apply_after_step_hooks.rb +12 -0
- data/lib/cucumber/filters/apply_around_hooks.rb +12 -0
- data/lib/cucumber/filters/apply_before_hooks.rb +9 -0
- data/lib/cucumber/{runtime → filters}/gated_receiver.rb +5 -1
- data/lib/cucumber/filters/prepare_world.rb +45 -0
- data/lib/cucumber/filters/quit.rb +28 -0
- data/lib/cucumber/filters/randomizer.rb +40 -0
- data/lib/cucumber/{runtime → filters}/tag_limits/test_case_index.rb +4 -2
- data/lib/cucumber/{runtime → filters}/tag_limits/verifier.rb +4 -2
- data/lib/cucumber/filters/tag_limits.rb +45 -0
- data/lib/cucumber/filters.rb +9 -0
- data/lib/cucumber/formatter/ansicolor.rb +0 -8
- data/lib/cucumber/formatter/console.rb +37 -20
- data/lib/cucumber/formatter/debug.rb +1 -8
- data/lib/cucumber/formatter/fanout.rb +27 -0
- data/lib/cucumber/formatter/gherkin_formatter_adapter.rb +10 -9
- data/lib/cucumber/formatter/html.rb +31 -6
- data/lib/cucumber/formatter/ignore_missing_messages.rb +20 -0
- data/lib/cucumber/formatter/junit.rb +97 -2
- data/lib/cucumber/formatter/legacy_api/adapter.rb +1060 -0
- data/lib/cucumber/formatter/legacy_api/ast.rb +376 -0
- data/lib/cucumber/formatter/legacy_api/results.rb +51 -0
- data/lib/cucumber/formatter/legacy_api/runtime_facade.rb +30 -0
- data/lib/cucumber/formatter/pretty.rb +14 -0
- data/lib/cucumber/formatter/progress.rb +10 -0
- data/lib/cucumber/formatter/rerun.rb +14 -88
- data/lib/cucumber/hooks.rb +97 -0
- data/lib/cucumber/language_support/language_methods.rb +0 -54
- data/lib/cucumber/multiline_argument/data_table.rb +41 -29
- data/lib/cucumber/platform.rb +3 -3
- data/lib/cucumber/project_initializer.rb +43 -0
- data/lib/cucumber/rb_support/rb_hook.rb +2 -2
- data/lib/cucumber/rb_support/rb_step_definition.rb +11 -2
- data/lib/cucumber/rb_support/rb_transform.rb +3 -1
- data/lib/cucumber/rb_support/rb_world.rb +2 -2
- data/lib/cucumber/rb_support/snippet.rb +1 -1
- data/lib/cucumber/rspec/doubles.rb +1 -1
- data/lib/cucumber/running_test_case.rb +115 -0
- data/lib/cucumber/runtime/after_hooks.rb +24 -0
- data/lib/cucumber/runtime/before_hooks.rb +23 -0
- data/lib/cucumber/runtime/for_programming_languages.rb +4 -8
- data/lib/cucumber/runtime/step_hooks.rb +22 -0
- data/lib/cucumber/runtime/support_code.rb +70 -5
- data/lib/cucumber/runtime.rb +56 -112
- data/lib/cucumber/step_match.rb +26 -2
- data/lib/cucumber.rb +7 -3
- data/spec/cucumber/cli/configuration_spec.rb +16 -1
- data/spec/cucumber/cli/profile_loader_spec.rb +10 -0
- data/spec/cucumber/core_ext/instance_exec_spec.rb +4 -0
- data/spec/cucumber/file_specs_spec.rb +21 -2
- data/spec/cucumber/filters/activate_steps_spec.rb +57 -0
- data/spec/cucumber/{runtime → filters}/gated_receiver_spec.rb +3 -3
- data/spec/cucumber/{runtime → filters}/tag_limits/test_case_index_spec.rb +3 -3
- data/spec/cucumber/{runtime → filters}/tag_limits/verifier_spec.rb +4 -4
- data/spec/cucumber/{runtime/tag_limits/filter_spec.rb → filters/tag_limits_spec.rb} +6 -6
- data/spec/cucumber/formatter/debug_spec.rb +25 -530
- data/spec/cucumber/formatter/html_spec.rb +140 -0
- data/spec/cucumber/formatter/junit_spec.rb +212 -156
- data/spec/cucumber/formatter/legacy_api/adapter_spec.rb +2090 -0
- data/spec/cucumber/formatter/pretty_spec.rb +248 -2
- data/spec/cucumber/formatter/rerun_spec.rb +107 -0
- data/spec/cucumber/formatter/spec_helper.rb +17 -8
- data/spec/cucumber/hooks_spec.rb +30 -0
- data/spec/cucumber/multiline_argument/data_table_spec.rb +53 -47
- data/spec/cucumber/project_initializer_spec.rb +87 -0
- data/spec/cucumber/rb_support/rb_language_spec.rb +2 -2
- data/spec/cucumber/rb_support/rb_step_definition_spec.rb +32 -7
- data/spec/cucumber/rb_support/rb_transform_spec.rb +20 -0
- data/spec/cucumber/rb_support/snippet_spec.rb +6 -6
- data/spec/cucumber/running_test_case_spec.rb +83 -0
- data/spec/cucumber/runtime_spec.rb +1 -5
- data/spec/spec_helper.rb +3 -4
- metadata +149 -107
- data/bin/cuke +0 -60
- data/features/docs/extending_cucumber/formatter_callbacks.feature +0 -370
- data/features/docs/output_from_hooks.feature +0 -128
- data/features/docs/report_called_undefined_steps.feature +0 -57
- data/features/docs/wire_protocol.feature +0 -337
- data/gem_tasks/yard/default/layout/html/bubble_32x32.png +0 -0
- data/gem_tasks/yard/default/layout/html/footer.erb +0 -5
- data/gem_tasks/yard/default/layout/html/index.erb +0 -1
- data/gem_tasks/yard/default/layout/html/layout.erb +0 -25
- data/gem_tasks/yard/default/layout/html/logo.erb +0 -1
- data/gem_tasks/yard/default/layout/html/setup.rb +0 -4
- data/gem_tasks/yard.rake +0 -43
- data/lib/cucumber/mappings.rb +0 -238
- data/lib/cucumber/reports/legacy_formatter.rb +0 -1349
- data/lib/cucumber/runtime/results.rb +0 -64
- data/lib/cucumber/runtime/tag_limits/filter.rb +0 -31
- data/lib/cucumber/runtime/tag_limits.rb +0 -15
- data/spec/cucumber/mappings_spec.rb +0 -180
- data/spec/cucumber/reports/legacy_formatter_spec.rb +0 -1860
- data/spec/cucumber/runtime/results_spec.rb +0 -88
|
@@ -66,10 +66,6 @@ module Cucumber
|
|
|
66
66
|
@options[:snippet_type] || :regexp
|
|
67
67
|
end
|
|
68
68
|
|
|
69
|
-
def build_tree_walker(runtime)
|
|
70
|
-
Ast::TreeWalker.new(runtime, formatters(runtime), self)
|
|
71
|
-
end
|
|
72
|
-
|
|
73
69
|
def formatter_class(format)
|
|
74
70
|
if(builtin = Options::BUILTIN_FORMATS[format])
|
|
75
71
|
constantize(builtin[0])
|
|
@@ -111,7 +107,7 @@ module Cucumber
|
|
|
111
107
|
Dir["#{path}/**/*.feature"].sort
|
|
112
108
|
elsif path[0..0] == '@' and # @listfile.txt
|
|
113
109
|
File.file?(path[1..-1]) # listfile.txt is a file
|
|
114
|
-
IO.read(path[1..-1]).split
|
|
110
|
+
IO.read(path[1..-1]).split(/(.*?\.feature.*?) /).collect(&:strip).reject(&:empty?)
|
|
115
111
|
else
|
|
116
112
|
path
|
|
117
113
|
end
|
|
@@ -151,7 +147,6 @@ module Cucumber
|
|
|
151
147
|
@options[:name_regexps]
|
|
152
148
|
end
|
|
153
149
|
|
|
154
|
-
# todo: remove as unused
|
|
155
150
|
def filters
|
|
156
151
|
@options.filters
|
|
157
152
|
end
|
|
@@ -169,13 +164,13 @@ module Cucumber
|
|
|
169
164
|
@options[:paths]
|
|
170
165
|
end
|
|
171
166
|
|
|
172
|
-
def
|
|
167
|
+
def formatter_factories
|
|
173
168
|
@options[:formats].map do |format_and_out|
|
|
174
169
|
format = format_and_out[0]
|
|
175
170
|
path_or_io = format_and_out[1]
|
|
176
171
|
begin
|
|
177
|
-
|
|
178
|
-
|
|
172
|
+
factory = formatter_class(format)
|
|
173
|
+
yield factory, path_or_io, @options
|
|
179
174
|
rescue Exception => e
|
|
180
175
|
e.message << "\nError creating formatter: #{format}"
|
|
181
176
|
raise e
|
|
@@ -183,7 +178,8 @@ module Cucumber
|
|
|
183
178
|
end
|
|
184
179
|
end
|
|
185
180
|
|
|
186
|
-
|
|
181
|
+
private
|
|
182
|
+
|
|
187
183
|
def with_default_features_path(paths)
|
|
188
184
|
return ['features'] if paths.empty?
|
|
189
185
|
paths
|
|
@@ -195,7 +191,6 @@ module Cucumber
|
|
|
195
191
|
end
|
|
196
192
|
end
|
|
197
193
|
|
|
198
|
-
|
|
199
194
|
def set_environment_variables
|
|
200
195
|
@options[:env_vars].each do |var, value|
|
|
201
196
|
ENV[var] = value
|
data/lib/cucumber/cli/main.rb
CHANGED
|
@@ -36,14 +36,14 @@ module Cucumber
|
|
|
36
36
|
end
|
|
37
37
|
|
|
38
38
|
runtime.run!
|
|
39
|
-
failure = runtime.
|
|
39
|
+
failure = runtime.failure? || Cucumber.wants_to_quit
|
|
40
40
|
@kernel.exit(failure ? 1 : 0)
|
|
41
41
|
rescue FileNotFoundException => e
|
|
42
42
|
@err.puts(e.message)
|
|
43
43
|
@err.puts("Couldn't open #{e.path}")
|
|
44
44
|
@kernel.exit(1)
|
|
45
45
|
rescue FeatureFolderNotFoundException => e
|
|
46
|
-
@err.puts(e.message + ".
|
|
46
|
+
@err.puts(e.message + ". You can use `cucumber --init` to get started.")
|
|
47
47
|
@kernel.exit(1)
|
|
48
48
|
rescue ProfilesNotDefinedError, YmlLoadError, ProfileNotFound => e
|
|
49
49
|
@err.puts(e.message)
|
data/lib/cucumber/cli/options.rb
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
require 'cucumber/cli/profile_loader'
|
|
2
2
|
require 'cucumber/formatter/ansicolor'
|
|
3
3
|
require 'cucumber/rb_support/rb_language'
|
|
4
|
+
require 'cucumber/project_initializer'
|
|
4
5
|
|
|
5
6
|
module Cucumber
|
|
6
7
|
module Cli
|
|
@@ -126,6 +127,12 @@ module Cucumber
|
|
|
126
127
|
*FORMAT_HELP) do |v|
|
|
127
128
|
@options[:formats] << [v, @out_stream]
|
|
128
129
|
end
|
|
130
|
+
opts.on('--init',
|
|
131
|
+
'Initializes folder structure and generates conventional files for',
|
|
132
|
+
'a Cucumber project.') do |v|
|
|
133
|
+
ProjectInitializer.new.run
|
|
134
|
+
Kernel.exit(0)
|
|
135
|
+
end
|
|
129
136
|
opts.on("-o", "--out [FILE|DIR]",
|
|
130
137
|
"Write output to a file/directory instead of STDOUT. This option",
|
|
131
138
|
"applies to the previously specified --format, or the",
|
|
@@ -266,7 +273,7 @@ TEXT
|
|
|
266
273
|
end
|
|
267
274
|
|
|
268
275
|
def filters
|
|
269
|
-
@options
|
|
276
|
+
@options[:filters] ||= []
|
|
270
277
|
end
|
|
271
278
|
|
|
272
279
|
protected
|
|
@@ -60,7 +60,7 @@ Defined profiles in cucumber.yml:
|
|
|
60
60
|
require 'erb'
|
|
61
61
|
require 'yaml'
|
|
62
62
|
begin
|
|
63
|
-
@cucumber_erb = ERB.new(IO.read(cucumber_file)).result(binding)
|
|
63
|
+
@cucumber_erb = ERB.new(IO.read(cucumber_file), nil, '%').result(binding)
|
|
64
64
|
rescue Exception => e
|
|
65
65
|
raise(YmlLoadError,"cucumber.yml was found, but could not be parsed with ERB. Please refer to cucumber's documentation on correct profile usage.\n#{$!.inspect}")
|
|
66
66
|
end
|
|
@@ -47,7 +47,7 @@ class Object #:nodoc:
|
|
|
47
47
|
end
|
|
48
48
|
end
|
|
49
49
|
|
|
50
|
-
INSTANCE_EXEC_OFFSET =
|
|
50
|
+
INSTANCE_EXEC_OFFSET = -3
|
|
51
51
|
|
|
52
52
|
def replace_instance_exec_invocation_line!(backtrace, instance_exec_invocation_line, pseudo_method)
|
|
53
53
|
return if Cucumber.use_full_backtrace
|
data/lib/cucumber/errors.rb
CHANGED
|
@@ -20,6 +20,14 @@ module Cucumber
|
|
|
20
20
|
end
|
|
21
21
|
end
|
|
22
22
|
|
|
23
|
+
# Raised when there is no matching StepDefinition for a step called
|
|
24
|
+
# from within another step definition.
|
|
25
|
+
class UndefinedDynamicStep < StandardError
|
|
26
|
+
def initialize(step_name)
|
|
27
|
+
super %(Undefined dynamic step: "#{step_name}")
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
23
31
|
# Raised when a StepDefinition's block invokes World#pending
|
|
24
32
|
class Pending < Core::Test::Result::Pending
|
|
25
33
|
end
|
data/lib/cucumber/file_specs.rb
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
require 'cucumber'
|
|
1
2
|
require 'cucumber/core/ast/location'
|
|
3
|
+
|
|
2
4
|
module Cucumber
|
|
3
5
|
class FileSpecs
|
|
4
6
|
FILE_COLON_LINE_PATTERN = /^([\w\W]*?)(?::([\d:]+))?$/ #:nodoc:
|
|
@@ -14,7 +16,7 @@ module Cucumber
|
|
|
14
16
|
end
|
|
15
17
|
|
|
16
18
|
def files
|
|
17
|
-
@file_specs.map(&:file)
|
|
19
|
+
@file_specs.map(&:file).uniq
|
|
18
20
|
end
|
|
19
21
|
|
|
20
22
|
class FileSpec
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
require 'cucumber/core/filter'
|
|
2
|
+
|
|
3
|
+
module Cucumber
|
|
4
|
+
module Filters
|
|
5
|
+
class ActivateSteps < Core::Filter.new(:step_definitions)
|
|
6
|
+
|
|
7
|
+
def test_case(test_case)
|
|
8
|
+
CaseFilter.new(test_case, step_definitions).test_case.describe_to receiver
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
class CaseFilter
|
|
12
|
+
def initialize(test_case, step_definitions)
|
|
13
|
+
@original_test_case = test_case
|
|
14
|
+
@step_definitions = step_definitions
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def test_case
|
|
18
|
+
@original_test_case.with_steps(new_test_steps)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
|
|
23
|
+
def new_test_steps
|
|
24
|
+
@original_test_case.test_steps.map(&self.method(:attempt_to_activate))
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def attempt_to_activate(test_step)
|
|
28
|
+
@step_definitions.find_match(test_step).activate(test_step)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
require 'cucumber/core/filter'
|
|
2
|
+
|
|
3
|
+
module Cucumber
|
|
4
|
+
module Filters
|
|
5
|
+
class ApplyAfterStepHooks < Core::Filter.new(:hooks)
|
|
6
|
+
def test_case(test_case)
|
|
7
|
+
test_steps = hooks.find_after_step_hooks(test_case).apply(test_case.test_steps)
|
|
8
|
+
test_case.with_steps(test_steps).describe_to(receiver)
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
require 'cucumber/core/filter'
|
|
2
|
+
|
|
3
|
+
module Cucumber
|
|
4
|
+
module Filters
|
|
5
|
+
class ApplyAroundHooks < Core::Filter.new(:hooks)
|
|
6
|
+
def test_case(test_case)
|
|
7
|
+
around_hooks = hooks.find_around_hooks(test_case)
|
|
8
|
+
test_case.with_around_hooks(around_hooks).describe_to(receiver)
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
module Cucumber
|
|
2
|
-
|
|
2
|
+
module Filters
|
|
3
|
+
|
|
3
4
|
class GatedReceiver
|
|
4
5
|
def initialize(receiver)
|
|
5
6
|
@receiver = receiver
|
|
@@ -8,6 +9,7 @@ module Cucumber
|
|
|
8
9
|
|
|
9
10
|
def test_case(test_case)
|
|
10
11
|
@test_cases << test_case
|
|
12
|
+
self
|
|
11
13
|
end
|
|
12
14
|
|
|
13
15
|
def done
|
|
@@ -15,7 +17,9 @@ module Cucumber
|
|
|
15
17
|
test_case.describe_to(@receiver)
|
|
16
18
|
end
|
|
17
19
|
@receiver.done
|
|
20
|
+
self
|
|
18
21
|
end
|
|
19
22
|
end
|
|
23
|
+
|
|
20
24
|
end
|
|
21
25
|
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
require 'cucumber/core/filter'
|
|
2
|
+
require 'cucumber/running_test_case'
|
|
3
|
+
require 'cucumber/hooks'
|
|
4
|
+
|
|
5
|
+
module Cucumber
|
|
6
|
+
module Filters
|
|
7
|
+
|
|
8
|
+
class PrepareWorld < Core::Filter.new(:runtime)
|
|
9
|
+
|
|
10
|
+
def test_case(test_case)
|
|
11
|
+
CaseFilter.new(runtime, test_case).test_case.describe_to receiver
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
class CaseFilter
|
|
15
|
+
def initialize(runtime, original_test_case)
|
|
16
|
+
@runtime, @original_test_case = runtime, original_test_case
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def test_case
|
|
20
|
+
init_scenario = Cucumber::Hooks.around_hook(@original_test_case.source) do |continue|
|
|
21
|
+
@runtime.begin_scenario(scenario)
|
|
22
|
+
continue.call
|
|
23
|
+
@runtime.end_scenario(scenario)
|
|
24
|
+
end
|
|
25
|
+
around_hooks = [init_scenario] + @original_test_case.around_hooks
|
|
26
|
+
|
|
27
|
+
default_hook = Cucumber::Hooks.before_hook(@original_test_case.source) do
|
|
28
|
+
#no op - legacy format adapter expects a before hooks
|
|
29
|
+
end
|
|
30
|
+
steps = [default_hook] + @original_test_case.test_steps
|
|
31
|
+
|
|
32
|
+
@original_test_case.with_around_hooks(around_hooks).with_steps(steps)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
private
|
|
36
|
+
|
|
37
|
+
def scenario
|
|
38
|
+
@scenario ||= RunningTestCase.new(test_case)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
module Cucumber
|
|
2
|
+
module Filters
|
|
3
|
+
|
|
4
|
+
class Quit
|
|
5
|
+
def initialize(receiver=nil)
|
|
6
|
+
@receiver = receiver
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def test_case(test_case)
|
|
10
|
+
unless Cucumber.wants_to_quit
|
|
11
|
+
test_case.describe_to @receiver
|
|
12
|
+
end
|
|
13
|
+
self
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def done
|
|
17
|
+
@receiver.done
|
|
18
|
+
self
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def with_receiver(receiver)
|
|
22
|
+
self.class.new(receiver)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
module Cucumber
|
|
2
|
+
module Filters
|
|
3
|
+
|
|
4
|
+
# Batches up all test cases, randomizes them, and then sends them on
|
|
5
|
+
class Randomizer
|
|
6
|
+
def initialize(seed, receiver=nil)
|
|
7
|
+
@receiver = receiver
|
|
8
|
+
@test_cases = []
|
|
9
|
+
@seed = seed
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def test_case(test_case)
|
|
13
|
+
@test_cases << test_case
|
|
14
|
+
self
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def done
|
|
18
|
+
shuffled_test_cases.each do |test_case|
|
|
19
|
+
test_case.describe_to(@receiver)
|
|
20
|
+
end
|
|
21
|
+
@receiver.done
|
|
22
|
+
self
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def with_receiver(receiver)
|
|
26
|
+
self.class.new(@seed, receiver)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
private
|
|
30
|
+
|
|
31
|
+
def shuffled_test_cases
|
|
32
|
+
@test_cases.shuffle(random: Random.new(seed))
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
attr_reader :seed
|
|
36
|
+
private :seed
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
module Cucumber
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
module Filters
|
|
3
|
+
class TagLimits
|
|
4
|
+
|
|
4
5
|
class TestCaseIndex
|
|
5
6
|
def initialize
|
|
6
7
|
@index = Hash.new { |hash, key| hash[key] = [] }
|
|
@@ -24,6 +25,7 @@ module Cucumber
|
|
|
24
25
|
|
|
25
26
|
attr_accessor :index
|
|
26
27
|
end
|
|
28
|
+
|
|
27
29
|
end
|
|
28
30
|
end
|
|
29
31
|
end
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
module Cucumber
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
module Filters
|
|
3
|
+
class TagLimits
|
|
4
|
+
|
|
4
5
|
class Verifier
|
|
5
6
|
def initialize(tag_limits)
|
|
6
7
|
@tag_limits = tag_limits
|
|
@@ -51,6 +52,7 @@ module Cucumber
|
|
|
51
52
|
attr_reader :limit
|
|
52
53
|
attr_reader :locations
|
|
53
54
|
end
|
|
55
|
+
|
|
54
56
|
end
|
|
55
57
|
end
|
|
56
58
|
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
require "cucumber/filters/gated_receiver"
|
|
2
|
+
require "cucumber/filters/tag_limits/test_case_index"
|
|
3
|
+
require "cucumber/filters/tag_limits/verifier"
|
|
4
|
+
|
|
5
|
+
module Cucumber
|
|
6
|
+
module Filters
|
|
7
|
+
class TagLimitExceededError < StandardError
|
|
8
|
+
def initialize(*limit_breaches)
|
|
9
|
+
super(limit_breaches.map(&:to_s).join("\n"))
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
class TagLimits
|
|
14
|
+
def initialize(tag_limits, receiver=nil)
|
|
15
|
+
@tag_limits = tag_limits
|
|
16
|
+
@gated_receiver = GatedReceiver.new(receiver)
|
|
17
|
+
@test_case_index = TestCaseIndex.new
|
|
18
|
+
@verifier = Verifier.new(@tag_limits)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def test_case(test_case)
|
|
22
|
+
gated_receiver.test_case(test_case)
|
|
23
|
+
test_case_index.add(test_case)
|
|
24
|
+
self
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def done
|
|
28
|
+
verifier.verify!(test_case_index)
|
|
29
|
+
gated_receiver.done
|
|
30
|
+
self
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def with_receiver(receiver)
|
|
34
|
+
self.class.new(@tag_limits, receiver)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
private
|
|
38
|
+
|
|
39
|
+
attr_reader :gated_receiver
|
|
40
|
+
attr_reader :test_case_index
|
|
41
|
+
attr_reader :verifier
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
require 'cucumber/filters/activate_steps'
|
|
2
|
+
require 'cucumber/filters/apply_after_step_hooks'
|
|
3
|
+
require 'cucumber/filters/apply_before_hooks'
|
|
4
|
+
require 'cucumber/filters/apply_after_hooks'
|
|
5
|
+
require 'cucumber/filters/apply_around_hooks'
|
|
6
|
+
require 'cucumber/filters/prepare_world'
|
|
7
|
+
require 'cucumber/filters/quit'
|
|
8
|
+
require 'cucumber/filters/randomizer'
|
|
9
|
+
require 'cucumber/filters/tag_limits'
|
|
@@ -1,14 +1,6 @@
|
|
|
1
1
|
require 'cucumber/platform'
|
|
2
2
|
require 'cucumber/term/ansicolor'
|
|
3
3
|
|
|
4
|
-
if Cucumber::IRONRUBY
|
|
5
|
-
begin
|
|
6
|
-
require 'iron-term-ansicolor'
|
|
7
|
-
rescue LoadError
|
|
8
|
-
STDERR.puts %{*** WARNING: You must "igem install iron-term-ansicolor" to get coloured ouput in on IronRuby}
|
|
9
|
-
end
|
|
10
|
-
end
|
|
11
|
-
|
|
12
4
|
if Cucumber::WINDOWS_MRI
|
|
13
5
|
unless ENV['ANSICON']
|
|
14
6
|
STDERR.puts %{*** WARNING: You must use ANSICON 1.31 or higher (https://github.com/adoxa/ansicon/) to get coloured output on Windows}
|
|
@@ -97,8 +97,8 @@ module Cucumber
|
|
|
97
97
|
|
|
98
98
|
def collect_failing_scenarios(runtime)
|
|
99
99
|
# TODO: brittle - stop coupling to types
|
|
100
|
-
scenario_class =
|
|
101
|
-
example_table_class =
|
|
100
|
+
scenario_class = LegacyApi::Ast::Scenario
|
|
101
|
+
example_table_class = Core::Ast::ExamplesTable
|
|
102
102
|
|
|
103
103
|
runtime.scenarios(:failed).select do |s|
|
|
104
104
|
[scenario_class, example_table_class].include?(s.class)
|
|
@@ -118,7 +118,7 @@ module Cucumber
|
|
|
118
118
|
end
|
|
119
119
|
|
|
120
120
|
def print_exception(e, status, indent)
|
|
121
|
-
message = "#{e.message} (#{e.class})"
|
|
121
|
+
message = "#{e.message} (#{e.class})".force_encoding("UTF-8")
|
|
122
122
|
if ENV['CUCUMBER_TRUNCATE_OUTPUT']
|
|
123
123
|
message = linebreaks(message, ENV['CUCUMBER_TRUNCATE_OUTPUT'].to_i)
|
|
124
124
|
end
|
|
@@ -132,18 +132,24 @@ module Cucumber
|
|
|
132
132
|
s.gsub(/.{1,#{max}}(?:\s|\Z)/){($& + 5.chr).gsub(/\n\005/,"\n").gsub(/\005/,"\n")}.rstrip
|
|
133
133
|
end
|
|
134
134
|
|
|
135
|
+
def collect_snippet_data(test_step, result)
|
|
136
|
+
# collect snippet data for undefined steps
|
|
137
|
+
unless hook?(test_step)
|
|
138
|
+
keyword = test_step.source.last.actual_keyword(@previous_step_keyword)
|
|
139
|
+
@previous_step_keyword = keyword
|
|
140
|
+
if result.undefined?
|
|
141
|
+
@snippets_input << Console::SnippetData.new(keyword, test_step.source.last)
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
|
|
135
146
|
def print_snippets(options)
|
|
136
147
|
return unless options[:snippets]
|
|
137
|
-
|
|
138
|
-
return if undefined.empty?
|
|
148
|
+
return if runtime.steps(:undefined).empty?
|
|
139
149
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
# TODO: This probably won't work for nested steps :( See above for old code.
|
|
144
|
-
step_name = step.name
|
|
145
|
-
@runtime.snippet_text(step.actual_keyword, step_name, step.multiline_arg)
|
|
146
|
-
end.compact.uniq
|
|
150
|
+
snippets = @snippets_input.map do |data|
|
|
151
|
+
@runtime.snippet_text(data.actual_keyword, data.step.name, data.step.multiline_arg)
|
|
152
|
+
end.uniq
|
|
147
153
|
|
|
148
154
|
text = "\nYou can implement step definitions for undefined steps with these snippets:\n\n"
|
|
149
155
|
text += snippets.join("\n\n")
|
|
@@ -215,16 +221,27 @@ module Cucumber
|
|
|
215
221
|
@io.puts "Using the #{profiles_sentence} profile#{'s' if profiles.size> 1}..."
|
|
216
222
|
end
|
|
217
223
|
|
|
218
|
-
|
|
224
|
+
private
|
|
219
225
|
|
|
220
|
-
|
|
226
|
+
FORMATS = Hash.new{ |hash, format| hash[format] = method(format).to_proc }
|
|
221
227
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
+
def format_for(*keys)
|
|
229
|
+
key = keys.join('_').to_sym
|
|
230
|
+
fmt = FORMATS[key]
|
|
231
|
+
raise "No format for #{key.inspect}: #{FORMATS.inspect}" if fmt.nil?
|
|
232
|
+
fmt
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
def hook?(test_step)
|
|
236
|
+
not test_step.source.last.respond_to?(:actual_keyword)
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
class SnippetData
|
|
240
|
+
attr_reader :actual_keyword, :step
|
|
241
|
+
def initialize(actual_keyword, step)
|
|
242
|
+
@actual_keyword, @step = actual_keyword, step
|
|
243
|
+
end
|
|
244
|
+
end
|
|
228
245
|
|
|
229
246
|
end
|
|
230
247
|
end
|
|
@@ -6,7 +6,6 @@ module Cucumber
|
|
|
6
6
|
class Debug
|
|
7
7
|
def initialize(runtime, io, options)
|
|
8
8
|
@io = io
|
|
9
|
-
@indent = 0
|
|
10
9
|
end
|
|
11
10
|
|
|
12
11
|
def log(message)
|
|
@@ -19,9 +18,7 @@ module Cucumber
|
|
|
19
18
|
end
|
|
20
19
|
|
|
21
20
|
def method_missing(name, *args)
|
|
22
|
-
@indent -= 2 if name.to_s =~ /^after/
|
|
23
21
|
print(name)
|
|
24
|
-
@indent += 2 if name.to_s =~ /^before/
|
|
25
22
|
end
|
|
26
23
|
|
|
27
24
|
def puts(*args)
|
|
@@ -31,11 +28,7 @@ module Cucumber
|
|
|
31
28
|
private
|
|
32
29
|
|
|
33
30
|
def print(text)
|
|
34
|
-
@io.puts
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
def indent
|
|
38
|
-
(' ' * @indent)
|
|
31
|
+
@io.puts text
|
|
39
32
|
end
|
|
40
33
|
end
|
|
41
34
|
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
module Cucumber
|
|
2
|
+
module Formatter
|
|
3
|
+
|
|
4
|
+
# Forwards any messages sent to this object to all recipients
|
|
5
|
+
# that respond to that message.
|
|
6
|
+
class Fanout < BasicObject
|
|
7
|
+
attr_reader :recipients
|
|
8
|
+
private :recipients
|
|
9
|
+
|
|
10
|
+
def initialize(recipients)
|
|
11
|
+
@recipients = recipients
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def method_missing(message, *args)
|
|
15
|
+
recipients.each do |recipient|
|
|
16
|
+
recipient.send(message, *args) if recipient.respond_to?(message)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def respond_to_missing?(name, include_private = false)
|
|
21
|
+
recipients.any? { |recipient| recipient.respond_to?(name, include_private) }
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
end
|
|
27
|
+
end
|