lopata 0.1.13 → 0.1.14

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,39 +1,39 @@
1
- module Lopata
2
- # @private
3
- class SharedStep
4
- attr_reader :name, :block
5
-
6
- class NotFound < StandardError; end
7
-
8
-
9
- def self.register(name, &block)
10
- raise ArgumentError, "Comma is not allowed in shared step name: '%s'" % name if name =~ /,/
11
- registry[name] = new(name, &block)
12
- end
13
-
14
- def self.find(name)
15
- registry[name] or raise NotFound, "Shared step '%s' not found" % name
16
- end
17
-
18
- def initialize(name, &block)
19
- @name, @block = name, block
20
- end
21
-
22
- def steps
23
- @steps ||= build_steps
24
- end
25
-
26
- def build_steps
27
- builder = Lopata::ScenarioBuilder.new(name)
28
- builder.shared_step = self
29
- builder.instance_exec(&block)
30
- builder.steps
31
- end
32
-
33
- private
34
-
35
- def self.registry
36
- @shared_steps ||= {}
37
- end
38
- end
1
+ module Lopata
2
+ # @private
3
+ class SharedStep
4
+ attr_reader :name, :block
5
+
6
+ class NotFound < StandardError; end
7
+
8
+
9
+ def self.register(name, &block)
10
+ raise ArgumentError, "Comma is not allowed in shared step name: '%s'" % name if name =~ /,/
11
+ registry[name] = new(name, &block)
12
+ end
13
+
14
+ def self.find(name)
15
+ registry[name] or raise NotFound, "Shared step '%s' not found" % name
16
+ end
17
+
18
+ def initialize(name, &block)
19
+ @name, @block = name, block
20
+ end
21
+
22
+ def steps
23
+ @steps ||= build_steps
24
+ end
25
+
26
+ def build_steps
27
+ builder = Lopata::ScenarioBuilder.new(name)
28
+ builder.shared_step = self
29
+ builder.instance_exec(&block)
30
+ builder.steps
31
+ end
32
+
33
+ private
34
+
35
+ def self.registry
36
+ @shared_steps ||= {}
37
+ end
38
+ end
39
39
  end
data/lib/lopata/step.rb CHANGED
@@ -1,191 +1,191 @@
1
- require 'forwardable'
2
-
3
- module Lopata
4
- # @private
5
- class Step
6
- attr_reader :block, :args, :condition, :method_name, :shared_step
7
- # metadata overrien by the step.
8
- attr_accessor :metadata
9
-
10
- def initialize(method_name, *args, condition: nil, shared_step: nil, &block)
11
- @method_name = method_name
12
- @args = args
13
- @block = block
14
- @shared_step = shared_step
15
- @condition = condition
16
- initialized! if defined? initialized!
17
- end
18
-
19
- def title
20
- base_title = args.first
21
- base_title ||= shared_step && "#{method_name.capitalize} #{shared_step.name}" || "Untitled #{method_name}"
22
- base_title
23
- end
24
-
25
- def execution_steps(scenario, groups: [])
26
- return [] if condition && !condition.match?(scenario)
27
- return [] unless block
28
- [StepExecution.new(self, groups, &block)]
29
- end
30
- end
31
-
32
- # @private
33
- # Used for action, setup, teardown, verify
34
- class ActionStep < Step
35
- def execution_steps(scenario, groups: [])
36
- steps = []
37
- return steps if condition && !condition.match?(scenario)
38
- convert_args(scenario).each do |step|
39
- if step.is_a?(String)
40
- Lopata::SharedStep.find(step).steps.each do |shared_step|
41
- next if shared_step.condition && !shared_step.condition.match?(scenario)
42
- steps += shared_step.execution_steps(scenario, groups: groups)
43
- end
44
- elsif step.is_a?(Proc)
45
- steps << StepExecution.new(self, groups, &step)
46
- end
47
- end
48
- steps << StepExecution.new(self, groups, &block) if block
49
- steps.reject { |s| !s.block }
50
- end
51
-
52
- def separate_args(args)
53
- args.map { |a| a.is_a?(String) && a =~ /,/ ? a.split(',').map(&:strip) : a }.flatten
54
- end
55
-
56
- def convert_args(scenario)
57
- flat_args = separate_args(args.flatten)
58
- flat_args.map do |arg|
59
- case arg
60
- # trait symbols as link to metadata.
61
- when Symbol then scenario.metadata[arg]
62
- else
63
- arg
64
- end
65
- end.flatten
66
- end
67
-
68
- def title
69
- shared_step && "#{method_name.capitalize} #{shared_step.name}" || "Untitled #{method_name}"
70
- end
71
- end
72
-
73
- # @private
74
- # Used for context
75
- class GroupStep < Step
76
-
77
- def execution_steps(scenario, groups: [])
78
- steps = []
79
- return steps if condition && !condition.match?(scenario)
80
- @steps.each do |step|
81
- steps += step.execution_steps(scenario, groups: groups + [self])
82
- end
83
- steps.reject! { |s| !s.block }
84
- steps.reject { |s| s.teardown_group?(self) } + steps.select { |s| s.teardown_group?(self) }
85
- end
86
-
87
- def let_methods
88
- @let_methods ||= {}
89
- end
90
-
91
- private
92
-
93
- # Group step's block is a block in context of builder, not scenario. So hide the @block to not be used in scenario.
94
- def initialized!
95
- builder = Lopata::ScenarioBuilder.new(title)
96
- builder.instance_exec(&@block)
97
- @steps = builder.steps
98
- @block = nil
99
- end
100
- end
101
-
102
- #@private
103
- class StepExecution
104
- attr_reader :step, :status, :exception, :block, :pending_message, :groups
105
- extend Forwardable
106
- def_delegators :step, :method_name
107
-
108
- class PendingStepFixedError < StandardError; end
109
-
110
- def initialize(step, groups, &block)
111
- @step = step
112
- @status = :not_runned
113
- @exception = nil
114
- @block = block
115
- @groups = groups
116
- end
117
-
118
- def title
119
- group_title = groups.map { |g| "#{g.title}: " }.join
120
- "#{group_title}#{step.title}"
121
- end
122
-
123
- def run(scenario)
124
- @status = :running
125
- begin
126
- run_step(scenario)
127
- if pending?
128
- @status = :failed
129
- raise PendingStepFixedError, 'Expected step to fail since it is pending, but it passed.'
130
- else
131
- @status = :passed
132
- end
133
- rescue Exception => e
134
- @status = :failed unless pending?
135
- @exception = e
136
- end
137
- end
138
-
139
- def run_step(scenario)
140
- return unless block
141
- scenario.instance_exec(&block)
142
- end
143
-
144
- def failed?
145
- status == :failed
146
- end
147
-
148
- def passed?
149
- status == :passed
150
- end
151
-
152
- def skipped?
153
- status == :skipped
154
- end
155
-
156
- def skip!
157
- @status = :skipped
158
- end
159
-
160
- def pending?
161
- status == :pending
162
- end
163
-
164
- def pending!(message = nil)
165
- @status = :pending
166
- @pending_message = message
167
- end
168
-
169
- def teardown?
170
- %i{ teardown cleanup }.include?(method_name)
171
- end
172
-
173
- def teardown_group?(group = nil)
174
- teardown? && self.groups.last == group
175
- end
176
-
177
- def skip_rest_on_failure?
178
- %i{ setup action }.include?(method_name)
179
- end
180
-
181
- # Step metadata is a combination of metadata given for step and all contexts (groups) the step included
182
- def metadata
183
- (groups + [step]).compact.inject({}) { |merged, part| merged.merge(part.metadata) }
184
- end
185
-
186
- # Step methods is a combination of let_methods for all contexts (group) the step included
187
- def let_methods
188
- (groups).compact.inject({}) { |merged, part| merged.merge(part.let_methods) }
189
- end
190
- end
191
- end
1
+ require 'forwardable'
2
+
3
+ module Lopata
4
+ # @private
5
+ class Step
6
+ attr_reader :block, :args, :condition, :method_name, :shared_step
7
+ # metadata overrien by the step.
8
+ attr_accessor :metadata
9
+
10
+ def initialize(method_name, *args, condition: nil, shared_step: nil, &block)
11
+ @method_name = method_name
12
+ @args = args
13
+ @block = block
14
+ @shared_step = shared_step
15
+ @condition = condition
16
+ initialized! if defined? initialized!
17
+ end
18
+
19
+ def title
20
+ base_title = args.first
21
+ base_title ||= shared_step && "#{method_name.capitalize} #{shared_step.name}" || "Untitled #{method_name}"
22
+ base_title
23
+ end
24
+
25
+ def execution_steps(scenario, groups: [])
26
+ return [] if condition && !condition.match?(scenario)
27
+ return [] unless block
28
+ [StepExecution.new(self, groups, &block)]
29
+ end
30
+ end
31
+
32
+ # @private
33
+ # Used for action, setup, teardown, verify
34
+ class ActionStep < Step
35
+ def execution_steps(scenario, groups: [])
36
+ steps = []
37
+ return steps if condition && !condition.match?(scenario)
38
+ convert_args(scenario).each do |step|
39
+ if step.is_a?(String)
40
+ Lopata::SharedStep.find(step).steps.each do |shared_step|
41
+ next if shared_step.condition && !shared_step.condition.match?(scenario)
42
+ steps += shared_step.execution_steps(scenario, groups: groups)
43
+ end
44
+ elsif step.is_a?(Proc)
45
+ steps << StepExecution.new(self, groups, &step)
46
+ end
47
+ end
48
+ steps << StepExecution.new(self, groups, &block) if block
49
+ steps.reject { |s| !s.block }
50
+ end
51
+
52
+ def separate_args(args)
53
+ args.map { |a| a.is_a?(String) && a =~ /,/ ? a.split(',').map(&:strip) : a }.flatten
54
+ end
55
+
56
+ def convert_args(scenario)
57
+ flat_args = separate_args(args.flatten)
58
+ flat_args.map do |arg|
59
+ case arg
60
+ # trait symbols as link to metadata.
61
+ when Symbol then scenario.metadata[arg]
62
+ else
63
+ arg
64
+ end
65
+ end.flatten
66
+ end
67
+
68
+ def title
69
+ shared_step && "#{method_name.capitalize} #{shared_step.name}" || "Untitled #{method_name}"
70
+ end
71
+ end
72
+
73
+ # @private
74
+ # Used for context
75
+ class GroupStep < Step
76
+
77
+ def execution_steps(scenario, groups: [])
78
+ steps = []
79
+ return steps if condition && !condition.match?(scenario)
80
+ @steps.each do |step|
81
+ steps += step.execution_steps(scenario, groups: groups + [self])
82
+ end
83
+ steps.reject! { |s| !s.block }
84
+ steps.reject { |s| s.teardown_group?(self) } + steps.select { |s| s.teardown_group?(self) }
85
+ end
86
+
87
+ def let_methods
88
+ @let_methods ||= {}
89
+ end
90
+
91
+ private
92
+
93
+ # Group step's block is a block in context of builder, not scenario. So hide the @block to not be used in scenario.
94
+ def initialized!
95
+ builder = Lopata::ScenarioBuilder.new(title)
96
+ builder.instance_exec(&@block)
97
+ @steps = builder.steps
98
+ @block = nil
99
+ end
100
+ end
101
+
102
+ #@private
103
+ class StepExecution
104
+ attr_reader :step, :status, :exception, :block, :pending_message, :groups
105
+ extend Forwardable
106
+ def_delegators :step, :method_name
107
+
108
+ class PendingStepFixedError < StandardError; end
109
+
110
+ def initialize(step, groups, &block)
111
+ @step = step
112
+ @status = :not_runned
113
+ @exception = nil
114
+ @block = block
115
+ @groups = groups
116
+ end
117
+
118
+ def title
119
+ group_title = groups.map { |g| "#{g.title}: " }.join
120
+ "#{group_title}#{step.title}"
121
+ end
122
+
123
+ def run(scenario)
124
+ @status = :running
125
+ begin
126
+ run_step(scenario)
127
+ if pending?
128
+ @status = :failed
129
+ raise PendingStepFixedError, 'Expected step to fail since it is pending, but it passed.'
130
+ else
131
+ @status = :passed
132
+ end
133
+ rescue Exception => e
134
+ @status = :failed unless pending?
135
+ @exception = e
136
+ end
137
+ end
138
+
139
+ def run_step(scenario)
140
+ return unless block
141
+ scenario.instance_exec(&block)
142
+ end
143
+
144
+ def failed?
145
+ status == :failed
146
+ end
147
+
148
+ def passed?
149
+ status == :passed
150
+ end
151
+
152
+ def skipped?
153
+ status == :skipped
154
+ end
155
+
156
+ def skip!
157
+ @status = :skipped
158
+ end
159
+
160
+ def pending?
161
+ status == :pending
162
+ end
163
+
164
+ def pending!(message = nil)
165
+ @status = :pending
166
+ @pending_message = message
167
+ end
168
+
169
+ def teardown?
170
+ %i{ teardown cleanup }.include?(method_name)
171
+ end
172
+
173
+ def teardown_group?(group = nil)
174
+ teardown? && self.groups.last == group
175
+ end
176
+
177
+ def skip_rest_on_failure?
178
+ %i{ setup action }.include?(method_name)
179
+ end
180
+
181
+ # Step metadata is a combination of metadata given for step and all contexts (groups) the step included
182
+ def metadata
183
+ (groups + [step]).compact.inject({}) { |merged, part| merged.merge(part.metadata) }
184
+ end
185
+
186
+ # Step methods is a combination of let_methods for all contexts (group) the step included
187
+ def let_methods
188
+ (groups).compact.inject({}) { |merged, part| merged.merge(part.let_methods) }
189
+ end
190
+ end
191
+ end