lopata 0.1.21 → 0.1.23
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 +4 -4
- data/lib/lopata/condition.rb +11 -1
- data/lib/lopata/observers/console_output_observer.rb +15 -3
- data/lib/lopata/observers/group_tree.rb +64 -0
- data/lib/lopata/observers/web_logger.rb +23 -1
- data/lib/lopata/scenario.rb +15 -2
- data/lib/lopata/step.rb +60 -7
- data/lib/lopata/version.rb +1 -1
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9404c01f3020e012451ba5cd5c6d91fbec443df94fe961ad9159e296f5783775
|
4
|
+
data.tar.gz: 16523f8e209f6864370912267f5e26955e1cc07708cfc7f31b2d4f324c0a2aec
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2c81b2e83e0df4838d7743dccdc6c79ef689ccb0d8a1caed6bf3ba3ecfd228041841b531881390a5efe369cc05d681feab919b0d0acebea8d48a065c36e0c6be
|
7
|
+
data.tar.gz: 363b3ea67a91e50ead1d51eb23c50856e9a5a8f2a0f524f56fbabd9f72d3c1b5cb4b7254b9bcf6bcc4fbaef57024ffe6a207bb52d277f8eb96e1a3723d1346fc
|
data/lib/lopata/condition.rb
CHANGED
@@ -1,14 +1,19 @@
|
|
1
1
|
module Lopata
|
2
2
|
# @private
|
3
3
|
class Condition
|
4
|
-
attr_reader :condition, :positive
|
4
|
+
attr_reader :condition, :positive, :dynamic
|
5
5
|
def initialize(condition, positive: true)
|
6
6
|
@condition, @positive = condition, positive
|
7
|
+
@dynamic = @condition.is_a?(Proc)
|
7
8
|
end
|
8
9
|
|
9
10
|
alias positive? positive
|
11
|
+
alias dynamic? dynamic
|
10
12
|
|
13
|
+
# Match scenario on build-time.
|
11
14
|
def match?(scenario)
|
15
|
+
# dynamic steps match scenario in build-time: will be verified later
|
16
|
+
return true if dynamic?
|
12
17
|
matched = match_metadata?(scenario)
|
13
18
|
positive? ? matched : !matched
|
14
19
|
end
|
@@ -33,5 +38,10 @@ module Lopata
|
|
33
38
|
end
|
34
39
|
end
|
35
40
|
|
41
|
+
def match_dynamic?(scenario_runtime)
|
42
|
+
return false unless dynamic?
|
43
|
+
matched = scenario_runtime.instance_exec(&condition)
|
44
|
+
positive? ? matched : !matched
|
45
|
+
end
|
36
46
|
end
|
37
47
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require_relative 'backtrace_formatter'
|
2
|
+
require_relative 'group_tree'
|
2
3
|
require 'forwardable'
|
3
4
|
|
4
5
|
module Lopata
|
@@ -34,9 +35,20 @@ module Lopata
|
|
34
35
|
statuses[scenario.status] += 1
|
35
36
|
|
36
37
|
if scenario.failed?
|
37
|
-
scenario.steps.
|
38
|
-
|
39
|
-
|
38
|
+
GroupTree.steps_hierarhy(scenario.steps).walk_through do |step|
|
39
|
+
if step.is_a?(Lopata::StepExecution)
|
40
|
+
next unless step.loggable?
|
41
|
+
puts colored(" #{status_marker(step.status)} #{step.title}", step.status)
|
42
|
+
puts indent(4, backtrace_formatter.error_message(step.exception, include_backtrace: true)) if step.failed?
|
43
|
+
else # GroupTree
|
44
|
+
group = step
|
45
|
+
if %i{ passed skipped }.include?(group.status)
|
46
|
+
puts colored(" #{status_marker(group.status)} #{group.title}", group.status)
|
47
|
+
false
|
48
|
+
else
|
49
|
+
true
|
50
|
+
end
|
51
|
+
end
|
40
52
|
end
|
41
53
|
end
|
42
54
|
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module Lopata
|
2
|
+
GroupTree = Struct.new(:group, :items, :title) do
|
3
|
+
def status
|
4
|
+
# return @status if @status
|
5
|
+
statuses = items.map(&:status).uniq
|
6
|
+
@status =
|
7
|
+
if statuses.length == 1
|
8
|
+
statuses.first
|
9
|
+
elsif statuses.include?(:failed)
|
10
|
+
:failed
|
11
|
+
elsif
|
12
|
+
statuses.first
|
13
|
+
end
|
14
|
+
@status
|
15
|
+
end
|
16
|
+
|
17
|
+
# Returns steps hierarhy: Group with nestet setps or groups
|
18
|
+
def self.steps_hierarhy(steps)
|
19
|
+
top = GroupTree.new(nil, [], '')
|
20
|
+
hierarhy = [top]
|
21
|
+
current_groups = []
|
22
|
+
steps.each do |step|
|
23
|
+
if step.groups == current_groups
|
24
|
+
hierarhy.last.items << step
|
25
|
+
else
|
26
|
+
# ensure hierarhy to is in current step tree - remove from hierary all groups not in new tree.
|
27
|
+
while hierarhy.last.group && !step.groups.include?(hierarhy.last.group)
|
28
|
+
hierarhy.pop
|
29
|
+
end
|
30
|
+
if hierarhy.last.group == step.groups.last
|
31
|
+
hierarhy.last.items << step
|
32
|
+
else
|
33
|
+
group_rest = step.groups.dup
|
34
|
+
while hierarhy.last.group && group_rest.first != hierarhy.last.group
|
35
|
+
group_rest.shift
|
36
|
+
end
|
37
|
+
group_rest.shift if group_rest.first == hierarhy.last.group
|
38
|
+
group_rest.each do
|
39
|
+
title = (hierarhy.map(&:group).compact + [_1]).map(&:title).join(': ')
|
40
|
+
group = GroupTree.new(_1, [], title)
|
41
|
+
hierarhy.last.items << group
|
42
|
+
hierarhy << group
|
43
|
+
end
|
44
|
+
hierarhy.last.items << step
|
45
|
+
end
|
46
|
+
current_groups = step.groups
|
47
|
+
end
|
48
|
+
end
|
49
|
+
return top
|
50
|
+
end
|
51
|
+
|
52
|
+
def walk_through(&block)
|
53
|
+
items.each do |step|
|
54
|
+
if step.is_a?(Lopata::StepExecution)
|
55
|
+
yield step
|
56
|
+
else # GroupTree
|
57
|
+
group = step
|
58
|
+
go_dipper = yield group
|
59
|
+
group.walk_through(&block) if go_dipper
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'httparty'
|
2
2
|
require 'json'
|
3
3
|
require_relative 'backtrace_formatter'
|
4
|
+
require_relative 'group_tree'
|
4
5
|
|
5
6
|
module Lopata
|
6
7
|
module Observers
|
@@ -48,7 +49,24 @@ module Lopata
|
|
48
49
|
|
49
50
|
def add_attempt(scenario, finished)
|
50
51
|
status = scenario.failed? ? Lopata::FAILED : Lopata::PASSED
|
51
|
-
steps =
|
52
|
+
steps = []
|
53
|
+
GroupTree.steps_hierarhy(scenario.steps).walk_through do |step|
|
54
|
+
if step.is_a?(Lopata::StepExecution)
|
55
|
+
next unless step.loggable?
|
56
|
+
steps << step_hash(step)
|
57
|
+
else # GroupTree
|
58
|
+
|
59
|
+
group = step
|
60
|
+
if %i{ passed skipped }.include?(group.status)
|
61
|
+
steps << group_hash(group)
|
62
|
+
false
|
63
|
+
else
|
64
|
+
true
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
steps = scenario.steps.select(&:loggable?).map { |s| step_hash(s) }
|
52
70
|
request = { status: status, steps: steps, launch: { id: @launch_id, finished: finished } }
|
53
71
|
test = test_id(scenario)
|
54
72
|
post("/tests/#{test}/attempts.json", body: request)
|
@@ -67,6 +85,10 @@ module Lopata
|
|
67
85
|
hash
|
68
86
|
end
|
69
87
|
|
88
|
+
def group_hash(group)
|
89
|
+
{ status: group.status, title: group.title }
|
90
|
+
end
|
91
|
+
|
70
92
|
def test_id(scenario)
|
71
93
|
request = {
|
72
94
|
test: {
|
data/lib/lopata/scenario.rb
CHANGED
@@ -90,7 +90,17 @@ class Lopata::Scenario
|
|
90
90
|
end
|
91
91
|
|
92
92
|
def run_step(step)
|
93
|
-
return if step.skipped?
|
93
|
+
return if step.skipped? || step.ignored?
|
94
|
+
groups = step.groups
|
95
|
+
if groups.length > 0 && groups != @current_groups
|
96
|
+
@current_groups = groups
|
97
|
+
condition = groups.last.condition
|
98
|
+
if condition&.dynamic? && !condition.match_dynamic?(scenario)
|
99
|
+
step.ignored!
|
100
|
+
ignore_groups(groups)
|
101
|
+
return
|
102
|
+
end
|
103
|
+
end
|
94
104
|
@current_step = step
|
95
105
|
step.run(scenario)
|
96
106
|
skip_rest if step.failed? && step.skip_rest_on_failure?
|
@@ -113,6 +123,10 @@ class Lopata::Scenario
|
|
113
123
|
steps.select { |s| s.status == :not_runned && !s.teardown? }.each(&:skip!)
|
114
124
|
end
|
115
125
|
|
126
|
+
def ignore_groups(groups)
|
127
|
+
steps.select { _1.status == :not_runned && _1.groups.take(groups.length) == groups }.each(&:ignored!)
|
128
|
+
end
|
129
|
+
|
116
130
|
def metadata
|
117
131
|
if current_step
|
118
132
|
@metadata.merge(current_step.metadata)
|
@@ -145,7 +159,6 @@ class Lopata::Scenario
|
|
145
159
|
let_base[method_name] = LetBangMethod.new(&block)
|
146
160
|
end
|
147
161
|
|
148
|
-
|
149
162
|
def cleanup
|
150
163
|
@title = nil
|
151
164
|
@metadata = nil
|
data/lib/lopata/step.rb
CHANGED
@@ -25,7 +25,7 @@ module Lopata
|
|
25
25
|
def execution_steps(scenario, groups: [])
|
26
26
|
return [] if condition && !condition.match?(scenario)
|
27
27
|
return [] unless block
|
28
|
-
[StepExecution.new(self, groups, &block)]
|
28
|
+
[StepExecution.new(self, groups, condition: condition, &block)]
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
@@ -39,13 +39,14 @@ module Lopata
|
|
39
39
|
if step.is_a?(String)
|
40
40
|
Lopata::SharedStep.find(step).steps.each do |shared_step|
|
41
41
|
next if shared_step.condition && !shared_step.condition.match?(scenario)
|
42
|
-
|
42
|
+
shared_group = SharedGroupStep.new(:shared_step)
|
43
|
+
steps += shared_step.execution_steps(scenario, groups: groups + [shared_group])
|
43
44
|
end
|
44
45
|
elsif step.is_a?(Proc)
|
45
|
-
steps << StepExecution.new(self, groups, &step)
|
46
|
+
steps << StepExecution.new(self, groups, condition: condition, &step)
|
46
47
|
end
|
47
48
|
end
|
48
|
-
steps << StepExecution.new(self, groups, &block) if block
|
49
|
+
steps << StepExecution.new(self, groups, condition: condition, &block) if block
|
49
50
|
steps.reject { |s| !s.block }
|
50
51
|
end
|
51
52
|
|
@@ -103,30 +104,48 @@ module Lopata
|
|
103
104
|
end
|
104
105
|
end
|
105
106
|
|
107
|
+
# @private
|
108
|
+
# Fake group for shared step instance
|
109
|
+
# Used to build group hierarhy including chared steps
|
110
|
+
class SharedGroupStep < Step
|
111
|
+
# stub title - should not be used in scenario/step name generation.
|
112
|
+
def title
|
113
|
+
''
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
106
117
|
#@private
|
107
118
|
class StepExecution
|
108
|
-
attr_reader :step, :status, :exception, :block, :pending_message, :groups
|
119
|
+
attr_reader :step, :status, :exception, :block, :pending_message, :groups, :condition
|
109
120
|
extend Forwardable
|
110
121
|
def_delegators :step, :method_name
|
111
122
|
|
112
123
|
class PendingStepFixedError < StandardError; end
|
113
124
|
|
114
|
-
def initialize(step, groups, &block)
|
125
|
+
def initialize(step, groups, condition: nil, &block)
|
115
126
|
@step = step
|
116
127
|
@status = :not_runned
|
117
128
|
@exception = nil
|
118
129
|
@block = block
|
119
130
|
@groups = groups
|
131
|
+
@condition = condition
|
120
132
|
end
|
121
133
|
|
122
134
|
def title
|
123
|
-
group_title = groups.map { |g| "#{g.title}: " }.join
|
124
135
|
"#{group_title}#{step.title}"
|
125
136
|
end
|
126
137
|
|
138
|
+
def group_title
|
139
|
+
groups.map { |g| "#{g.title}: " }.join
|
140
|
+
end
|
141
|
+
|
127
142
|
def run(scenario)
|
128
143
|
@status = :running
|
129
144
|
begin
|
145
|
+
unless check_dynamic_condition?(scenario)
|
146
|
+
@status = :ignored
|
147
|
+
return
|
148
|
+
end
|
130
149
|
run_step(scenario)
|
131
150
|
if pending?
|
132
151
|
@status = :failed
|
@@ -145,6 +164,22 @@ module Lopata
|
|
145
164
|
scenario.instance_exec(&block)
|
146
165
|
end
|
147
166
|
|
167
|
+
def check_dynamic_condition?(scenario)
|
168
|
+
dynamic_conditions.each do
|
169
|
+
return false unless _1.match_dynamic?(scenario)
|
170
|
+
end
|
171
|
+
true
|
172
|
+
end
|
173
|
+
|
174
|
+
def dynamic_conditions
|
175
|
+
conds = []
|
176
|
+
conds << condition if condition&.dynamic?
|
177
|
+
groups.each do
|
178
|
+
conds << _1.condition if _1.condition&.dynamic?
|
179
|
+
end
|
180
|
+
conds
|
181
|
+
end
|
182
|
+
|
148
183
|
def failed?
|
149
184
|
status == :failed
|
150
185
|
end
|
@@ -157,6 +192,14 @@ module Lopata
|
|
157
192
|
status == :skipped
|
158
193
|
end
|
159
194
|
|
195
|
+
def ignored?
|
196
|
+
status == :ignored
|
197
|
+
end
|
198
|
+
|
199
|
+
def ignored!
|
200
|
+
status == :ignored
|
201
|
+
end
|
202
|
+
|
160
203
|
def skip!
|
161
204
|
@status = :skipped
|
162
205
|
end
|
@@ -170,6 +213,12 @@ module Lopata
|
|
170
213
|
@pending_message = message
|
171
214
|
end
|
172
215
|
|
216
|
+
# Need log this step.
|
217
|
+
def loggable?
|
218
|
+
return false if ignored?
|
219
|
+
not %i{ let let! }.include?(method_name)
|
220
|
+
end
|
221
|
+
|
173
222
|
def teardown?
|
174
223
|
%i{ teardown cleanup }.include?(method_name)
|
175
224
|
end
|
@@ -178,6 +227,10 @@ module Lopata
|
|
178
227
|
teardown? && self.groups.last == group
|
179
228
|
end
|
180
229
|
|
230
|
+
def in_group?(group)
|
231
|
+
groups.include?(group)
|
232
|
+
end
|
233
|
+
|
181
234
|
def skip_rest_on_failure?
|
182
235
|
%i{ setup action }.include?(method_name)
|
183
236
|
end
|
data/lib/lopata/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lopata
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.23
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alexey Volochnev
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-09-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: httparty
|
@@ -107,6 +107,7 @@ files:
|
|
107
107
|
- lib/lopata/observers/backtrace_formatter.rb
|
108
108
|
- lib/lopata/observers/base_observer.rb
|
109
109
|
- lib/lopata/observers/console_output_observer.rb
|
110
|
+
- lib/lopata/observers/group_tree.rb
|
110
111
|
- lib/lopata/observers/web_logger.rb
|
111
112
|
- lib/lopata/role.rb
|
112
113
|
- lib/lopata/runner.rb
|
@@ -138,5 +139,5 @@ requirements: []
|
|
138
139
|
rubygems_version: 3.2.15
|
139
140
|
signing_key:
|
140
141
|
specification_version: 4
|
141
|
-
summary: lopata-0.1.
|
142
|
+
summary: lopata-0.1.23
|
142
143
|
test_files: []
|