cucumber-core 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. checksums.yaml +7 -0
  2. data/.coveralls.yml +1 -0
  3. data/.rspec +1 -0
  4. data/.ruby-gemset +1 -0
  5. data/.travis.yml +16 -0
  6. data/Gemfile +2 -0
  7. data/LICENSE +20 -0
  8. data/README.md +9 -0
  9. data/Rakefile +24 -0
  10. data/cucumber-core.gemspec +32 -0
  11. data/lib/cucumber/core.rb +37 -0
  12. data/lib/cucumber/core/ast.rb +13 -0
  13. data/lib/cucumber/core/ast/background.rb +33 -0
  14. data/lib/cucumber/core/ast/comment.rb +17 -0
  15. data/lib/cucumber/core/ast/data_table.rb +326 -0
  16. data/lib/cucumber/core/ast/describes_itself.rb +16 -0
  17. data/lib/cucumber/core/ast/doc_string.rb +83 -0
  18. data/lib/cucumber/core/ast/empty_background.rb +12 -0
  19. data/lib/cucumber/core/ast/examples_table.rb +95 -0
  20. data/lib/cucumber/core/ast/feature.rb +62 -0
  21. data/lib/cucumber/core/ast/location.rb +140 -0
  22. data/lib/cucumber/core/ast/multiline_argument.rb +33 -0
  23. data/lib/cucumber/core/ast/names.rb +19 -0
  24. data/lib/cucumber/core/ast/outline_step.rb +51 -0
  25. data/lib/cucumber/core/ast/scenario.rb +43 -0
  26. data/lib/cucumber/core/ast/scenario_outline.rb +44 -0
  27. data/lib/cucumber/core/ast/step.rb +38 -0
  28. data/lib/cucumber/core/ast/tag.rb +14 -0
  29. data/lib/cucumber/core/compiler.rb +136 -0
  30. data/lib/cucumber/core/gherkin/ast_builder.rb +315 -0
  31. data/lib/cucumber/core/gherkin/document.rb +20 -0
  32. data/lib/cucumber/core/gherkin/parser.rb +45 -0
  33. data/lib/cucumber/core/gherkin/writer.rb +220 -0
  34. data/lib/cucumber/core/gherkin/writer/helpers.rb +178 -0
  35. data/lib/cucumber/core/platform.rb +30 -0
  36. data/lib/cucumber/core/test/case.rb +143 -0
  37. data/lib/cucumber/core/test/filters.rb +48 -0
  38. data/lib/cucumber/core/test/filters/tag_filter.rb +110 -0
  39. data/lib/cucumber/core/test/hook_compiler.rb +109 -0
  40. data/lib/cucumber/core/test/mapper.rb +56 -0
  41. data/lib/cucumber/core/test/mapping.rb +67 -0
  42. data/lib/cucumber/core/test/result.rb +191 -0
  43. data/lib/cucumber/core/test/runner.rb +149 -0
  44. data/lib/cucumber/core/test/step.rb +69 -0
  45. data/lib/cucumber/core/test/timer.rb +31 -0
  46. data/lib/cucumber/core/version.rb +9 -0
  47. data/lib/cucumber/initializer.rb +18 -0
  48. data/spec/capture_warnings.rb +68 -0
  49. data/spec/coverage.rb +10 -0
  50. data/spec/cucumber/core/ast/data_table_spec.rb +139 -0
  51. data/spec/cucumber/core/ast/doc_string_spec.rb +77 -0
  52. data/spec/cucumber/core/ast/examples_table_spec.rb +87 -0
  53. data/spec/cucumber/core/ast/location_spec.rb +105 -0
  54. data/spec/cucumber/core/ast/outline_step_spec.rb +77 -0
  55. data/spec/cucumber/core/ast/step_spec.rb +44 -0
  56. data/spec/cucumber/core/compiler_spec.rb +249 -0
  57. data/spec/cucumber/core/gherkin/parser_spec.rb +182 -0
  58. data/spec/cucumber/core/gherkin/writer_spec.rb +332 -0
  59. data/spec/cucumber/core/test/case_spec.rb +416 -0
  60. data/spec/cucumber/core/test/hook_compiler_spec.rb +78 -0
  61. data/spec/cucumber/core/test/mapper_spec.rb +68 -0
  62. data/spec/cucumber/core/test/mapping_spec.rb +103 -0
  63. data/spec/cucumber/core/test/result_spec.rb +178 -0
  64. data/spec/cucumber/core/test/runner_spec.rb +265 -0
  65. data/spec/cucumber/core/test/step_spec.rb +58 -0
  66. data/spec/cucumber/core/test/timer_spec.rb +13 -0
  67. data/spec/cucumber/core_spec.rb +419 -0
  68. data/spec/cucumber/initializer_spec.rb +49 -0
  69. metadata +221 -0
@@ -0,0 +1,67 @@
1
+ require 'cucumber/core/test/result'
2
+ require 'cucumber/core/test/timer'
3
+ require 'cucumber/core/test/result'
4
+
5
+ module Cucumber
6
+ module Core
7
+ module Test
8
+
9
+ class Mapping
10
+ def initialize(&block)
11
+ raise ArgumentError, "Passing a block to execute the mapping is mandatory." unless block
12
+ @block = block
13
+ @timer = Timer.new
14
+ end
15
+
16
+ def skip
17
+ skipped
18
+ end
19
+
20
+ def execute
21
+ @timer.start
22
+ @block.call
23
+ passed
24
+ rescue Result::Pending => exception
25
+ pending(exception)
26
+ rescue Exception => exception
27
+ failed(exception)
28
+ end
29
+
30
+ private
31
+
32
+ def passed
33
+ Result::Passed.new(@timer.duration)
34
+ end
35
+
36
+ def failed(exception)
37
+ Result::Failed.new(@timer.duration, exception)
38
+ end
39
+
40
+ def skipped
41
+ Result::Skipped.new
42
+ end
43
+
44
+ def pending(exception)
45
+ exception.with_duration(@timer.duration)
46
+ end
47
+ end
48
+
49
+ class UndefinedMapping
50
+ def execute
51
+ undefined
52
+ end
53
+
54
+ def skip
55
+ undefined
56
+ end
57
+
58
+ private
59
+
60
+ def undefined
61
+ Result::Undefined.new
62
+ end
63
+ end
64
+
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,191 @@
1
+ # encoding: UTF-8¬
2
+ require 'cucumber/initializer'
3
+
4
+ module Cucumber
5
+ module Core
6
+ module Test
7
+ module Result
8
+ def self.status_queries(status)
9
+ Module.new do
10
+ [:passed, :failed, :undefined, :unknown, :skipped, :pending].each do |possible_status|
11
+ define_method("#{possible_status}?") do
12
+ possible_status == status
13
+ end
14
+ end
15
+ end
16
+ end
17
+
18
+ Unknown = Class.new do
19
+ include Result.status_queries :unknown
20
+
21
+ def describe_to(visitor, *args)
22
+ self
23
+ end
24
+ end
25
+
26
+ class Passed
27
+ include Result.status_queries :passed
28
+ include Cucumber.initializer(:duration)
29
+ attr_reader :duration
30
+
31
+ def initialize(duration)
32
+ raise ArgumentError unless duration
33
+ super
34
+ end
35
+
36
+ def describe_to(visitor, *args)
37
+ visitor.passed(*args)
38
+ visitor.duration(duration, *args)
39
+ self
40
+ end
41
+
42
+ def to_s
43
+ "✓"
44
+ end
45
+ end
46
+
47
+ class Failed
48
+ include Result.status_queries :failed
49
+ include Cucumber.initializer(:duration, :exception)
50
+ attr_reader :duration, :exception
51
+
52
+ def initialize(duration, exception)
53
+ raise ArgumentError unless duration
54
+ raise ArgumentError unless exception
55
+ super
56
+ end
57
+
58
+ def describe_to(visitor, *args)
59
+ visitor.failed(*args)
60
+ visitor.duration(duration, *args)
61
+ visitor.exception(exception, *args) if exception
62
+ self
63
+ end
64
+
65
+ def to_s
66
+ "✗"
67
+ end
68
+
69
+ def with_duration(new_duration)
70
+ self.class.new(new_duration, exception)
71
+ end
72
+
73
+ end
74
+
75
+ Undefined = Class.new do
76
+ include Result.status_queries :undefined
77
+ include Cucumber.initializer(:duration)
78
+ attr_reader :duration
79
+
80
+ def initialize(duration = 0)
81
+ super
82
+ end
83
+
84
+ def describe_to(visitor, *args)
85
+ visitor.undefined(*args)
86
+ self
87
+ end
88
+
89
+ def to_s
90
+ "✗"
91
+ end
92
+
93
+ def with_duration(new_duration)
94
+ self.class.new(new_duration)
95
+ end
96
+ end
97
+
98
+ Skipped = Class.new do
99
+ include Result.status_queries :skipped
100
+
101
+ def describe_to(visitor, *args)
102
+ visitor.skipped(*args)
103
+ self
104
+ end
105
+
106
+ def to_s
107
+ "-"
108
+ end
109
+ end
110
+
111
+ class Pending < StandardError
112
+ include Result.status_queries :pending
113
+ attr_reader :message, :duration
114
+
115
+ def initialize(message, duration = :unknown, backtrace=nil)
116
+ raise ArgumentError unless message
117
+ @message, @duration = message, duration
118
+ super(message)
119
+ set_backtrace(backtrace) if backtrace
120
+ end
121
+
122
+ def describe_to(visitor, *args)
123
+ visitor.pending(self, *args)
124
+ visitor.duration(duration, *args) unless duration == :unknown
125
+ self
126
+ end
127
+
128
+ def to_s
129
+ "P"
130
+ end
131
+
132
+ def with_duration(new_duration)
133
+ self.class.new(message, new_duration, backtrace)
134
+ end
135
+ end
136
+
137
+ class Summary
138
+ attr_reader :total_failed,
139
+ :total_passed,
140
+ :total_skipped,
141
+ :total_undefined,
142
+ :exceptions,
143
+ :durations
144
+
145
+ def initialize
146
+ @total_failed =
147
+ @total_passed =
148
+ @total_skipped =
149
+ @total_undefined = 0
150
+ @exceptions = []
151
+ @durations = []
152
+ end
153
+
154
+ def failed(*args)
155
+ @total_failed += 1
156
+ self
157
+ end
158
+
159
+ def passed(*args)
160
+ @total_passed += 1
161
+ self
162
+ end
163
+
164
+ def skipped(*args)
165
+ @total_skipped +=1
166
+ self
167
+ end
168
+
169
+ def undefined(*args)
170
+ @total_undefined += 1
171
+ self
172
+ end
173
+
174
+ def exception(exception)
175
+ @exceptions << exception
176
+ self
177
+ end
178
+
179
+ def duration(duration)
180
+ @durations << duration
181
+ self
182
+ end
183
+
184
+ def total
185
+ total_passed + total_failed + total_skipped + total_undefined
186
+ end
187
+ end
188
+ end
189
+ end
190
+ end
191
+ end
@@ -0,0 +1,149 @@
1
+ require 'cucumber/initializer'
2
+ require 'cucumber/core/test/timer'
3
+
4
+ module Cucumber
5
+ module Core
6
+ module Test
7
+ class Runner
8
+ module StepRunner
9
+ class Default
10
+ def initialize
11
+ @timer = Timer.new.start
12
+ end
13
+
14
+ def execute(test_step)
15
+ status.execute(test_step, self)
16
+ end
17
+
18
+ def result
19
+ status.result(@timer.duration)
20
+ end
21
+
22
+ def failed(step_result)
23
+ @status = Failing.new(step_result)
24
+ self
25
+ end
26
+
27
+ def passed(step_result)
28
+ @status = Passing.new
29
+ self
30
+ end
31
+
32
+ def pending(message, step_result)
33
+ @status = Pending.new(step_result)
34
+ self
35
+ end
36
+
37
+ def undefined(step_result)
38
+ failed(step_result)
39
+ self
40
+ end
41
+
42
+ def exception(step_exception, step_result)
43
+ self
44
+ end
45
+
46
+ def duration(step_duration, step_result)
47
+ self
48
+ end
49
+
50
+ private
51
+
52
+ def status
53
+ @status ||= Unknown.new
54
+ end
55
+ end
56
+
57
+ class DryRun
58
+ def execute(test_step)
59
+ step_result = test_step.skip
60
+ @case_result = Result::Undefined.new if step_result.undefined?
61
+ step_result
62
+ end
63
+
64
+ def result
65
+ @case_result ||= Result::Skipped.new
66
+ end
67
+ end
68
+
69
+ class Unknown
70
+ def execute(test_step, monitor)
71
+ result = test_step.execute
72
+ result.describe_to(monitor, result)
73
+ end
74
+
75
+ def result(duration)
76
+ Result::Unknown.new
77
+ end
78
+ end
79
+
80
+ class Passing < Unknown
81
+ def result(duration)
82
+ Result::Passed.new(duration)
83
+ end
84
+ end
85
+
86
+ Failing = Struct.new(:step_result) do
87
+ def execute(test_step, monitor)
88
+ test_step.skip
89
+ end
90
+
91
+ def result(duration)
92
+ step_result.with_duration(duration)
93
+ end
94
+ end
95
+
96
+ Pending = Class.new(Failing)
97
+ end
98
+
99
+ STEP_RUNNER_STRATEGY = {
100
+ default: StepRunner::Default,
101
+ dry_run: StepRunner::DryRun
102
+ }
103
+
104
+ attr_reader :report, :step_runner_class
105
+ private :report, :step_runner_class
106
+ def initialize(report, run_options = {})
107
+ @report = report
108
+
109
+ run_mode = run_options.fetch(:run_mode) { :default }
110
+ @step_runner_class = STEP_RUNNER_STRATEGY.fetch(run_mode) do
111
+ raise ArgumentError, "No strategy for run mode: #{run_mode.inspect}"
112
+ end
113
+ end
114
+
115
+ def test_case(test_case, &descend)
116
+ report.before_test_case(test_case)
117
+ descend.call
118
+ report.after_test_case(test_case, current_case_result)
119
+ @current_step_runner = nil
120
+ end
121
+
122
+ def test_step(test_step)
123
+ report.before_test_step test_step
124
+ step_result = current_step_runner.execute(test_step)
125
+ report.after_test_step test_step, step_result
126
+ end
127
+
128
+ def around_hook(hook, &continue)
129
+ hook.call(continue)
130
+ end
131
+
132
+ def done
133
+ report.done
134
+ self
135
+ end
136
+
137
+ private
138
+
139
+ def current_case_result
140
+ current_step_runner.result
141
+ end
142
+
143
+ def current_step_runner
144
+ @current_step_runner ||= step_runner_class.new
145
+ end
146
+ end
147
+ end
148
+ end
149
+ end
@@ -0,0 +1,69 @@
1
+ require 'cucumber/initializer'
2
+ require 'cucumber/core/test/result'
3
+ require 'cucumber/core/test/mapping'
4
+
5
+ module Cucumber
6
+ module Core
7
+ module Test
8
+ class Step
9
+ include Cucumber.initializer(:source)
10
+
11
+ def initialize(source, mapping = Test::UndefinedMapping.new)
12
+ raise ArgumentError if source.any?(&:nil?)
13
+ @mapping = mapping
14
+ super(source)
15
+ end
16
+
17
+ def describe_to(visitor, *args)
18
+ visitor.test_step(self, *args)
19
+ end
20
+
21
+ def describe_source_to(visitor, *args)
22
+ source.each do |node|
23
+ node.describe_to(visitor, *args)
24
+ end
25
+ end
26
+
27
+ def name
28
+ step.name
29
+ end
30
+
31
+ def multiline_arg
32
+ step.multiline_arg
33
+ end
34
+
35
+ def skip
36
+ @mapping.skip
37
+ end
38
+
39
+ def execute
40
+ @mapping.execute
41
+ end
42
+
43
+ def map(&block)
44
+ self.class.new(source, Test::Mapping.new(&block))
45
+ end
46
+
47
+ def location
48
+ step.location
49
+ end
50
+
51
+ def match_locations?(queried_locations)
52
+ return true if queried_locations.include? location
53
+ source.any? { |s| s.match_locations?(queried_locations) }
54
+ end
55
+
56
+ def inspect
57
+ "#{self.class}: #{location}"
58
+ end
59
+
60
+ private
61
+
62
+ def step
63
+ source.last
64
+ end
65
+
66
+ end
67
+ end
68
+ end
69
+ end