lopata 0.1.1 → 0.1.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +6 -2
- data/exe/lopata +1 -1
- data/lib/lopata.rb +54 -1
- data/lib/lopata/active_record.rb +99 -0
- data/lib/lopata/condition.rb +2 -3
- data/lib/lopata/configuration.rb +126 -0
- data/lib/lopata/environment.rb +36 -0
- data/lib/lopata/factory_bot.rb +36 -0
- data/lib/lopata/generators/app.rb +0 -2
- data/lib/lopata/generators/templates/Gemfile +0 -2
- data/lib/lopata/generators/templates/config/environments/qa.yml +0 -1
- data/lib/lopata/observers/backtrace_formatter.rb +103 -0
- data/lib/lopata/observers/base_observer.rb +17 -6
- data/lib/lopata/observers/console_output_observer.rb +63 -26
- data/lib/lopata/observers/web_logger.rb +57 -59
- data/lib/lopata/role.rb +46 -0
- data/lib/lopata/runner.rb +18 -17
- data/lib/lopata/scenario.rb +94 -34
- data/lib/lopata/scenario_builder.rb +62 -73
- data/lib/lopata/shared_step.rb +10 -4
- data/lib/lopata/step.rb +143 -44
- data/lib/lopata/version.rb +1 -1
- data/lib/lopata/world.rb +3 -1
- metadata +10 -10
- data/lib/lopata/config.rb +0 -101
- data/lib/lopata/generators/templates/.rspec +0 -3
- data/lib/lopata/generators/templates/spec/spec_helper.rb +0 -2
- data/lib/lopata/rspec/ar_dsl.rb +0 -38
- data/lib/lopata/rspec/dsl.rb +0 -39
- data/lib/lopata/rspec/role.rb +0 -75
data/lib/lopata/shared_step.rb
CHANGED
@@ -2,16 +2,15 @@ module Lopata
|
|
2
2
|
class SharedStep
|
3
3
|
attr_reader :name, :block
|
4
4
|
|
5
|
-
class
|
5
|
+
class NotFound < StandardError; end
|
6
6
|
|
7
7
|
def self.register(name, &block)
|
8
8
|
raise ArgumentError, "Comma is not allowed in shared step name: '%s'" % name if name =~ /,/
|
9
|
-
|
10
|
-
@shared_steps[name] = new(name, &block)
|
9
|
+
registry[name] = new(name, &block)
|
11
10
|
end
|
12
11
|
|
13
12
|
def self.find(name)
|
14
|
-
|
13
|
+
registry[name] or raise NotFound, "Shared step '%s' not found" % name
|
15
14
|
end
|
16
15
|
|
17
16
|
def initialize(name, &block)
|
@@ -24,8 +23,15 @@ module Lopata
|
|
24
23
|
|
25
24
|
def build_steps
|
26
25
|
builder = Lopata::ScenarioBuilder.new(name)
|
26
|
+
builder.shared_step = self
|
27
27
|
builder.instance_exec(&block)
|
28
28
|
builder.steps
|
29
29
|
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def self.registry
|
34
|
+
@shared_steps ||= {}
|
35
|
+
end
|
30
36
|
end
|
31
37
|
end
|
data/lib/lopata/step.rb
CHANGED
@@ -1,69 +1,48 @@
|
|
1
1
|
module Lopata
|
2
2
|
class Step
|
3
|
-
attr_reader :block, :
|
3
|
+
attr_reader :block, :args, :condition, :method_name, :shared_step
|
4
|
+
# metadata overrien by the step.
|
5
|
+
attr_accessor :metadata
|
4
6
|
|
5
|
-
def initialize(method_name, *args, condition: nil, &block)
|
7
|
+
def initialize(method_name, *args, condition: nil, shared_step: nil, &block)
|
6
8
|
@method_name = method_name
|
7
9
|
@args = args
|
8
|
-
@status = :not_started
|
9
10
|
@block = block
|
10
|
-
@
|
11
|
-
@condition = condition
|
12
|
-
|
13
|
-
|
14
|
-
def run(scenario)
|
15
|
-
@status = :running
|
16
|
-
world.notify_observers(:step_started, self)
|
17
|
-
begin
|
18
|
-
run_step(scenario)
|
19
|
-
@status = :passed
|
20
|
-
rescue Exception => e
|
21
|
-
@status = :failed
|
22
|
-
@exception = e
|
23
|
-
end
|
24
|
-
world.notify_observers(:step_finished, self)
|
25
|
-
end
|
26
|
-
|
27
|
-
def run_step(scenario)
|
28
|
-
scenario.instance_exec(&block) if block
|
29
|
-
end
|
30
|
-
|
31
|
-
def world
|
32
|
-
@world ||= Lopata::Config.world
|
11
|
+
@shared_step = shared_step
|
12
|
+
@condition = condition
|
13
|
+
initialized! if defined? initialized!
|
33
14
|
end
|
34
15
|
|
35
|
-
def
|
36
|
-
|
16
|
+
def title
|
17
|
+
base_title = args.first
|
18
|
+
base_title ||= shared_step && "#{method_name.capitalize} #{shared_step.name}" || "Untitled #{method_name}"
|
19
|
+
base_title
|
37
20
|
end
|
38
21
|
|
39
|
-
def
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
def teardown?
|
44
|
-
%i{ teardown cleanup }.include?(@method_name)
|
45
|
-
end
|
46
|
-
|
47
|
-
def pre_steps(scenario)
|
48
|
-
[]
|
22
|
+
def execution_steps(scenario, groups: [])
|
23
|
+
return [] if condition && !condition.match?(scenario)
|
24
|
+
return [] unless block
|
25
|
+
[StepExecution.new(self, groups, &block)]
|
49
26
|
end
|
50
27
|
end
|
51
28
|
|
52
29
|
# Used for action, setup, teardown
|
53
30
|
class ActionStep < Step
|
54
|
-
def
|
31
|
+
def execution_steps(scenario, groups: [])
|
55
32
|
steps = []
|
33
|
+
return steps if condition && !condition.match?(scenario)
|
56
34
|
convert_args(scenario).each do |step|
|
57
35
|
if step.is_a?(String)
|
58
36
|
Lopata::SharedStep.find(step).steps.each do |shared_step|
|
59
|
-
|
60
|
-
steps
|
37
|
+
next if shared_step.condition && !shared_step.condition.match?(scenario)
|
38
|
+
steps += shared_step.execution_steps(scenario, groups: groups)
|
61
39
|
end
|
62
40
|
elsif step.is_a?(Proc)
|
63
|
-
steps <<
|
41
|
+
steps << StepExecution.new(self, groups, &step)
|
64
42
|
end
|
65
43
|
end
|
66
|
-
steps
|
44
|
+
steps << StepExecution.new(self, groups, &block) if block
|
45
|
+
steps.reject { |s| !s.block }
|
67
46
|
end
|
68
47
|
|
69
48
|
def separate_args(args)
|
@@ -82,5 +61,125 @@ module Lopata
|
|
82
61
|
end.flatten
|
83
62
|
end
|
84
63
|
|
64
|
+
def title
|
65
|
+
shared_step && "#{method_name.capitalize} #{shared_step.name}" || "Untitled #{method_name}"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# Used for context
|
70
|
+
class GroupStep < Step
|
71
|
+
|
72
|
+
def execution_steps(scenario, groups: [])
|
73
|
+
steps = []
|
74
|
+
return steps if condition && !condition.match?(scenario)
|
75
|
+
@steps.each do |step|
|
76
|
+
steps += step.execution_steps(scenario, groups: groups + [self])
|
77
|
+
end
|
78
|
+
steps.reject! { |s| !s.block }
|
79
|
+
steps.reject { |s| s.teardown_group?(self) } + steps.select { |s| s.teardown_group?(self) }
|
80
|
+
end
|
81
|
+
|
82
|
+
def let_methods
|
83
|
+
@let_methods ||= {}
|
84
|
+
end
|
85
|
+
|
86
|
+
private
|
87
|
+
|
88
|
+
# Group step's block is a block in context of builder, not scenario. So hide the @block to not be used in scenario.
|
89
|
+
def initialized!
|
90
|
+
builder = Lopata::ScenarioBuilder.new(title)
|
91
|
+
builder.instance_exec(&@block)
|
92
|
+
@steps = builder.steps
|
93
|
+
@block = nil
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
class StepExecution
|
98
|
+
attr_reader :step, :status, :exception, :block, :pending_message, :groups
|
99
|
+
extend Forwardable
|
100
|
+
def_delegators :step, :method_name
|
101
|
+
|
102
|
+
class PendingStepFixedError < StandardError; end
|
103
|
+
|
104
|
+
def initialize(step, groups, &block)
|
105
|
+
@step = step
|
106
|
+
@status = :not_runned
|
107
|
+
@exception = nil
|
108
|
+
@block = block
|
109
|
+
@groups = groups
|
110
|
+
end
|
111
|
+
|
112
|
+
def title
|
113
|
+
group_title = groups.map { |g| "#{g.title}: " }.join
|
114
|
+
"#{group_title}#{step.title}"
|
115
|
+
end
|
116
|
+
|
117
|
+
def run(scenario)
|
118
|
+
@status = :running
|
119
|
+
begin
|
120
|
+
run_step(scenario)
|
121
|
+
if pending?
|
122
|
+
@status = :failed
|
123
|
+
raise PendingStepFixedError, 'Expected step to fail since it is pending, but it passed.'
|
124
|
+
else
|
125
|
+
@status = :passed
|
126
|
+
end
|
127
|
+
rescue Exception => e
|
128
|
+
@status = :failed unless pending?
|
129
|
+
@exception = e
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
def run_step(scenario)
|
134
|
+
return unless block
|
135
|
+
scenario.instance_exec(&block)
|
136
|
+
end
|
137
|
+
|
138
|
+
def failed?
|
139
|
+
status == :failed
|
140
|
+
end
|
141
|
+
|
142
|
+
def passed?
|
143
|
+
status == :passed
|
144
|
+
end
|
145
|
+
|
146
|
+
def skipped?
|
147
|
+
status == :skipped
|
148
|
+
end
|
149
|
+
|
150
|
+
def skip!
|
151
|
+
@status = :skipped
|
152
|
+
end
|
153
|
+
|
154
|
+
def pending?
|
155
|
+
status == :pending
|
156
|
+
end
|
157
|
+
|
158
|
+
def pending!(message = nil)
|
159
|
+
@status = :pending
|
160
|
+
@pending_message = message
|
161
|
+
end
|
162
|
+
|
163
|
+
def teardown?
|
164
|
+
%i{ teardown cleanup }.include?(method_name)
|
165
|
+
end
|
166
|
+
|
167
|
+
def teardown_group?(group = nil)
|
168
|
+
teardown? && self.groups.last == group
|
169
|
+
end
|
170
|
+
|
171
|
+
def skip_rest_on_failure?
|
172
|
+
%i{ setup action }.include?(method_name)
|
173
|
+
end
|
174
|
+
|
175
|
+
# Step metadata is a combination of metadata given for step and all contexts (groups) the step included
|
176
|
+
def metadata
|
177
|
+
(groups + [step]).compact.inject({}) { |merged, part| merged.merge(part.metadata) }
|
178
|
+
end
|
179
|
+
|
180
|
+
# Step methods is a combination of let_methods for all contexts (group) the step included
|
181
|
+
def let_methods
|
182
|
+
(groups).compact.inject({}) { |merged, part| merged.merge(part.let_methods) }
|
183
|
+
end
|
85
184
|
end
|
86
|
-
end
|
185
|
+
end
|
data/lib/lopata/version.rb
CHANGED
data/lib/lopata/world.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.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alexey Volochnev
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-06-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: httparty
|
@@ -80,7 +80,7 @@ dependencies:
|
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '1.0'
|
83
|
-
description: Functional acceptance
|
83
|
+
description: Functional acceptance testing
|
84
84
|
email: alexey.volochnev@gmail.com
|
85
85
|
executables:
|
86
86
|
- lopata
|
@@ -90,24 +90,24 @@ files:
|
|
90
90
|
- README.md
|
91
91
|
- exe/lopata
|
92
92
|
- lib/lopata.rb
|
93
|
+
- lib/lopata/active_record.rb
|
93
94
|
- lib/lopata/condition.rb
|
94
|
-
- lib/lopata/
|
95
|
+
- lib/lopata/configuration.rb
|
96
|
+
- lib/lopata/environment.rb
|
97
|
+
- lib/lopata/factory_bot.rb
|
95
98
|
- lib/lopata/generators/app.rb
|
96
|
-
- lib/lopata/generators/templates/.rspec
|
97
99
|
- lib/lopata/generators/templates/Gemfile
|
98
100
|
- lib/lopata/generators/templates/Lopatafile
|
99
101
|
- lib/lopata/generators/templates/config/environments/qa.yml
|
100
102
|
- lib/lopata/generators/templates/config/initializers/capybara.rb
|
101
|
-
- lib/lopata/generators/templates/spec/spec_helper.rb
|
102
103
|
- lib/lopata/id.rb
|
103
104
|
- lib/lopata/loader.rb
|
104
105
|
- lib/lopata/observers.rb
|
106
|
+
- lib/lopata/observers/backtrace_formatter.rb
|
105
107
|
- lib/lopata/observers/base_observer.rb
|
106
108
|
- lib/lopata/observers/console_output_observer.rb
|
107
109
|
- lib/lopata/observers/web_logger.rb
|
108
|
-
- lib/lopata/
|
109
|
-
- lib/lopata/rspec/dsl.rb
|
110
|
-
- lib/lopata/rspec/role.rb
|
110
|
+
- lib/lopata/role.rb
|
111
111
|
- lib/lopata/runner.rb
|
112
112
|
- lib/lopata/scenario.rb
|
113
113
|
- lib/lopata/scenario_builder.rb
|
@@ -137,5 +137,5 @@ requirements: []
|
|
137
137
|
rubygems_version: 3.0.3
|
138
138
|
signing_key:
|
139
139
|
specification_version: 4
|
140
|
-
summary: lopata-0.1.
|
140
|
+
summary: lopata-0.1.6
|
141
141
|
test_files: []
|
data/lib/lopata/config.rb
DELETED
@@ -1,101 +0,0 @@
|
|
1
|
-
module Lopata
|
2
|
-
module Config
|
3
|
-
extend self
|
4
|
-
|
5
|
-
attr_accessor :build_number, :lopata_host, :lopata_code, :only_roles, :role_descriptions, :after_as,
|
6
|
-
:default_role, :ops, :after_scenario
|
7
|
-
|
8
|
-
def init(env)
|
9
|
-
require 'yaml'
|
10
|
-
@config = {}
|
11
|
-
config_filename = "./config/environments/#{env}.yml"
|
12
|
-
@config = YAML::load(File.open(config_filename)) if File.exists?(config_filename)
|
13
|
-
init_db
|
14
|
-
@role_descriptions ||= {}
|
15
|
-
# init_includes
|
16
|
-
end
|
17
|
-
|
18
|
-
def [](key)
|
19
|
-
@config[key]
|
20
|
-
end
|
21
|
-
|
22
|
-
%w{url name readonly}.each do |opt|
|
23
|
-
define_method opt do
|
24
|
-
raise "Lopata::Config unititlalized, use Lopata::Config#init(env) to set environment" unless @config
|
25
|
-
@config[opt]
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
def init_db
|
30
|
-
ActiveRecord::Base.establish_connection(@config['db']) if @config['db']
|
31
|
-
end
|
32
|
-
|
33
|
-
def init_rspec
|
34
|
-
require 'lopata/rspec/dsl'
|
35
|
-
require 'lopata/rspec/role'
|
36
|
-
::RSpec.configure do |c|
|
37
|
-
c.include Lopata::RSpec::DSL
|
38
|
-
c.include Lopata::RSpec::Role
|
39
|
-
end
|
40
|
-
init_rspec_filters
|
41
|
-
end
|
42
|
-
|
43
|
-
def init_active_record
|
44
|
-
require 'lopata/rspec/ar_dsl'
|
45
|
-
::RSpec.configure do |c|
|
46
|
-
c.include Lopata::RSpec::AR::DSL
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
def init_lopata_logging(build)
|
51
|
-
self.build_number = build
|
52
|
-
require 'lopata/observers/web_logger'
|
53
|
-
add_observer Lopata::Observers::WebLogger.new
|
54
|
-
end
|
55
|
-
|
56
|
-
def init_rerun
|
57
|
-
::RSpec.configure do |c|
|
58
|
-
c.inclusion_filter = { full_description: build_rerun_filter_proc }
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
def init_rspec_filters
|
63
|
-
filters = {}
|
64
|
-
filters[:focus] = true if ops[:focus]
|
65
|
-
if ops[:rerun]
|
66
|
-
filters[:full_description] = build_rerun_filter_proc
|
67
|
-
end
|
68
|
-
if ops[:text]
|
69
|
-
filters[:full_description] = ->(desc) { desc.include?(ops[:text]) }
|
70
|
-
end
|
71
|
-
unless filters.blank?
|
72
|
-
::RSpec.configure do |c|
|
73
|
-
c.inclusion_filter = filters
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
def build_rerun_filter_proc
|
79
|
-
to_rerun = Lopata::Client.new(Lopata::Config.build_number).to_rerun
|
80
|
-
Proc.new do |desc|
|
81
|
-
to_rerun.include?(desc)
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
def before_start(&block)
|
86
|
-
@before_start = block
|
87
|
-
end
|
88
|
-
|
89
|
-
def initialize_test
|
90
|
-
@before_start.call if @before_start
|
91
|
-
end
|
92
|
-
|
93
|
-
def world
|
94
|
-
@world ||= Lopata::World.new
|
95
|
-
end
|
96
|
-
|
97
|
-
def add_observer(observer)
|
98
|
-
world.observers << observer
|
99
|
-
end
|
100
|
-
end
|
101
|
-
end
|
data/lib/lopata/rspec/ar_dsl.rb
DELETED
@@ -1,38 +0,0 @@
|
|
1
|
-
module Lopata
|
2
|
-
module RSpec
|
3
|
-
module AR
|
4
|
-
module DSL
|
5
|
-
def self.included(base)
|
6
|
-
base.extend(ClassMethods)
|
7
|
-
end
|
8
|
-
|
9
|
-
def cleanup(*objects)
|
10
|
-
return if Lopata::Config.ops[:keep]
|
11
|
-
objects.flatten.compact.each do |o|
|
12
|
-
begin
|
13
|
-
o.reload.destroy!
|
14
|
-
rescue ActiveRecord::RecordNotFound
|
15
|
-
# Already destroyed
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
def reload(*objects)
|
21
|
-
objects.flatten.each(&:reload)
|
22
|
-
end
|
23
|
-
|
24
|
-
|
25
|
-
module ClassMethods
|
26
|
-
def cleanup(*vars, &block)
|
27
|
-
unless vars.empty?
|
28
|
-
teardown do
|
29
|
-
cleanup vars.map { |v| instance_variable_get "@#{v}" }
|
30
|
-
end
|
31
|
-
end
|
32
|
-
teardown &block if block_given?
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|