lopata 0.1.25 → 0.1.27
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/lopata/observers/console_output_observer.rb +19 -18
- data/lib/lopata/observers/web_logger.rb +24 -19
- data/lib/lopata/runner.rb +8 -0
- data/lib/lopata/scenario.rb +53 -53
- data/lib/lopata/scenario_builder.rb +7 -3
- data/lib/lopata/step.rb +136 -84
- data/lib/lopata/version.rb +1 -1
- metadata +3 -4
- data/lib/lopata/observers/group_tree.rb +0 -64
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b0587bd058d882d2a656a1ab4f4e60ae05f756f2190e5f2b977ea9c97ca9a749
|
4
|
+
data.tar.gz: 97fc9b78d90d71c2ecfdd43d892380b25aed11b3ad03b5370683a601b5aa3a17
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d20009dbd9d904fc2af94df682c2964b74d269871c7d331eacf26536c365b39d830a03308c1aa6eb7399022e21d63a98cb1ec60dbf6d8bac876be1484db725ae
|
7
|
+
data.tar.gz: adf29771c6c191fca1e1dcf7954d5a21a2ae0acf28fabeb94886a8d82e83e4120f74d4610febaace4049ac5be20d28927c0076b9cc1590b8b3fae473e0177fd7
|
@@ -1,5 +1,4 @@
|
|
1
1
|
require_relative 'backtrace_formatter'
|
2
|
-
require_relative 'group_tree'
|
3
2
|
require 'forwardable'
|
4
3
|
|
5
4
|
module Lopata
|
@@ -34,25 +33,27 @@ module Lopata
|
|
34
33
|
statuses[scenario.status] ||= 0
|
35
34
|
statuses[scenario.status] += 1
|
36
35
|
|
37
|
-
if scenario.failed?
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
36
|
+
log_steps(scenario.steps) if scenario.failed?
|
37
|
+
|
38
|
+
flush
|
39
|
+
end
|
40
|
+
|
41
|
+
# @private
|
42
|
+
def log_steps(steps)
|
43
|
+
steps.each do |step|
|
44
|
+
next unless step.loggable?
|
45
|
+
if step.group?
|
46
|
+
status = step.status
|
47
|
+
if %i{ passed skipped ignored }.include?(status)
|
48
|
+
puts colored(" #{status_marker(step.status)} #{step.title}", status)
|
49
|
+
else
|
50
|
+
log_steps(step.steps)
|
51
51
|
end
|
52
|
+
else
|
53
|
+
puts colored(" #{status_marker(step.status)} #{step.title}", step.status)
|
54
|
+
puts indent(4, backtrace_formatter.error_message(step.exception, include_backtrace: true)) if step.failed?
|
52
55
|
end
|
53
56
|
end
|
54
|
-
|
55
|
-
flush
|
56
57
|
end
|
57
58
|
|
58
59
|
private
|
@@ -61,7 +62,7 @@ module Lopata
|
|
61
62
|
case status
|
62
63
|
when :failed then red(text)
|
63
64
|
when :passed then green(text)
|
64
|
-
when :skipped then cyan(text)
|
65
|
+
when :skipped, :ignored then cyan(text)
|
65
66
|
when :pending then yellow(text)
|
66
67
|
else text
|
67
68
|
end
|
@@ -1,7 +1,6 @@
|
|
1
1
|
require 'httparty'
|
2
2
|
require 'json'
|
3
3
|
require_relative 'backtrace_formatter'
|
4
|
-
require_relative 'group_tree'
|
5
4
|
|
6
5
|
module Lopata
|
7
6
|
module Observers
|
@@ -47,26 +46,15 @@ module Lopata
|
|
47
46
|
@launch_id = JSON.parse(post("/projects/#{project_code}/builds/#{build_number}/launches.json", body: {total: count}).body)['id']
|
48
47
|
end
|
49
48
|
|
49
|
+
# Create test stubs for all the scenarios within then build
|
50
|
+
def init_scenarios(world)
|
51
|
+
post("/projects/#{project_code}/builds/#{build_number}/tests.json",
|
52
|
+
body: { scenarios: world.scenarios.map { { title: _1.title } } })
|
53
|
+
end
|
54
|
+
|
50
55
|
def add_attempt(scenario, finished)
|
51
56
|
status = scenario.failed? ? Lopata::FAILED : Lopata::PASSED
|
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) }
|
57
|
+
steps = build_hashes(scenario.steps)
|
70
58
|
request = { status: status, steps: steps, launch: { id: @launch_id, finished: finished } }
|
71
59
|
test = test_id(scenario)
|
72
60
|
post("/tests/#{test}/attempts.json", body: request)
|
@@ -76,6 +64,23 @@ module Lopata
|
|
76
64
|
puts e.backtrace
|
77
65
|
end
|
78
66
|
|
67
|
+
def build_hashes(steps)
|
68
|
+
hashes = []
|
69
|
+
steps.each do |step|
|
70
|
+
next unless step.loggable?
|
71
|
+
if step.group?
|
72
|
+
if %i{ passed skipped ignored }.include?(step.status)
|
73
|
+
hashes << group_hash(step)
|
74
|
+
else
|
75
|
+
hashes += build_hashes(step.steps)
|
76
|
+
end
|
77
|
+
else
|
78
|
+
hashes << step_hash(step)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
hashes
|
82
|
+
end
|
83
|
+
|
79
84
|
def step_hash(step)
|
80
85
|
hash = { status: step.status, title: step.title }
|
81
86
|
if step.failed?
|
data/lib/lopata/runner.rb
CHANGED
@@ -15,6 +15,7 @@ module Lopata
|
|
15
15
|
option :keep, type: :boolean, aliases: 'k'
|
16
16
|
option :text, aliases: 't'
|
17
17
|
option :list, type: :boolean, aliases: 'l'
|
18
|
+
option :init, type: :boolean, aliases: 'i'
|
18
19
|
def test(*args)
|
19
20
|
trap_interrupt
|
20
21
|
configure_from_options
|
@@ -22,6 +23,8 @@ module Lopata
|
|
22
23
|
Lopata::Loader.load_scenarios(*args)
|
23
24
|
if options[:list]
|
24
25
|
list_scenarios
|
26
|
+
elsif
|
27
|
+
init_scenarios
|
25
28
|
else
|
26
29
|
run_scenarios
|
27
30
|
end
|
@@ -64,6 +67,11 @@ module Lopata
|
|
64
67
|
Lopata.world.scenarios.each { |s| puts s.title }
|
65
68
|
end
|
66
69
|
|
70
|
+
def init_scenarios
|
71
|
+
client = Lopata::Client.new
|
72
|
+
client.init_scenarios(Lopata.world)
|
73
|
+
end
|
74
|
+
|
67
75
|
def run_scenarios
|
68
76
|
world = Lopata.world
|
69
77
|
world.notify_observers(:started, world)
|
data/lib/lopata/scenario.rb
CHANGED
@@ -45,8 +45,9 @@ class Lopata::Scenario
|
|
45
45
|
|
46
46
|
# @private
|
47
47
|
def method_missing(method, *args, &block)
|
48
|
-
|
49
|
-
|
48
|
+
|
49
|
+
if (let_method = execution.find_let_method(method))
|
50
|
+
let_method.call_in_scenario(self, *args)
|
50
51
|
elsif metadata.keys.include?(method)
|
51
52
|
metadata[method]
|
52
53
|
else
|
@@ -56,21 +57,18 @@ class Lopata::Scenario
|
|
56
57
|
|
57
58
|
# @private
|
58
59
|
def respond_to_missing?(method, *)
|
59
|
-
execution.
|
60
|
+
execution.find_let_method(method) or metadata.keys.include?(method) or super
|
60
61
|
end
|
61
62
|
|
62
63
|
# @private
|
63
64
|
# Scenario execution and live-cycle information
|
64
65
|
class Execution
|
65
|
-
attr_reader :scenario, :
|
66
|
-
|
67
|
-
def initialize(title,
|
68
|
-
@title = [title, options_title].compact.reject(&:empty?).join(' ')
|
69
|
-
@metadata = metadata
|
70
|
-
@let_methods = {}
|
71
|
-
@status = :not_runned
|
72
|
-
@steps = []
|
66
|
+
attr_reader :scenario, :current_step, :top
|
67
|
+
|
68
|
+
def initialize(title, metadata = {})
|
73
69
|
@scenario = Lopata::Scenario.new(self)
|
70
|
+
@top = Lopata::GroupExecution.new(Lopata::TopStep.new(title, metadata: metadata), nil, steps: [])
|
71
|
+
@current_step = @top
|
74
72
|
end
|
75
73
|
|
76
74
|
# Provide a human-readable representation of this class
|
@@ -79,32 +77,42 @@ class Lopata::Scenario
|
|
79
77
|
end
|
80
78
|
alias to_s inspect
|
81
79
|
|
80
|
+
def steps
|
81
|
+
top.steps
|
82
|
+
end
|
83
|
+
|
82
84
|
def run
|
83
|
-
@status = :running
|
84
|
-
sort_steps
|
85
85
|
world.notify_observers(:scenario_started, self)
|
86
|
-
|
87
|
-
@status = steps.any?(&:failed?) ? :failed : :passed
|
86
|
+
run_step(top)
|
88
87
|
world.notify_observers(:scenario_finished, self)
|
89
88
|
cleanup
|
90
89
|
end
|
91
90
|
|
92
91
|
def run_step(step)
|
93
|
-
|
94
|
-
|
95
|
-
if
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
92
|
+
@current_step = step
|
93
|
+
return :skipped if step.skipped?
|
94
|
+
return :ignored if step.ignored?
|
95
|
+
if step.condition&.dynamic && !step.condition.match_dynamic?(scenario)
|
96
|
+
step.ignored!
|
97
|
+
return :ignored
|
98
|
+
end
|
99
|
+
if step.group?
|
100
|
+
skip_rest = false
|
101
|
+
step.steps.each do
|
102
|
+
if _1.teardown?
|
103
|
+
run_step(_1)
|
104
|
+
elsif skip_rest
|
105
|
+
_1.skip!
|
106
|
+
else
|
107
|
+
run_step(_1)
|
108
|
+
skip_rest = true if _1.failed? && _1.skip_rest_on_failure?
|
109
|
+
end
|
102
110
|
end
|
111
|
+
step.status!
|
112
|
+
else
|
113
|
+
step.run(scenario)
|
114
|
+
step.status
|
103
115
|
end
|
104
|
-
@current_step = step
|
105
|
-
step.run(scenario)
|
106
|
-
skip_rest if step.failed? && step.skip_rest_on_failure?
|
107
|
-
@current_step = nil
|
108
116
|
end
|
109
117
|
|
110
118
|
def world
|
@@ -115,55 +123,47 @@ class Lopata::Scenario
|
|
115
123
|
status == :failed
|
116
124
|
end
|
117
125
|
|
118
|
-
def
|
119
|
-
|
126
|
+
def metadata
|
127
|
+
current_step.metadata
|
120
128
|
end
|
121
129
|
|
122
|
-
def
|
123
|
-
|
130
|
+
def let_methods
|
131
|
+
current_step.let_methods
|
124
132
|
end
|
125
133
|
|
126
|
-
def
|
127
|
-
|
134
|
+
def find_let_method(name)
|
135
|
+
current_step.find_let_method(name)
|
128
136
|
end
|
129
137
|
|
130
|
-
def
|
131
|
-
|
132
|
-
@metadata.merge(current_step.metadata)
|
133
|
-
else
|
134
|
-
@metadata
|
135
|
-
end
|
138
|
+
def title
|
139
|
+
top.title
|
136
140
|
end
|
137
141
|
|
138
|
-
def
|
139
|
-
|
140
|
-
@let_methods.merge(current_step.let_methods)
|
141
|
-
else
|
142
|
-
@let_methods
|
143
|
-
end
|
142
|
+
def status
|
143
|
+
top.status
|
144
144
|
end
|
145
145
|
|
146
146
|
def let_base
|
147
|
-
if current_step
|
148
|
-
current_step
|
147
|
+
if current_step.group?
|
148
|
+
current_step
|
149
149
|
else
|
150
|
-
|
150
|
+
current_step.parent
|
151
151
|
end
|
152
152
|
end
|
153
153
|
|
154
154
|
def let(method_name, &block)
|
155
|
-
let_base
|
155
|
+
let_base.add_let_method(method_name, LetMethod.new(&block))
|
156
156
|
end
|
157
157
|
|
158
158
|
def let!(method_name, &block)
|
159
|
-
let_base
|
159
|
+
let_base.add_let_method(method_name, LetBangMethod.new(&block))
|
160
160
|
end
|
161
161
|
|
162
162
|
def cleanup
|
163
163
|
@title = nil
|
164
|
-
@metadata = nil
|
165
|
-
@steps = nil
|
166
164
|
@scenario = nil
|
165
|
+
@top = nil
|
166
|
+
@current_step = nil
|
167
167
|
end
|
168
168
|
end
|
169
169
|
|
@@ -38,16 +38,20 @@ class Lopata::ScenarioBuilder
|
|
38
38
|
filters = Lopata.configuration.filters
|
39
39
|
option_combinations.each do |option_set|
|
40
40
|
metadata = common_metadata.merge(option_set.metadata)
|
41
|
-
|
42
|
-
|
41
|
+
scenario_title = [title, option_set.title].compact.reject(&:empty?).join(' ')
|
42
|
+
scenario = Lopata::Scenario::Execution.new(scenario_title, metadata)
|
43
|
+
|
43
44
|
unless filters.empty?
|
44
45
|
next unless filters.all? { |f| f[scenario] }
|
45
46
|
end
|
46
47
|
|
48
|
+
exec_steps = []
|
47
49
|
steps_with_hooks.each do |step|
|
48
50
|
next if step.condition && !step.condition.match?(scenario)
|
49
|
-
step.execution_steps(scenario).each { |s|
|
51
|
+
step.execution_steps(scenario, parent: scenario.top).each { |s| exec_steps << s }
|
50
52
|
end
|
53
|
+
scenario.steps.push(*exec_steps.reject(&:teardown?))
|
54
|
+
scenario.steps.push(*exec_steps.select(&:teardown?))
|
51
55
|
|
52
56
|
world.scenarios << scenario
|
53
57
|
end
|
data/lib/lopata/step.rb
CHANGED
@@ -7,12 +7,13 @@ module Lopata
|
|
7
7
|
# metadata overrien by the step.
|
8
8
|
attr_accessor :metadata
|
9
9
|
|
10
|
-
def initialize(method_name, *args, condition: nil, shared_step: nil, &block)
|
10
|
+
def initialize(method_name, *args, condition: nil, shared_step: nil, metadata: {}, &block)
|
11
11
|
@method_name = method_name
|
12
12
|
@args = args
|
13
13
|
@block = block
|
14
14
|
@shared_step = shared_step
|
15
15
|
@condition = condition
|
16
|
+
@metadata = metadata
|
16
17
|
initialized! if defined? initialized!
|
17
18
|
end
|
18
19
|
|
@@ -22,31 +23,31 @@ module Lopata
|
|
22
23
|
base_title
|
23
24
|
end
|
24
25
|
|
25
|
-
def execution_steps(scenario,
|
26
|
+
def execution_steps(scenario, parent:)
|
26
27
|
return [] if condition && !condition.match?(scenario)
|
27
28
|
return [] unless block
|
28
|
-
[StepExecution.new(self,
|
29
|
+
[StepExecution.new(self, parent, condition: condition, &block)]
|
29
30
|
end
|
30
31
|
end
|
31
32
|
|
32
33
|
# @private
|
33
34
|
# Used for action, setup, teardown, verify
|
34
35
|
class ActionStep < Step
|
35
|
-
def execution_steps(scenario,
|
36
|
+
def execution_steps(scenario, parent:)
|
36
37
|
steps = []
|
37
38
|
return steps if condition && !condition.match?(scenario)
|
38
39
|
convert_args(scenario).each do |step|
|
39
40
|
if step.is_a?(String)
|
40
41
|
Lopata::SharedStep.find(step).steps.each do |shared_step|
|
41
42
|
next if shared_step.condition && !shared_step.condition.match?(scenario)
|
42
|
-
steps += shared_step.execution_steps(scenario,
|
43
|
+
steps += shared_step.execution_steps(scenario, parent: parent)
|
43
44
|
end
|
44
45
|
elsif step.is_a?(Proc)
|
45
|
-
steps << StepExecution.new(self,
|
46
|
+
steps << StepExecution.new(self, parent, condition: condition, &step)
|
46
47
|
end
|
47
48
|
end
|
48
|
-
steps << StepExecution.new(self,
|
49
|
-
steps
|
49
|
+
steps << StepExecution.new(self, parent, condition: condition, &block) if block
|
50
|
+
steps
|
50
51
|
end
|
51
52
|
|
52
53
|
def separate_args(args)
|
@@ -74,22 +75,18 @@ module Lopata
|
|
74
75
|
# Used for context
|
75
76
|
class GroupStep < Step
|
76
77
|
|
77
|
-
def execution_steps(scenario,
|
78
|
+
def execution_steps(scenario, parent: nil)
|
78
79
|
steps = []
|
79
80
|
return steps if condition && !condition.match?(scenario)
|
81
|
+
group = GroupExecution.new(self, parent, steps: steps, condition: condition)
|
80
82
|
@steps.each do |step|
|
81
|
-
steps += step.execution_steps(scenario,
|
83
|
+
steps += step.execution_steps(scenario, parent: group)
|
82
84
|
end
|
83
|
-
steps.reject
|
84
|
-
steps.
|
85
|
+
group.steps.push(*steps.reject(&:teardown?))
|
86
|
+
group.steps.push(*steps.select(&:teardown?))
|
87
|
+
[group]
|
85
88
|
end
|
86
89
|
|
87
|
-
def let_methods
|
88
|
-
@let_methods ||= {}
|
89
|
-
end
|
90
|
-
|
91
|
-
private
|
92
|
-
|
93
90
|
# Group step's block is a block in context of builder, not scenario. So hide the @block to not be used in scenario.
|
94
91
|
def initialized!
|
95
92
|
builder = Lopata::ScenarioBuilder.new(title)
|
@@ -99,70 +96,60 @@ module Lopata
|
|
99
96
|
end
|
100
97
|
end
|
101
98
|
|
102
|
-
|
103
|
-
class
|
104
|
-
|
99
|
+
# @private
|
100
|
+
class TopStep < Step
|
101
|
+
def initialize(title, metadata: {})
|
102
|
+
super(:top, title, metadata: metadata)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
# @private
|
107
|
+
# Abstract execution step. Composition, may be group or step.
|
108
|
+
class BaseExecution
|
109
|
+
attr_reader :step, :status, :parent, :condition
|
105
110
|
extend Forwardable
|
106
111
|
def_delegators :step, :method_name
|
107
112
|
|
108
|
-
|
109
|
-
|
110
|
-
def initialize(step, groups, condition: nil, &block)
|
113
|
+
def initialize(step, parent, condition: nil)
|
111
114
|
@step = step
|
115
|
+
@parent = parent
|
112
116
|
@status = :not_runned
|
113
|
-
@exception = nil
|
114
|
-
@block = block
|
115
|
-
@groups = groups
|
116
117
|
@condition = condition
|
117
118
|
end
|
118
119
|
|
119
|
-
def
|
120
|
-
|
120
|
+
def group?
|
121
|
+
false
|
121
122
|
end
|
122
123
|
|
123
|
-
def
|
124
|
-
|
124
|
+
def top?
|
125
|
+
!parent
|
125
126
|
end
|
126
127
|
|
127
|
-
def
|
128
|
-
|
129
|
-
begin
|
130
|
-
unless check_dynamic_condition?(scenario)
|
131
|
-
@status = :ignored
|
132
|
-
return
|
133
|
-
end
|
134
|
-
run_step(scenario)
|
135
|
-
if pending?
|
136
|
-
@status = :failed
|
137
|
-
raise PendingStepFixedError, 'Expected step to fail since it is pending, but it passed.'
|
138
|
-
else
|
139
|
-
@status = :passed
|
140
|
-
end
|
141
|
-
rescue Exception => e
|
142
|
-
@status = :failed unless pending?
|
143
|
-
@exception = e
|
144
|
-
end
|
128
|
+
def teardown?
|
129
|
+
%i{ teardown cleanup }.include?(method_name)
|
145
130
|
end
|
146
131
|
|
147
|
-
def
|
148
|
-
|
149
|
-
|
132
|
+
def parents
|
133
|
+
result = []
|
134
|
+
prnt = parent
|
135
|
+
while prnt
|
136
|
+
result << prnt
|
137
|
+
prnt = prnt.parent
|
138
|
+
end
|
139
|
+
result
|
150
140
|
end
|
151
141
|
|
152
|
-
|
153
|
-
|
154
|
-
|
142
|
+
# Step metadata is a combination of metadata given for step and all contexts (groups) the step included
|
143
|
+
def metadata
|
144
|
+
result = step.metadata || {}
|
145
|
+
if parent
|
146
|
+
result = parent.metadata.merge(result)
|
155
147
|
end
|
156
|
-
|
148
|
+
result
|
157
149
|
end
|
158
150
|
|
159
|
-
def
|
160
|
-
|
161
|
-
conds << condition if condition&.dynamic?
|
162
|
-
groups.each do
|
163
|
-
conds << _1.condition if _1.condition&.dynamic?
|
164
|
-
end
|
165
|
-
conds
|
151
|
+
def find_let_method(name)
|
152
|
+
parent&.find_let_method(name)
|
166
153
|
end
|
167
154
|
|
168
155
|
def failed?
|
@@ -189,13 +176,12 @@ module Lopata
|
|
189
176
|
@status = :skipped
|
190
177
|
end
|
191
178
|
|
192
|
-
def
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
@pending_message = message
|
179
|
+
def title
|
180
|
+
if parent && !parent.top?
|
181
|
+
"#{parent.title}: #{step.title}"
|
182
|
+
else
|
183
|
+
step.title
|
184
|
+
end
|
199
185
|
end
|
200
186
|
|
201
187
|
# Need log this step.
|
@@ -204,30 +190,96 @@ module Lopata
|
|
204
190
|
not %i{ let let! }.include?(method_name)
|
205
191
|
end
|
206
192
|
|
207
|
-
def
|
208
|
-
%i{
|
193
|
+
def skip_rest_on_failure?
|
194
|
+
%i{ setup action }.include?(method_name)
|
209
195
|
end
|
196
|
+
end
|
210
197
|
|
211
|
-
|
212
|
-
|
198
|
+
# @private
|
199
|
+
class GroupExecution < BaseExecution
|
200
|
+
attr_reader :steps
|
201
|
+
|
202
|
+
def initialize(step, parent, condition: nil, steps:)
|
203
|
+
super(step, parent, condition: condition)
|
204
|
+
@steps = steps
|
205
|
+
@let_methods = {}
|
213
206
|
end
|
214
207
|
|
215
|
-
def
|
216
|
-
|
208
|
+
def group?
|
209
|
+
true
|
217
210
|
end
|
218
211
|
|
219
|
-
def
|
220
|
-
|
212
|
+
def status!
|
213
|
+
# return @status if @status
|
214
|
+
statuses = steps.map(&:status!).uniq
|
215
|
+
@status =
|
216
|
+
if statuses.length == 1
|
217
|
+
statuses.first
|
218
|
+
elsif statuses.include?(:failed)
|
219
|
+
:failed
|
220
|
+
else
|
221
|
+
statuses.first || :skipped
|
222
|
+
end
|
223
|
+
@status = :passed if @status == :pending
|
224
|
+
@status
|
221
225
|
end
|
222
226
|
|
223
|
-
|
224
|
-
|
225
|
-
|
227
|
+
def find_let_method(name)
|
228
|
+
@let_methods[name] || parent&.find_let_method(name)
|
229
|
+
end
|
230
|
+
|
231
|
+
def add_let_method(name, method)
|
232
|
+
@let_methods[name] = method
|
233
|
+
end
|
234
|
+
|
235
|
+
def ignored!
|
236
|
+
@status = :ignored
|
237
|
+
steps.each(&:ignored!)
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
# @private
|
242
|
+
class StepExecution < BaseExecution
|
243
|
+
attr_reader :exception, :block, :pending_message
|
244
|
+
|
245
|
+
class PendingStepFixedError < StandardError; end
|
246
|
+
|
247
|
+
def initialize(step, parent, condition: nil, &block)
|
248
|
+
super(step, parent, condition: condition)
|
249
|
+
@exception = nil
|
250
|
+
@block = block
|
251
|
+
end
|
252
|
+
|
253
|
+
alias status! status
|
254
|
+
|
255
|
+
def run(scenario)
|
256
|
+
@status = :running
|
257
|
+
begin
|
258
|
+
run_step(scenario)
|
259
|
+
if pending?
|
260
|
+
@status = :failed
|
261
|
+
raise PendingStepFixedError, 'Expected step to fail since it is pending, but it passed.'
|
262
|
+
else
|
263
|
+
@status = :passed
|
264
|
+
end
|
265
|
+
rescue Exception => e
|
266
|
+
@status = :failed unless pending?
|
267
|
+
@exception = e
|
268
|
+
end
|
226
269
|
end
|
227
270
|
|
228
|
-
|
229
|
-
|
230
|
-
|
271
|
+
def run_step(scenario)
|
272
|
+
return unless block
|
273
|
+
scenario.instance_exec(&block)
|
274
|
+
end
|
275
|
+
|
276
|
+
def pending?
|
277
|
+
status == :pending
|
278
|
+
end
|
279
|
+
|
280
|
+
def pending!(message = nil)
|
281
|
+
@status = :pending
|
282
|
+
@pending_message = message
|
231
283
|
end
|
232
284
|
end
|
233
285
|
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.27
|
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-12-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: httparty
|
@@ -107,7 +107,6 @@ 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
|
111
110
|
- lib/lopata/observers/web_logger.rb
|
112
111
|
- lib/lopata/role.rb
|
113
112
|
- lib/lopata/runner.rb
|
@@ -139,5 +138,5 @@ requirements: []
|
|
139
138
|
rubygems_version: 3.2.15
|
140
139
|
signing_key:
|
141
140
|
specification_version: 4
|
142
|
-
summary: lopata-0.1.
|
141
|
+
summary: lopata-0.1.27
|
143
142
|
test_files: []
|
@@ -1,64 +0,0 @@
|
|
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
|