cucumber 2.1.0 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
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