lopata 0.1.20 → 0.1.22
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/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 +52 -9
- data/lib/lopata/scenario_builder.rb +18 -0
- data/lib/lopata/step.rb +18 -1
- 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: 594efeb814131537b5efdcd66d912bf4557038f47a85e3fad0fb9b17408586fb
|
4
|
+
data.tar.gz: a63860ec22996bd77f569ad3e85060b208eefc392ec79f6e5d3be7dc56ac7418
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 110b59071e44955f890c8df68c6cc1d5180b968d8c93556ddae4a3da29fe253951f9650a36dc7f5dc38ad04e9bbd9e770100332597512c267ae387cfca7b82f0
|
7
|
+
data.tar.gz: f2300be4be7155921fdf1972fd5bc98832daccc3707d80c8f93d51fe806a130914349f978931c09317f629acc57561b564955a07521a66139234229e6b9a7bdc
|
@@ -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
@@ -46,7 +46,7 @@ class Lopata::Scenario
|
|
46
46
|
# @private
|
47
47
|
def method_missing(method, *args, &block)
|
48
48
|
if execution.let_methods.include?(method)
|
49
|
-
|
49
|
+
execution.let_methods[method].call_in_scenario(self, *args)
|
50
50
|
elsif metadata.keys.include?(method)
|
51
51
|
metadata[method]
|
52
52
|
else
|
@@ -129,15 +129,20 @@ class Lopata::Scenario
|
|
129
129
|
end
|
130
130
|
end
|
131
131
|
|
132
|
+
def let_base
|
133
|
+
if current_step && !current_step.groups.empty?
|
134
|
+
current_step.groups.last.let_methods
|
135
|
+
else
|
136
|
+
@let_methods
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
132
140
|
def let(method_name, &block)
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
@let_methods
|
139
|
-
end
|
140
|
-
base[method_name] = block
|
141
|
+
let_base[method_name] = LetMethod.new(&block)
|
142
|
+
end
|
143
|
+
|
144
|
+
def let!(method_name, &block)
|
145
|
+
let_base[method_name] = LetBangMethod.new(&block)
|
141
146
|
end
|
142
147
|
|
143
148
|
def cleanup
|
@@ -147,4 +152,42 @@ class Lopata::Scenario
|
|
147
152
|
@scenario = nil
|
148
153
|
end
|
149
154
|
end
|
155
|
+
|
156
|
+
# @private
|
157
|
+
# let! methods incapsulate cached value and calculation block
|
158
|
+
class LetBangMethod
|
159
|
+
attr_reader :block, :calculated, :value
|
160
|
+
|
161
|
+
alias calculated? calculated
|
162
|
+
|
163
|
+
def initialize(&block)
|
164
|
+
@block = block
|
165
|
+
@calculated = false
|
166
|
+
@value = nil
|
167
|
+
end
|
168
|
+
|
169
|
+
def call_in_scenario(scenario, *args)
|
170
|
+
if calculated?
|
171
|
+
value
|
172
|
+
else
|
173
|
+
@value = scenario.instance_exec(&block)
|
174
|
+
@calculated = true
|
175
|
+
@value
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
# @private
|
181
|
+
# let methods calculates
|
182
|
+
class LetMethod
|
183
|
+
attr_reader :block
|
184
|
+
|
185
|
+
def initialize(&block)
|
186
|
+
@block = block
|
187
|
+
end
|
188
|
+
|
189
|
+
def call_in_scenario(scenario, *args)
|
190
|
+
scenario.instance_exec(*args, &block)
|
191
|
+
end
|
192
|
+
end
|
150
193
|
end
|
@@ -277,6 +277,24 @@ class Lopata::ScenarioBuilder
|
|
277
277
|
end
|
278
278
|
end
|
279
279
|
|
280
|
+
# Define memorized runtime method for the scenario.
|
281
|
+
#
|
282
|
+
# @note
|
283
|
+
# The method to be called via #method_missing, so it wont override already defined methods.
|
284
|
+
#
|
285
|
+
# @example
|
286
|
+
# let!(:started) { Time.now }
|
287
|
+
# it 'started early' do
|
288
|
+
# first_started = started
|
289
|
+
# expect(started).to eq first_started
|
290
|
+
# end
|
291
|
+
def let!(method_name, &block)
|
292
|
+
steps << Lopata::Step.new(:let) do
|
293
|
+
execution.let!(method_name, &block)
|
294
|
+
end
|
295
|
+
end
|
296
|
+
|
297
|
+
|
280
298
|
# @!endgroup
|
281
299
|
|
282
300
|
# @private
|
data/lib/lopata/step.rb
CHANGED
@@ -88,6 +88,10 @@ module Lopata
|
|
88
88
|
@let_methods ||= {}
|
89
89
|
end
|
90
90
|
|
91
|
+
def let_bang_methods
|
92
|
+
@let_bang_methods ||= {}
|
93
|
+
end
|
94
|
+
|
91
95
|
private
|
92
96
|
|
93
97
|
# Group step's block is a block in context of builder, not scenario. So hide the @block to not be used in scenario.
|
@@ -116,10 +120,13 @@ module Lopata
|
|
116
120
|
end
|
117
121
|
|
118
122
|
def title
|
119
|
-
group_title = groups.map { |g| "#{g.title}: " }.join
|
120
123
|
"#{group_title}#{step.title}"
|
121
124
|
end
|
122
125
|
|
126
|
+
def group_title
|
127
|
+
groups.map { |g| "#{g.title}: " }.join
|
128
|
+
end
|
129
|
+
|
123
130
|
def run(scenario)
|
124
131
|
@status = :running
|
125
132
|
begin
|
@@ -166,6 +173,11 @@ module Lopata
|
|
166
173
|
@pending_message = message
|
167
174
|
end
|
168
175
|
|
176
|
+
# Need log this step.
|
177
|
+
def loggable?
|
178
|
+
not %i{ let let! }.include?(method_name)
|
179
|
+
end
|
180
|
+
|
169
181
|
def teardown?
|
170
182
|
%i{ teardown cleanup }.include?(method_name)
|
171
183
|
end
|
@@ -187,5 +199,10 @@ module Lopata
|
|
187
199
|
def let_methods
|
188
200
|
(groups).compact.inject({}) { |merged, part| merged.merge(part.let_methods) }
|
189
201
|
end
|
202
|
+
|
203
|
+
# Step bang methods is a combination of let_bang_methods for all contexts (group) the step included
|
204
|
+
def let_bang_methods
|
205
|
+
(groups).compact.inject({}) { |merged, part| merged.merge(part.let_bang_methods) }
|
206
|
+
end
|
190
207
|
end
|
191
208
|
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.22
|
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-08-18 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.22
|
142
143
|
test_files: []
|