cucumber-core 1.0.0.beta.4 → 1.0.0

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