cucumber 2.1.0 → 2.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.
Files changed (82) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +10 -0
  3. data/Gemfile +3 -1
  4. data/History.md +18 -2
  5. data/README.md +5 -1
  6. data/cucumber.gemspec +3 -4
  7. data/cucumber.yml +2 -2
  8. data/features/docs/api/run_cli_main_with_existing_runtime.feature +4 -7
  9. data/features/docs/defining_steps/skip_scenario.feature +6 -2
  10. data/features/docs/formatters/api_methods.feature +36 -0
  11. data/features/docs/profiles.feature +2 -2
  12. data/features/lib/step_definitions/profile_steps.rb +1 -1
  13. data/lib/cucumber.rb +11 -4
  14. data/lib/cucumber/cli/configuration.rb +2 -2
  15. data/lib/cucumber/cli/options.rb +2 -2
  16. data/lib/cucumber/configuration.rb +25 -3
  17. data/lib/cucumber/deprecate.rb +29 -0
  18. data/lib/cucumber/filters/activate_steps.rb +39 -5
  19. data/lib/cucumber/formatter/console.rb +4 -4
  20. data/lib/cucumber/formatter/io.rb +1 -1
  21. data/lib/cucumber/formatter/legacy_api/adapter.rb +30 -30
  22. data/lib/cucumber/formatter/legacy_api/runtime_facade.rb +4 -9
  23. data/lib/cucumber/platform.rb +2 -7
  24. data/lib/cucumber/rb_support/rb_language.rb +72 -26
  25. data/lib/cucumber/rb_support/rb_step_definition.rb +2 -2
  26. data/lib/cucumber/rb_support/rb_world.rb +6 -1
  27. data/lib/cucumber/rb_support/snippet.rb +21 -0
  28. data/lib/cucumber/running_test_case.rb +5 -1
  29. data/lib/cucumber/runtime.rb +11 -15
  30. data/lib/cucumber/runtime/support_code.rb +20 -128
  31. data/lib/cucumber/step_argument.rb +25 -0
  32. data/lib/cucumber/step_match.rb +6 -12
  33. data/lib/cucumber/step_match_search.rb +67 -0
  34. data/lib/cucumber/version +1 -0
  35. data/spec/cucumber/configuration_spec.rb +3 -2
  36. data/spec/cucumber/filters/activate_steps_spec.rb +95 -3
  37. data/spec/cucumber/formatter/html_spec.rb +1 -1
  38. data/spec/cucumber/formatter/legacy_api/adapter_spec.rb +55 -28
  39. data/spec/cucumber/formatter/pretty_spec.rb +2 -2
  40. data/spec/cucumber/formatter/spec_helper.rb +22 -12
  41. data/spec/cucumber/rb_support/rb_language_spec.rb +9 -45
  42. data/spec/cucumber/rb_support/rb_step_definition_spec.rb +2 -2
  43. data/spec/cucumber/rb_support/rb_world_spec.rb +47 -0
  44. data/spec/cucumber/runtime/for_programming_languages_spec.rb +1 -1
  45. data/spec/cucumber/runtime/support_code_spec.rb +4 -111
  46. data/spec/cucumber/step_argument_spec.rb +18 -0
  47. data/spec/cucumber/step_match_search_spec.rb +122 -0
  48. data/spec/cucumber/step_match_spec.rb +8 -2
  49. data/spec/cucumber/world/pending_spec.rb +2 -1
  50. data/spec/cucumber_spec.rb +39 -0
  51. metadata +45 -50
  52. data/features/docs/wire_protocol/erb_configuration.feature +0 -56
  53. data/features/docs/wire_protocol/handle_unexpected_response.feature +0 -30
  54. data/features/docs/wire_protocol/invoke_message.feature +0 -216
  55. data/features/docs/wire_protocol/readme.md +0 -26
  56. data/features/docs/wire_protocol/snippets_message.feature +0 -51
  57. data/features/docs/wire_protocol/step_matches_message.feature +0 -81
  58. data/features/docs/wire_protocol/table_diffing.feature +0 -126
  59. data/features/docs/wire_protocol/tags.feature +0 -87
  60. data/features/docs/wire_protocol/timeouts.feature +0 -64
  61. data/lib/cucumber/events/bus.rb +0 -86
  62. data/lib/cucumber/gherkin/formatter/argument.rb +0 -17
  63. data/lib/cucumber/gherkin/formatter/hashable.rb +0 -27
  64. data/lib/cucumber/language_support.rb +0 -30
  65. data/lib/cucumber/language_support/language_methods.rb +0 -72
  66. data/lib/cucumber/rb_support/regexp_argument_matcher.rb +0 -21
  67. data/lib/cucumber/wire_support/configuration.rb +0 -38
  68. data/lib/cucumber/wire_support/connection.rb +0 -61
  69. data/lib/cucumber/wire_support/request_handler.rb +0 -32
  70. data/lib/cucumber/wire_support/wire_exception.rb +0 -32
  71. data/lib/cucumber/wire_support/wire_language.rb +0 -68
  72. data/lib/cucumber/wire_support/wire_packet.rb +0 -34
  73. data/lib/cucumber/wire_support/wire_protocol.rb +0 -43
  74. data/lib/cucumber/wire_support/wire_protocol/requests.rb +0 -133
  75. data/lib/cucumber/wire_support/wire_step_definition.rb +0 -21
  76. data/spec/cucumber/events/bus_spec.rb +0 -94
  77. data/spec/cucumber/rb_support/regexp_argument_matcher_spec.rb +0 -22
  78. data/spec/cucumber/wire_support/configuration_spec.rb +0 -64
  79. data/spec/cucumber/wire_support/connection_spec.rb +0 -64
  80. data/spec/cucumber/wire_support/wire_exception_spec.rb +0 -50
  81. data/spec/cucumber/wire_support/wire_language_spec.rb +0 -46
  82. data/spec/cucumber/wire_support/wire_packet_spec.rb +0 -44
@@ -1,126 +0,0 @@
1
- @wire
2
- Feature: Wire protocol table diffing
3
-
4
- In order to use the amazing functionality in the Cucumber table object
5
- As a wire server
6
- I want to be able to ask for a table diff during a step definition invocation
7
-
8
- Background:
9
- Given a file named "features/wired.feature" with:
10
- """
11
- Feature: Hello
12
- Scenario: Wired
13
- Given we're all wired
14
-
15
- """
16
- And a file named "features/step_definitions/some_remote_place.wire" with:
17
- """
18
- host: localhost
19
- port: 54321
20
-
21
- """
22
-
23
- @spawn
24
- Scenario: Invoke a step definition tries to diff the table and fails
25
- Given there is a wire server running on port 54321 which understands the following protocol:
26
- | request | response |
27
- | ["step_matches",{"name_to_match":"we're all wired"}] | ["success",[{"id":"1", "args":[]}]] |
28
- | ["begin_scenario"] | ["success"] |
29
- | ["invoke",{"id":"1","args":[]}] | ["diff",[[["a","b"],["c","d"]],[["x","y"],["z","z"]]]] |
30
- | ["diff_failed"] | ["fail",{"message":"Not same", "exception":"DifferentException", "backtrace":["a.cs:12","b.cs:34"]}] |
31
- | ["end_scenario"] | ["success"] |
32
- When I run `cucumber -f progress --backtrace`
33
- Then the stderr should not contain anything
34
- And it should fail with:
35
- """
36
- F
37
-
38
- (::) failed steps (::)
39
-
40
- Not same (DifferentException from localhost:54321)
41
- a.cs:12
42
- b.cs:34
43
- features/wired.feature:3:in `Given we're all wired'
44
-
45
- Failing Scenarios:
46
- cucumber features/wired.feature:2 # Scenario: Wired
47
-
48
- 1 scenario (1 failed)
49
- 1 step (1 failed)
50
-
51
- """
52
-
53
- Scenario: Invoke a step definition tries to diff the table and passes
54
- Given there is a wire server running on port 54321 which understands the following protocol:
55
- | request | response |
56
- | ["step_matches",{"name_to_match":"we're all wired"}] | ["success",[{"id":"1", "args":[]}]] |
57
- | ["begin_scenario"] | ["success"] |
58
- | ["invoke",{"id":"1","args":[]}] | ["diff",[[["a"],["b"]],[["a"],["b"]]]] |
59
- | ["diff_ok"] | ["success"] |
60
- | ["end_scenario"] | ["success"] |
61
- When I run `cucumber -f progress`
62
- Then it should pass with:
63
- """
64
- .
65
-
66
- 1 scenario (1 passed)
67
- 1 step (1 passed)
68
-
69
- """
70
-
71
- @spawn
72
- Scenario: Invoke a step definition which successfully diffs a table but then fails
73
- Given there is a wire server running on port 54321 which understands the following protocol:
74
- | request | response |
75
- | ["step_matches",{"name_to_match":"we're all wired"}] | ["success",[{"id":"1", "args":[]}]] |
76
- | ["begin_scenario"] | ["success"] |
77
- | ["invoke",{"id":"1","args":[]}] | ["diff",[[["a"],["b"]],[["a"],["b"]]]] |
78
- | ["diff_ok"] | ["fail",{"message":"I wanted things to be different for us"}] |
79
- | ["end_scenario"] | ["success"] |
80
- When I run `cucumber -f progress`
81
- Then it should fail with:
82
- """
83
- F
84
-
85
- (::) failed steps (::)
86
-
87
- I wanted things to be different for us (Cucumber::WireSupport::WireException)
88
- features/wired.feature:3:in `Given we're all wired'
89
-
90
- Failing Scenarios:
91
- cucumber features/wired.feature:2 # Scenario: Wired
92
-
93
- 1 scenario (1 failed)
94
- 1 step (1 failed)
95
-
96
- """
97
-
98
- @spawn
99
- Scenario: Invoke a step definition which asks for an immediate diff that fails
100
- Given there is a wire server running on port 54321 which understands the following protocol:
101
- | request | response |
102
- | ["step_matches",{"name_to_match":"we're all wired"}] | ["success",[{"id":"1", "args":[]}]] |
103
- | ["begin_scenario"] | ["success"] |
104
- | ["invoke",{"id":"1","args":[]}] | ["diff!",[[["a"]],[["b"]]]] |
105
- | ["end_scenario"] | ["success"] |
106
- When I run `cucumber -f progress`
107
- And it should fail with exactly:
108
- """
109
- F
110
-
111
- (::) failed steps (::)
112
-
113
- Tables were not identical:
114
-
115
- | (-) a | (+) b |
116
- (Cucumber::MultilineArgument::DataTable::Different)
117
- features/wired.feature:3:in `Given we're all wired'
118
-
119
- Failing Scenarios:
120
- cucumber features/wired.feature:2 # Scenario: Wired
121
-
122
- 1 scenario (1 failed)
123
- 1 step (1 failed)
124
- 0m0.012s
125
-
126
- """
@@ -1,87 +0,0 @@
1
- @wire
2
- Feature: Wire protocol tags
3
-
4
- In order to use Before and After hooks in a wire server, we send tags with the
5
- scenario in the begin_scenario and end_scenario messages
6
-
7
- Background:
8
- And a file named "features/step_definitions/some_remote_place.wire" with:
9
- """
10
- host: localhost
11
- port: 54321
12
-
13
- """
14
-
15
- Scenario: Run a scenario
16
- Given a file named "features/wired.feature" with:
17
- """
18
- @foo @bar
19
- Feature: Wired
20
-
21
- @baz
22
- Scenario: Everybody's Wired
23
- Given we're all wired
24
-
25
- """
26
- And there is a wire server running on port 54321 which understands the following protocol:
27
- | request | response |
28
- | ["step_matches",{"name_to_match":"we're all wired"}] | ["success",[{"id":"1", "args":[]}]] |
29
- | ["begin_scenario", {"tags":["bar","baz","foo"]}] | ["success"] |
30
- | ["invoke",{"id":"1","args":[]}] | ["success"] |
31
- | ["end_scenario", {"tags":["bar","baz","foo"]}] | ["success"] |
32
- When I run `cucumber -f pretty -q`
33
- Then the stderr should not contain anything
34
- And it should pass with:
35
- """
36
- @foo @bar
37
- Feature: Wired
38
-
39
- @baz
40
- Scenario: Everybody's Wired
41
- Given we're all wired
42
-
43
- 1 scenario (1 passed)
44
- 1 step (1 passed)
45
-
46
- """
47
-
48
- Scenario: Run a scenario outline example
49
- Given a file named "features/wired.feature" with:
50
- """
51
- @foo @bar
52
- Feature: Wired
53
-
54
- @baz
55
- Scenario Outline: Everybody's Wired
56
- Given we're all <something>
57
-
58
- Examples:
59
- | something |
60
- | wired |
61
-
62
- """
63
- And there is a wire server running on port 54321 which understands the following protocol:
64
- | request | response |
65
- | ["step_matches",{"name_to_match":"we're all wired"}] | ["success",[{"id":"1", "args":[]}]] |
66
- | ["begin_scenario", {"tags":["bar","baz","foo"]}] | ["success"] |
67
- | ["invoke",{"id":"1","args":[]}] | ["success"] |
68
- | ["end_scenario", {"tags":["bar","baz","foo"]}] | ["success"] |
69
- When I run `cucumber -f pretty -q`
70
- Then the stderr should not contain anything
71
- And it should pass with:
72
- """
73
- @foo @bar
74
- Feature: Wired
75
-
76
- @baz
77
- Scenario Outline: Everybody's Wired
78
- Given we're all <something>
79
-
80
- Examples:
81
- | something |
82
- | wired |
83
-
84
- 1 scenario (1 passed)
85
- 1 step (1 passed)
86
-
87
- """
@@ -1,64 +0,0 @@
1
- @wire
2
- Feature: Wire protocol timeouts
3
-
4
- We don't want Cucumber to hang forever on a wire server that's not even there,
5
- but equally we need to give the user the flexibility to allow step definitions
6
- to take a while to execute, if that's what they need.
7
-
8
- Background:
9
- And a file named "features/wired.feature" with:
10
- """
11
- Feature: Telegraphy
12
- Scenario: Wired
13
- Given we're all wired
14
-
15
- """
16
-
17
- Scenario: Try to talk to a server that's not there
18
- Given a file named "features/step_definitions/some_remote_place.wire" with:
19
- """
20
- host: localhost
21
- port: 54321
22
-
23
- """
24
- When I run `cucumber -f progress`
25
- Then the stderr should contain:
26
- """
27
- Unable to contact the wire server at localhost:54321
28
- """
29
-
30
- @spawn
31
- Scenario: Invoke a step definition that takes longer than its timeout
32
- Given a file named "features/step_definitions/some_remote_place.wire" with:
33
- """
34
- host: localhost
35
- port: 54321
36
- timeout:
37
- invoke: 0.1
38
-
39
- """
40
- And there is a wire server on port 54321 which understands the following protocol:
41
- | request | response |
42
- | ["step_matches",{"name_to_match":"we're all wired"}] | ["success",[{"id":"1", "args":[{"val":"wired", "pos":10}]}]] |
43
- | ["begin_scenario"] | ["success"] |
44
- | ["invoke",{"id":"1","args":["wired"]}] | ["success"] |
45
- | ["end_scenario"] | ["success"] |
46
- And the wire server takes 0.2 seconds to respond to the invoke message
47
- When I run `cucumber -f pretty`
48
- Then the stderr should not contain anything
49
- And it should fail with:
50
- """
51
- Feature: Telegraphy
52
-
53
- Scenario: Wired # features/wired.feature:2
54
- Given we're all wired # Unknown
55
- Timed out calling wire server with message 'invoke' (Timeout::Error)
56
- features/wired.feature:3:in `Given we're all wired'
57
-
58
- Failing Scenarios:
59
- cucumber features/wired.feature:2 # Scenario: Wired
60
-
61
- 1 scenario (1 failed)
62
- 1 step (1 failed)
63
-
64
- """
@@ -1,86 +0,0 @@
1
- module Cucumber
2
- module Events
3
-
4
- # Event bus
5
- #
6
- # Implements and in-process pub-sub events broadcaster allowing multiple observers
7
- # to subscribe to different events that fire as your tests are executed.
8
- #
9
- # @private
10
- class Bus
11
-
12
- def initialize(default_namespace)
13
- @default_namespace = default_namespace.to_s
14
- @handlers = {}
15
- end
16
-
17
- # Register for an event
18
- def register(event_id, handler_object = nil, &handler_proc)
19
- handler = handler_proc || handler_object
20
- raise ArgumentError.new("Please pass either an object or a handler block") unless handler
21
- event_class = parse_event_id(event_id)
22
- handlers_for(event_class) << handler
23
- end
24
-
25
- # Broadcast an event
26
- def notify(event)
27
- handlers_for(event.class).each { |handler| handler.call(event) }
28
- end
29
-
30
- private
31
-
32
- def handlers_for(event_class)
33
- @handlers[event_class.to_s] ||= []
34
- end
35
-
36
- def parse_event_id(event_id)
37
- case event_id
38
- when Class
39
- return event_id
40
- when String
41
- constantize(event_id)
42
- else
43
- constantize("#{@default_namespace}::#{camel_case(event_id)}")
44
- end
45
- end
46
-
47
- def camel_case(underscored_name)
48
- underscored_name.to_s.split("_").map { |word| word.upcase[0] + word[1..-1] }.join
49
- end
50
-
51
- # Thanks ActiveSupport
52
- # (Only needed to support Ruby 1.9.3 and JRuby)
53
- def constantize(camel_cased_word)
54
- names = camel_cased_word.split('::')
55
-
56
- # Trigger a built-in NameError exception including the ill-formed constant in the message.
57
- Object.const_get(camel_cased_word) if names.empty?
58
-
59
- # Remove the first blank element in case of '::ClassName' notation.
60
- names.shift if names.size > 1 && names.first.empty?
61
-
62
- names.inject(Object) do |constant, name|
63
- if constant == Object
64
- constant.const_get(name)
65
- else
66
- candidate = constant.const_get(name)
67
- next candidate if constant.const_defined?(name, false)
68
- next candidate unless Object.const_defined?(name)
69
-
70
- # Go down the ancestors to check if it is owned directly. The check
71
- # stops when we reach Object or the end of ancestors tree.
72
- constant = constant.ancestors.inject do |const, ancestor|
73
- break const if ancestor == Object
74
- break ancestor if ancestor.const_defined?(name, false)
75
- const
76
- end
77
-
78
- # owner is in Object, so raise
79
- constant.const_get(name, false)
80
- end
81
- end
82
- end
83
-
84
- end
85
- end
86
- end
@@ -1,17 +0,0 @@
1
- require 'cucumber/gherkin/formatter/hashable'
2
-
3
- module Cucumber
4
- module Gherkin
5
- module Formatter
6
- class Argument < Hashable
7
- #native_impl('gherkin')
8
- attr_reader :offset, :val
9
-
10
- # Creates a new Argument that starts at character offset +offset+ with value +val+
11
- def initialize(offset, val)
12
- @offset, @val = offset, val
13
- end
14
- end
15
- end
16
- end
17
- end
@@ -1,27 +0,0 @@
1
- module Cucumber
2
- module Gherkin
3
- module Formatter
4
- class Hashable
5
- def to_hash
6
- ivars = instance_variables
7
- # When tests are runn with therubyracer (JavaScript), an extra field might
8
- # exist - added by Ref::WeakReference
9
- # https://github.com/bdurand/ref/blob/master/lib/ref/weak_reference/pure_ruby.rb
10
- # Remove it - we don't want it in the JSON.
11
- ivars.delete(:@__weak_backreferences__)
12
- ivars.inject({}) do |hash, ivar|
13
- value = instance_variable_get(ivar)
14
- value = value.to_hash if value.respond_to?(:to_hash)
15
- if Array === value
16
- value = value.map do |e|
17
- e.respond_to?(:to_hash) ? e.to_hash : e
18
- end
19
- end
20
- hash[ivar[1..-1]] = value unless [[], nil].index(value)
21
- hash
22
- end
23
- end
24
- end
25
- end
26
- end
27
- end
@@ -1,30 +0,0 @@
1
- module Cucumber
2
- # This module defines the API for programming language support in Cucumber.
3
- # While Cucumber itself is written in Ruby, any programming language can
4
- # be supported by implementing this API.
5
- #
6
- # For the sake of illustration we'll consider an imaginary language called
7
- # _why. _why files have the .why extension, so we need to put support for
8
- # this language in the <tt>Cucumber::WhySupport::WhyLanguage</tt>. This
9
- # class must be defined in a file called <tt>cucumber/why_support/why_language.rb</tt>
10
- # and be available on Ruby's <tt>$LOAD_PATH</tt>:
11
- #
12
- # module Cucumber
13
- # module WhySupport
14
- # class WhyLanguage
15
- #
16
- # # Uses whatever available language bridge to load
17
- # # +why_file+ and returns an Array of StepDefinition.
18
- # def load_code_file(why_file)
19
- # end
20
- # end
21
- # end
22
- # end
23
- #
24
- # Each language implementation manages its own hooks, and must execute them
25
- # at appropriate times.
26
- #
27
- #
28
- module LanguageSupport
29
- end
30
- end
@@ -1,72 +0,0 @@
1
- require 'cucumber/step_match'
2
- require 'cucumber/step_definition_light'
3
-
4
- module Cucumber
5
- module LanguageSupport
6
- module LanguageMethods
7
-
8
- def after_configuration(cli_configuration)
9
- configuration = Configuration.new(cli_configuration)
10
- hooks[:after_configuration].each do |hook|
11
- hook.invoke('AfterConfiguration', configuration)
12
- end
13
- end
14
-
15
- def execute_transforms(args)
16
- args.map do |arg|
17
- matching_transform = transforms.detect {|transform| transform.match(arg) }
18
- matching_transform ? matching_transform.invoke(arg) : arg
19
- end
20
- end
21
-
22
- def add_hook(phase, hook)
23
- hooks[phase.to_sym] << hook
24
- hook
25
- end
26
-
27
- def clear_hooks
28
- @hooks = nil
29
- end
30
-
31
- def add_transform(transform)
32
- transforms.unshift transform
33
- transform
34
- end
35
-
36
- def hooks_for(phase, scenario) #:nodoc:
37
- hooks[phase.to_sym].select{|hook| scenario.accept_hook?(hook)}
38
- end
39
-
40
- def unmatched_step_definitions
41
- available_step_definition_hash.keys - invoked_step_definition_hash.keys
42
- end
43
-
44
- def available_step_definition(regexp_source, location)
45
- available_step_definition_hash[StepDefinitionLight.new(regexp_source, location)] = nil
46
- end
47
-
48
- def invoked_step_definition(regexp_source, location)
49
- invoked_step_definition_hash[StepDefinitionLight.new(regexp_source, location)] = nil
50
- end
51
-
52
- private
53
-
54
- def available_step_definition_hash
55
- @available_step_definition_hash ||= {}
56
- end
57
-
58
- def invoked_step_definition_hash
59
- @invoked_step_definition_hash ||= {}
60
- end
61
-
62
- def hooks
63
- @hooks ||= Hash.new{|h,k| h[k] = []}
64
- end
65
-
66
- def transforms
67
- @transforms ||= []
68
- end
69
-
70
- end
71
- end
72
- end