cucumber-core 1.0.0.beta.4 → 1.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.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -0
  3. data/CONTRIBUTING.md +14 -0
  4. data/HISTORY.md +14 -1
  5. data/README.md +34 -33
  6. data/lib/cucumber/core.rb +3 -5
  7. data/lib/cucumber/core/ast/background.rb +13 -2
  8. data/lib/cucumber/core/ast/comment.rb +8 -2
  9. data/lib/cucumber/core/ast/examples_table.rb +14 -5
  10. data/lib/cucumber/core/ast/feature.rb +15 -6
  11. data/lib/cucumber/core/ast/scenario.rb +17 -4
  12. data/lib/cucumber/core/ast/scenario_outline.rb +20 -8
  13. data/lib/cucumber/core/ast/tag.rb +5 -3
  14. data/lib/cucumber/core/compiler.rb +39 -7
  15. data/lib/cucumber/core/filter.rb +83 -0
  16. data/lib/cucumber/core/gherkin/ast_builder.rb +7 -2
  17. data/lib/cucumber/core/gherkin/document.rb +5 -2
  18. data/lib/cucumber/core/gherkin/parser.rb +6 -1
  19. data/lib/cucumber/core/test/action.rb +8 -8
  20. data/lib/cucumber/core/test/around_hook.rb +19 -0
  21. data/lib/cucumber/core/test/case.rb +6 -4
  22. data/lib/cucumber/core/test/filters/locations_filter.rb +3 -6
  23. data/lib/cucumber/core/test/filters/name_filter.rb +3 -7
  24. data/lib/cucumber/core/test/filters/tag_filter.rb +4 -2
  25. data/lib/cucumber/core/test/result.rb +5 -7
  26. data/lib/cucumber/core/test/runner.rb +39 -40
  27. data/lib/cucumber/core/test/step.rb +7 -10
  28. data/lib/cucumber/core/version.rb +1 -1
  29. data/spec/capture_warnings.rb +5 -0
  30. data/spec/cucumber/core/filter_spec.rb +100 -0
  31. data/spec/cucumber/core/gherkin/parser_spec.rb +0 -1
  32. data/spec/cucumber/core/test/action_spec.rb +29 -31
  33. data/spec/cucumber/core/test/runner_spec.rb +5 -5
  34. data/spec/cucumber/core/test/step_spec.rb +18 -9
  35. data/spec/cucumber/core_spec.rb +40 -172
  36. metadata +11 -16
  37. data/lib/cucumber/core/test/hooks.rb +0 -93
  38. data/lib/cucumber/core/test/mapper.rb +0 -150
  39. data/lib/cucumber/initializer.rb +0 -18
  40. data/spec/cucumber/core/test/hooks_spec.rb +0 -30
  41. data/spec/cucumber/core/test/mapper_spec.rb +0 -203
  42. data/spec/cucumber/initializer_spec.rb +0 -49
@@ -0,0 +1,83 @@
1
+ module Cucumber
2
+ module Core
3
+
4
+ # Filters process test cases.
5
+ #
6
+ # Each filter must respond to the following protocol:
7
+ #
8
+ # * `with_receiver(new_receiver)`
9
+ # * `test_case(test_case, &describe_test_steps)`
10
+ # * `done`
11
+ #
12
+ # The `with_receiver` method is used to assemble the filters into a chain. It should return a new instance of the
13
+ # filter with the receiver attribute set to the new receiver. The receiver will also respond to the filter protocol.
14
+ #
15
+ # When a `test_case` message is received, the filter can choose to:
16
+ #
17
+ # 1. pass the test_case directly to its receiver (no-op)
18
+ # 2. pass a modified copy of the test_case to its receiver
19
+ # 3. not pass the test_case to its receiver at all
20
+ #
21
+ # Finally, the `done` message is sent. A filter should pass this message directly to its receiver.
22
+ #
23
+ module Filter
24
+
25
+ # Utility method for quick construction of filter classes.
26
+ #
27
+ # @example Example usage:
28
+ #
29
+ # class BlankingFilter < Filter.new(:name_to_blank, :receiver)
30
+ # def test_case(test_case)
31
+ # if name_to_blank == test_case.name
32
+ # test_case.with_steps([]).describe_to(receiver)
33
+ # else
34
+ # test_case.describe_to(receiver)
35
+ # end
36
+ # end
37
+ # end
38
+ #
39
+ # The attribute names passed to the Filter constructor will become private attributes of
40
+ # your filter class.
41
+ #
42
+ def self.new(*attributes, &block)
43
+ attributes << :receiver
44
+
45
+ result = Class.new do
46
+ attr_reader(*attributes)
47
+ private(*attributes)
48
+
49
+ define_method(:initialize) do |*args|
50
+ attributes.zip(args) do |name, value|
51
+ instance_variable_set("@#{name}".to_sym, value)
52
+ end
53
+ end
54
+
55
+ def test_case(test_case)
56
+ test_case.describe_to receiver
57
+ self
58
+ end
59
+
60
+ def done
61
+ receiver.done
62
+ self
63
+ end
64
+
65
+ define_method(:with_receiver) do |new_receiver|
66
+ args = attributes.map { |name|
67
+ instance_variable_get("@#{name}".to_sym)
68
+ }
69
+ args[-1] = new_receiver
70
+ self.class.new(*args)
71
+ end
72
+
73
+ end
74
+
75
+ if block
76
+ Class.new(result, &block)
77
+ else
78
+ result
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
@@ -1,4 +1,3 @@
1
- require 'cucumber/initializer'
2
1
  require 'cucumber/core/ast'
3
2
  require 'cucumber/core/platform'
4
3
  require 'gherkin/rubify'
@@ -76,7 +75,13 @@ module Cucumber
76
75
  end
77
76
 
78
77
  class Builder
79
- include Cucumber.initializer(:file, :node)
78
+ attr_reader :file, :node
79
+ private :file, :node
80
+
81
+ def initialize(file, node)
82
+ @file = file
83
+ @node = node
84
+ end
80
85
 
81
86
  private
82
87
 
@@ -1,12 +1,15 @@
1
- require 'cucumber/initializer'
2
1
 
3
2
  module Cucumber
4
3
  module Core
5
4
  module Gherkin
6
5
  class Document
7
- include Cucumber.initializer(:uri, :body)
8
6
  attr_reader :uri, :body
9
7
 
8
+ def initialize(uri, body)
9
+ @uri = uri
10
+ @body = body
11
+ end
12
+
10
13
  def to_s
11
14
  body
12
15
  end
@@ -7,7 +7,12 @@ module Cucumber
7
7
  ParseError = Class.new(StandardError)
8
8
 
9
9
  class Parser
10
- include Cucumber.initializer(:receiver)
10
+ attr_reader :receiver
11
+ private :receiver
12
+
13
+ def initialize(receiver)
14
+ @receiver = receiver
15
+ end
11
16
 
12
17
  def document(document)
13
18
  builder = AstBuilder.new(document.uri)
@@ -8,18 +8,18 @@ module Cucumber
8
8
  module Test
9
9
  class Action
10
10
  def initialize(&block)
11
- raise ArgumentError, "Passing a block to execute the mapping is mandatory." unless block
11
+ raise ArgumentError, "Passing a block to execute the action is mandatory." unless block
12
12
  @block = block
13
13
  @timer = Timer.new
14
14
  end
15
15
 
16
- def skip(last_result)
16
+ def skip(*)
17
17
  skipped
18
18
  end
19
19
 
20
- def execute(last_result)
20
+ def execute(*args)
21
21
  @timer.start
22
- @block.call(last_result)
22
+ @block.call(*args)
23
23
  passed
24
24
  rescue Result::Raisable => exception
25
25
  exception.with_duration(@timer.duration)
@@ -51,17 +51,17 @@ module Cucumber
51
51
  end
52
52
 
53
53
  class UnskippableAction < Action
54
- def skip(last_result)
55
- execute(last_result)
54
+ def skip(*args)
55
+ execute(*args)
56
56
  end
57
57
  end
58
58
 
59
59
  class UndefinedAction
60
- def execute(last_result)
60
+ def execute(*)
61
61
  undefined
62
62
  end
63
63
 
64
- def skip(last_result)
64
+ def skip(*)
65
65
  undefined
66
66
  end
67
67
 
@@ -0,0 +1,19 @@
1
+ module Cucumber
2
+ module Core
3
+ module Test
4
+ class AroundHook
5
+ def initialize(&block)
6
+ @block = block
7
+ end
8
+
9
+ def describe_to(visitor, *args, &continue)
10
+ visitor.around_hook(self, *args, &continue)
11
+ end
12
+
13
+ def call(continue)
14
+ @block.call(continue)
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -1,15 +1,17 @@
1
- require 'cucumber/initializer'
2
1
  require 'cucumber/core/test/result'
3
2
 
4
3
  module Cucumber
5
4
  module Core
6
5
  module Test
7
6
  class Case
8
- include Cucumber.initializer(:test_steps, :source, :around_hooks)
9
- attr_reader :source, :test_steps
7
+ attr_reader :source, :test_steps, :around_hooks
8
+ private :around_hooks
10
9
 
11
10
  def initialize(test_steps, source, around_hooks = [])
12
- super(test_steps, source, around_hooks)
11
+ raise ArgumentError.new("test_steps should be an Array but is a #{test_steps.class}") unless test_steps.kind_of?(Array)
12
+ @test_steps = test_steps
13
+ @source = source
14
+ @around_hooks = around_hooks
13
15
  end
14
16
 
15
17
  def step_count
@@ -1,8 +1,9 @@
1
+ require 'cucumber/core/filter'
2
+
1
3
  module Cucumber
2
4
  module Core
3
5
  module Test
4
- class LocationsFilter
5
- include Cucumber.initializer(:locations, :receiver)
6
+ class LocationsFilter < Filter.new(:locations)
6
7
 
7
8
  def test_case(test_case)
8
9
  if test_case.match_locations?(@locations)
@@ -11,10 +12,6 @@ module Cucumber
11
12
  self
12
13
  end
13
14
 
14
- def done
15
- @receiver.done
16
- self
17
- end
18
15
  end
19
16
  end
20
17
  end
@@ -1,8 +1,9 @@
1
+ require 'cucumber/core/filter'
2
+
1
3
  module Cucumber
2
4
  module Core
3
5
  module Test
4
- class NameFilter
5
- include Cucumber.initializer(:name_regexps, :receiver)
6
+ class NameFilter < Filter.new(:name_regexps)
6
7
 
7
8
  def test_case(test_case)
8
9
  if accept?(test_case)
@@ -11,11 +12,6 @@ module Cucumber
11
12
  self
12
13
  end
13
14
 
14
- def done
15
- @receiver.done
16
- self
17
- end
18
-
19
15
  private
20
16
 
21
17
  def accept?(test_case)
@@ -1,8 +1,9 @@
1
+ require 'cucumber/core/filter'
2
+
1
3
  module Cucumber
2
4
  module Core
3
5
  module Test
4
- class TagFilter
5
- include Cucumber.initializer(:filter_expressions, :receiver)
6
+ class TagFilter < Filter.new(:filter_expressions)
6
7
 
7
8
  def test_case(test_case)
8
9
  test_cases << test_case
@@ -19,6 +20,7 @@ module Cucumber
19
20
  end
20
21
 
21
22
  private
23
+
22
24
  def test_cases
23
25
  @test_cases ||= TestCases.new
24
26
  end
@@ -1,5 +1,4 @@
1
- # encoding: UTF-8¬
2
- require 'cucumber/initializer'
1
+ # encoding: UTF-8
3
2
 
4
3
  module Cucumber
5
4
  module Core
@@ -29,12 +28,11 @@ module Cucumber
29
28
 
30
29
  class Passed
31
30
  include Result.status_queries(:passed)
32
- include Cucumber.initializer(:duration)
33
- attr_reader :duration
31
+ attr_accessor :duration
34
32
 
35
33
  def initialize(duration)
36
34
  raise ArgumentError unless duration
37
- super
35
+ @duration = duration
38
36
  end
39
37
 
40
38
  def describe_to(visitor, *args)
@@ -50,13 +48,13 @@ module Cucumber
50
48
 
51
49
  class Failed
52
50
  include Result.status_queries(:failed)
53
- include Cucumber.initializer(:duration, :exception)
54
51
  attr_reader :duration, :exception
55
52
 
56
53
  def initialize(duration, exception)
57
54
  raise ArgumentError unless duration
58
55
  raise ArgumentError unless exception
59
- super
56
+ @duration = duration
57
+ @exception = exception
60
58
  end
61
59
 
62
60
  def describe_to(visitor, *args)
@@ -1,11 +1,42 @@
1
- require 'cucumber/initializer'
2
1
  require 'cucumber/core/test/timer'
3
2
 
4
3
  module Cucumber
5
4
  module Core
6
5
  module Test
7
6
  class Runner
8
- class StepRunner
7
+ attr_reader :report, :running_test_case
8
+ private :report, :running_test_case
9
+
10
+ def initialize(report)
11
+ @report = report
12
+ end
13
+
14
+ def test_case(test_case, &descend)
15
+ @running_test_case = RunningTestCase.new
16
+ report.before_test_case(test_case)
17
+ descend.call(self)
18
+ report.after_test_case(test_case, running_test_case.result)
19
+ self
20
+ end
21
+
22
+ def test_step(test_step)
23
+ report.before_test_step test_step
24
+ step_result = running_test_case.execute(test_step)
25
+ report.after_test_step test_step, step_result
26
+ self
27
+ end
28
+
29
+ def around_hook(hook, &continue)
30
+ hook.call(continue)
31
+ self
32
+ end
33
+
34
+ def done
35
+ report.done
36
+ self
37
+ end
38
+
39
+ class RunningTestCase
9
40
  def initialize
10
41
  @timer = Timer.new.start
11
42
  @status = Status::Unknown.new(Result::Unknown.new)
@@ -57,7 +88,12 @@ module Cucumber
57
88
 
58
89
  module Status
59
90
  class Base
60
- include Cucumber.initializer(:step_result)
91
+ attr_reader :step_result
92
+ private :step_result
93
+
94
+ def initialize(step_result)
95
+ @step_result = step_result
96
+ end
61
97
 
62
98
  def execute(test_step, monitor)
63
99
  result = test_step.execute(monitor.result)
@@ -101,43 +137,6 @@ module Cucumber
101
137
  end
102
138
  end
103
139
 
104
- attr_reader :report
105
- private :report
106
- def initialize(report)
107
- @report = report
108
- end
109
-
110
- def test_case(test_case, &descend)
111
- report.before_test_case(test_case)
112
- descend.call(self)
113
- report.after_test_case(test_case, current_case_result)
114
- @current_step_runner = nil
115
- end
116
-
117
- def test_step(test_step)
118
- report.before_test_step test_step
119
- step_result = current_step_runner.execute(test_step)
120
- report.after_test_step test_step, step_result
121
- end
122
-
123
- def around_hook(hook, &continue)
124
- hook.call(continue)
125
- end
126
-
127
- def done
128
- report.done
129
- self
130
- end
131
-
132
- private
133
-
134
- def current_case_result
135
- current_step_runner.result
136
- end
137
-
138
- def current_step_runner
139
- @current_step_runner ||= StepRunner.new
140
- end
141
140
  end
142
141
  end
143
142
  end
@@ -1,4 +1,3 @@
1
- require 'cucumber/initializer'
2
1
  require 'cucumber/core/test/result'
3
2
  require 'cucumber/core/test/action'
4
3
 
@@ -6,13 +5,11 @@ module Cucumber
6
5
  module Core
7
6
  module Test
8
7
  class Step
9
- include Cucumber.initializer(:source)
10
8
  attr_reader :source
11
9
 
12
- def initialize(source, mapping = Test::UndefinedAction.new)
10
+ def initialize(source, action = Test::UndefinedAction.new)
13
11
  raise ArgumentError if source.any?(&:nil?)
14
- @mapping = mapping
15
- super(source)
12
+ @source, @action = source, action
16
13
  end
17
14
 
18
15
  def describe_to(visitor, *args)
@@ -26,15 +23,15 @@ module Cucumber
26
23
  self
27
24
  end
28
25
 
29
- def skip(last_result)
30
- @mapping.skip(last_result)
26
+ def skip(*args)
27
+ @action.skip(*args)
31
28
  end
32
29
 
33
- def execute(last_result)
34
- @mapping.execute(last_result)
30
+ def execute(*args)
31
+ @action.execute(*args)
35
32
  end
36
33
 
37
- def with_mapping(&block)
34
+ def with_action(&block)
38
35
  self.class.new(source, Test::Action.new(&block))
39
36
  end
40
37