cucumber-core 0.1.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.
- checksums.yaml +7 -0
- data/.coveralls.yml +1 -0
- data/.rspec +1 -0
- data/.ruby-gemset +1 -0
- data/.travis.yml +16 -0
- data/Gemfile +2 -0
- data/LICENSE +20 -0
- data/README.md +9 -0
- data/Rakefile +24 -0
- data/cucumber-core.gemspec +32 -0
- data/lib/cucumber/core.rb +37 -0
- data/lib/cucumber/core/ast.rb +13 -0
- data/lib/cucumber/core/ast/background.rb +33 -0
- data/lib/cucumber/core/ast/comment.rb +17 -0
- data/lib/cucumber/core/ast/data_table.rb +326 -0
- data/lib/cucumber/core/ast/describes_itself.rb +16 -0
- data/lib/cucumber/core/ast/doc_string.rb +83 -0
- data/lib/cucumber/core/ast/empty_background.rb +12 -0
- data/lib/cucumber/core/ast/examples_table.rb +95 -0
- data/lib/cucumber/core/ast/feature.rb +62 -0
- data/lib/cucumber/core/ast/location.rb +140 -0
- data/lib/cucumber/core/ast/multiline_argument.rb +33 -0
- data/lib/cucumber/core/ast/names.rb +19 -0
- data/lib/cucumber/core/ast/outline_step.rb +51 -0
- data/lib/cucumber/core/ast/scenario.rb +43 -0
- data/lib/cucumber/core/ast/scenario_outline.rb +44 -0
- data/lib/cucumber/core/ast/step.rb +38 -0
- data/lib/cucumber/core/ast/tag.rb +14 -0
- data/lib/cucumber/core/compiler.rb +136 -0
- data/lib/cucumber/core/gherkin/ast_builder.rb +315 -0
- data/lib/cucumber/core/gherkin/document.rb +20 -0
- data/lib/cucumber/core/gherkin/parser.rb +45 -0
- data/lib/cucumber/core/gherkin/writer.rb +220 -0
- data/lib/cucumber/core/gherkin/writer/helpers.rb +178 -0
- data/lib/cucumber/core/platform.rb +30 -0
- data/lib/cucumber/core/test/case.rb +143 -0
- data/lib/cucumber/core/test/filters.rb +48 -0
- data/lib/cucumber/core/test/filters/tag_filter.rb +110 -0
- data/lib/cucumber/core/test/hook_compiler.rb +109 -0
- data/lib/cucumber/core/test/mapper.rb +56 -0
- data/lib/cucumber/core/test/mapping.rb +67 -0
- data/lib/cucumber/core/test/result.rb +191 -0
- data/lib/cucumber/core/test/runner.rb +149 -0
- data/lib/cucumber/core/test/step.rb +69 -0
- data/lib/cucumber/core/test/timer.rb +31 -0
- data/lib/cucumber/core/version.rb +9 -0
- data/lib/cucumber/initializer.rb +18 -0
- data/spec/capture_warnings.rb +68 -0
- data/spec/coverage.rb +10 -0
- data/spec/cucumber/core/ast/data_table_spec.rb +139 -0
- data/spec/cucumber/core/ast/doc_string_spec.rb +77 -0
- data/spec/cucumber/core/ast/examples_table_spec.rb +87 -0
- data/spec/cucumber/core/ast/location_spec.rb +105 -0
- data/spec/cucumber/core/ast/outline_step_spec.rb +77 -0
- data/spec/cucumber/core/ast/step_spec.rb +44 -0
- data/spec/cucumber/core/compiler_spec.rb +249 -0
- data/spec/cucumber/core/gherkin/parser_spec.rb +182 -0
- data/spec/cucumber/core/gherkin/writer_spec.rb +332 -0
- data/spec/cucumber/core/test/case_spec.rb +416 -0
- data/spec/cucumber/core/test/hook_compiler_spec.rb +78 -0
- data/spec/cucumber/core/test/mapper_spec.rb +68 -0
- data/spec/cucumber/core/test/mapping_spec.rb +103 -0
- data/spec/cucumber/core/test/result_spec.rb +178 -0
- data/spec/cucumber/core/test/runner_spec.rb +265 -0
- data/spec/cucumber/core/test/step_spec.rb +58 -0
- data/spec/cucumber/core/test/timer_spec.rb +13 -0
- data/spec/cucumber/core_spec.rb +419 -0
- data/spec/cucumber/initializer_spec.rb +49 -0
- 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
|