lopata 0.1.13 → 0.1.14
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/README.md +25 -25
- data/exe/lopata +11 -11
- data/lib/lopata.rb +74 -74
- data/lib/lopata/active_record.rb +135 -135
- data/lib/lopata/condition.rb +30 -30
- data/lib/lopata/configuration.rb +125 -125
- data/lib/lopata/environment.rb +35 -35
- data/lib/lopata/factory_bot.rb +72 -72
- data/lib/lopata/generators/app.rb +42 -42
- data/lib/lopata/generators/templates/Gemfile +7 -7
- data/lib/lopata/generators/templates/Lopatafile +20 -20
- data/lib/lopata/generators/templates/config/environments/qa.yml +7 -7
- data/lib/lopata/generators/templates/config/initializers/capybara.rb +1 -1
- data/lib/lopata/id.rb +22 -22
- data/lib/lopata/loader.rb +31 -31
- data/lib/lopata/observers.rb +4 -4
- data/lib/lopata/observers/backtrace_formatter.rb +103 -103
- data/lib/lopata/observers/base_observer.rb +33 -33
- data/lib/lopata/observers/console_output_observer.rb +100 -100
- data/lib/lopata/observers/web_logger.rb +130 -130
- data/lib/lopata/role.rb +109 -109
- data/lib/lopata/runner.rb +67 -67
- data/lib/lopata/scenario.rb +136 -136
- data/lib/lopata/scenario_builder.rb +497 -497
- data/lib/lopata/shared_step.rb +38 -38
- data/lib/lopata/step.rb +191 -191
- data/lib/lopata/version.rb +6 -6
- data/lib/lopata/world.rb +24 -24
- metadata +4 -4
data/lib/lopata/role.rb
CHANGED
@@ -1,110 +1,110 @@
|
|
1
|
-
module Lopata
|
2
|
-
# Adds ability to run scenarios by given user roles
|
3
|
-
#
|
4
|
-
# @example Usage
|
5
|
-
# require 'lopata/role'
|
6
|
-
# Lopata.configure do |c|
|
7
|
-
# c.role_descriptions = {
|
8
|
-
# user: 'User',
|
9
|
-
# admin: 'Admin'
|
10
|
-
# }
|
11
|
-
# c.default_role = :user
|
12
|
-
# c.before_scenaro 'setup user'
|
13
|
-
# end
|
14
|
-
# Lopata.shared_step 'setup user' do
|
15
|
-
# setup { @user = User.create(role: current_role) if current_role }
|
16
|
-
# cleanup :user
|
17
|
-
# end
|
18
|
-
# Lopata.define 'login' do
|
19
|
-
# # will generate 2 scenarios, one for :user and one for :admin
|
20
|
-
# as :user, :admin
|
21
|
-
# action 'login'
|
22
|
-
# # verify the user is logged in
|
23
|
-
# end
|
24
|
-
#
|
25
|
-
# @see Lopata::Configuration#role_descriptions
|
26
|
-
# @see Lopata::Configuration#default_role
|
27
|
-
module Role
|
28
|
-
# To be included in Lopata::Scenario
|
29
|
-
module Methods
|
30
|
-
# @return [Symbol, nil] user role for current scenario or nil, if scenario is running without user.
|
31
|
-
def current_role
|
32
|
-
metadata[:as]
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
# To be included in Lopata::ScenarioBuilder
|
37
|
-
module DSL
|
38
|
-
# Enumerate the roles the scenario to be runned under.
|
39
|
-
# If not invoked the default role only will be used.
|
40
|
-
#
|
41
|
-
# The scenario should be set to use the role via before_scenario step using #current_role param.
|
42
|
-
#
|
43
|
-
# @param args [Array<Symbol>] list of roles the scenario to be runned with.
|
44
|
-
# @param block [Block] the block to calculate role from scenario metadata.
|
45
|
-
def as(*args, &block)
|
46
|
-
@roles = args.flatten
|
47
|
-
@roles << Lopata::ScenarioBuilder::CalculatedValue.new(&block) if block_given?
|
48
|
-
@use_all_roles = true
|
49
|
-
@role_options = nil
|
50
|
-
end
|
51
|
-
|
52
|
-
# Enumerate the roles the scenario can be run.
|
53
|
-
#
|
54
|
-
# The scenario should be set to use the role via before_scenario step using #current_role param.
|
55
|
-
#
|
56
|
-
# Only first role will be used if scenario has no options or diagonales. Some first roles will be used if
|
57
|
-
# options or diagonales are declared, in order of appearence.
|
58
|
-
#
|
59
|
-
# Use this to describe possible roles, but not needed to run scenario with all of them in order to save time
|
60
|
-
# of running.
|
61
|
-
#
|
62
|
-
# @param args [Array<Symbol>] list of roles the scenario to be runned with.
|
63
|
-
def as_first(*args, &block)
|
64
|
-
@roles = args.flatten
|
65
|
-
@use_all_roles = false
|
66
|
-
@role_options = nil
|
67
|
-
end
|
68
|
-
|
69
|
-
# @private
|
70
|
-
def role_options
|
71
|
-
@role_options ||= build_role_options
|
72
|
-
end
|
73
|
-
|
74
|
-
# Marks scenario to be runned without user.
|
75
|
-
#
|
76
|
-
# @example
|
77
|
-
# Lopata.define 'scenario withou user' do
|
78
|
-
# without_user
|
79
|
-
# it 'does not define the user' do
|
80
|
-
# expect(current_role).to be_nil
|
81
|
-
# end
|
82
|
-
# end
|
83
|
-
def without_user
|
84
|
-
@without_user = true
|
85
|
-
end
|
86
|
-
|
87
|
-
# @private
|
88
|
-
def build_role_options
|
89
|
-
return [] unless roles
|
90
|
-
role_variants = roles.map { |r| [Lopata.configuration.role_descriptions[r], r] }
|
91
|
-
[Lopata::ScenarioBuilder::Diagonal.new(:as, role_variants, @use_all_roles)]
|
92
|
-
end
|
93
|
-
|
94
|
-
# @private
|
95
|
-
def roles
|
96
|
-
return false if @without_user
|
97
|
-
@roles ||= [Lopata.configuration.default_role].compact
|
98
|
-
end
|
99
|
-
|
100
|
-
# @private
|
101
|
-
def diagonals
|
102
|
-
super + role_options
|
103
|
-
end
|
104
|
-
end
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
Lopata::Scenario.include Lopata::Role::Methods
|
109
|
-
# Prepend the module to overload #diagonals method
|
1
|
+
module Lopata
|
2
|
+
# Adds ability to run scenarios by given user roles
|
3
|
+
#
|
4
|
+
# @example Usage
|
5
|
+
# require 'lopata/role'
|
6
|
+
# Lopata.configure do |c|
|
7
|
+
# c.role_descriptions = {
|
8
|
+
# user: 'User',
|
9
|
+
# admin: 'Admin'
|
10
|
+
# }
|
11
|
+
# c.default_role = :user
|
12
|
+
# c.before_scenaro 'setup user'
|
13
|
+
# end
|
14
|
+
# Lopata.shared_step 'setup user' do
|
15
|
+
# setup { @user = User.create(role: current_role) if current_role }
|
16
|
+
# cleanup :user
|
17
|
+
# end
|
18
|
+
# Lopata.define 'login' do
|
19
|
+
# # will generate 2 scenarios, one for :user and one for :admin
|
20
|
+
# as :user, :admin
|
21
|
+
# action 'login'
|
22
|
+
# # verify the user is logged in
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
# @see Lopata::Configuration#role_descriptions
|
26
|
+
# @see Lopata::Configuration#default_role
|
27
|
+
module Role
|
28
|
+
# To be included in Lopata::Scenario
|
29
|
+
module Methods
|
30
|
+
# @return [Symbol, nil] user role for current scenario or nil, if scenario is running without user.
|
31
|
+
def current_role
|
32
|
+
metadata[:as]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# To be included in Lopata::ScenarioBuilder
|
37
|
+
module DSL
|
38
|
+
# Enumerate the roles the scenario to be runned under.
|
39
|
+
# If not invoked the default role only will be used.
|
40
|
+
#
|
41
|
+
# The scenario should be set to use the role via before_scenario step using #current_role param.
|
42
|
+
#
|
43
|
+
# @param args [Array<Symbol>] list of roles the scenario to be runned with.
|
44
|
+
# @param block [Block] the block to calculate role from scenario metadata.
|
45
|
+
def as(*args, &block)
|
46
|
+
@roles = args.flatten
|
47
|
+
@roles << Lopata::ScenarioBuilder::CalculatedValue.new(&block) if block_given?
|
48
|
+
@use_all_roles = true
|
49
|
+
@role_options = nil
|
50
|
+
end
|
51
|
+
|
52
|
+
# Enumerate the roles the scenario can be run.
|
53
|
+
#
|
54
|
+
# The scenario should be set to use the role via before_scenario step using #current_role param.
|
55
|
+
#
|
56
|
+
# Only first role will be used if scenario has no options or diagonales. Some first roles will be used if
|
57
|
+
# options or diagonales are declared, in order of appearence.
|
58
|
+
#
|
59
|
+
# Use this to describe possible roles, but not needed to run scenario with all of them in order to save time
|
60
|
+
# of running.
|
61
|
+
#
|
62
|
+
# @param args [Array<Symbol>] list of roles the scenario to be runned with.
|
63
|
+
def as_first(*args, &block)
|
64
|
+
@roles = args.flatten
|
65
|
+
@use_all_roles = false
|
66
|
+
@role_options = nil
|
67
|
+
end
|
68
|
+
|
69
|
+
# @private
|
70
|
+
def role_options
|
71
|
+
@role_options ||= build_role_options
|
72
|
+
end
|
73
|
+
|
74
|
+
# Marks scenario to be runned without user.
|
75
|
+
#
|
76
|
+
# @example
|
77
|
+
# Lopata.define 'scenario withou user' do
|
78
|
+
# without_user
|
79
|
+
# it 'does not define the user' do
|
80
|
+
# expect(current_role).to be_nil
|
81
|
+
# end
|
82
|
+
# end
|
83
|
+
def without_user
|
84
|
+
@without_user = true
|
85
|
+
end
|
86
|
+
|
87
|
+
# @private
|
88
|
+
def build_role_options
|
89
|
+
return [] unless roles
|
90
|
+
role_variants = roles.map { |r| [Lopata.configuration.role_descriptions[r], r] }
|
91
|
+
[Lopata::ScenarioBuilder::Diagonal.new(:as, role_variants, @use_all_roles)]
|
92
|
+
end
|
93
|
+
|
94
|
+
# @private
|
95
|
+
def roles
|
96
|
+
return false if @without_user
|
97
|
+
@roles ||= [Lopata.configuration.default_role].compact
|
98
|
+
end
|
99
|
+
|
100
|
+
# @private
|
101
|
+
def diagonals
|
102
|
+
super + role_options
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
Lopata::Scenario.include Lopata::Role::Methods
|
109
|
+
# Prepend the module to overload #diagonals method
|
110
110
|
Lopata::ScenarioBuilder.prepend Lopata::Role::DSL
|
data/lib/lopata/runner.rb
CHANGED
@@ -1,67 +1,67 @@
|
|
1
|
-
require 'thor'
|
2
|
-
require_relative 'generators/app'
|
3
|
-
require_relative 'world'
|
4
|
-
require_relative 'loader'
|
5
|
-
require_relative '../lopata'
|
6
|
-
require_relative 'observers'
|
7
|
-
require_relative 'condition'
|
8
|
-
|
9
|
-
module Lopata
|
10
|
-
# @private
|
11
|
-
class Runner < Thor
|
12
|
-
desc 'test', 'Run tests'
|
13
|
-
option :env, default: :qa, aliases: 'e'
|
14
|
-
option :rerun, type: :boolean, aliases: 'r'
|
15
|
-
option :keep, type: :boolean, aliases: 'k'
|
16
|
-
option :text, aliases: 't'
|
17
|
-
def test(*args)
|
18
|
-
trap_interrupt
|
19
|
-
configure_from_options
|
20
|
-
Lopata::Loader.load_shared_steps
|
21
|
-
Lopata::Loader.load_scenarios(*args)
|
22
|
-
world = Lopata.world
|
23
|
-
world.notify_observers(:started, world)
|
24
|
-
world.scenarios.each { |s| s.run }
|
25
|
-
world.notify_observers(:finished, world)
|
26
|
-
end
|
27
|
-
|
28
|
-
default_task :test
|
29
|
-
|
30
|
-
register Generators::App, :new, 'lopata new project-name', 'Init new lopata projects'
|
31
|
-
|
32
|
-
def self.exit_on_failure?
|
33
|
-
true
|
34
|
-
end
|
35
|
-
|
36
|
-
no_commands do
|
37
|
-
def configure_from_options
|
38
|
-
Lopata.configure do |c|
|
39
|
-
c.env = options[:env].to_sym
|
40
|
-
c.keep = options[:keep]
|
41
|
-
c.load_environment
|
42
|
-
c.run_before_start_hooks
|
43
|
-
end
|
44
|
-
add_text_filter(options[:text]) if options[:text]
|
45
|
-
add_rerun_filter if options[:rerun]
|
46
|
-
end
|
47
|
-
|
48
|
-
def add_text_filter(text)
|
49
|
-
Lopata.configuration.filters << -> (scenario) { scenario.title.include?(text) }
|
50
|
-
end
|
51
|
-
|
52
|
-
def add_rerun_filter
|
53
|
-
to_rerun = Lopata::Client.new.to_rerun
|
54
|
-
Lopata.configuration.filters << -> (scenario) { to_rerun.include?(scenario.title) }
|
55
|
-
end
|
56
|
-
|
57
|
-
def trap_interrupt
|
58
|
-
trap('INT') { exit!(1) }
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
unless ARGV.first == 'new'
|
65
|
-
eval File.binread('./Lopatafile') if File.exists?('./Lopatafile')
|
66
|
-
end
|
67
|
-
|
1
|
+
require 'thor'
|
2
|
+
require_relative 'generators/app'
|
3
|
+
require_relative 'world'
|
4
|
+
require_relative 'loader'
|
5
|
+
require_relative '../lopata'
|
6
|
+
require_relative 'observers'
|
7
|
+
require_relative 'condition'
|
8
|
+
|
9
|
+
module Lopata
|
10
|
+
# @private
|
11
|
+
class Runner < Thor
|
12
|
+
desc 'test', 'Run tests'
|
13
|
+
option :env, default: :qa, aliases: 'e'
|
14
|
+
option :rerun, type: :boolean, aliases: 'r'
|
15
|
+
option :keep, type: :boolean, aliases: 'k'
|
16
|
+
option :text, aliases: 't'
|
17
|
+
def test(*args)
|
18
|
+
trap_interrupt
|
19
|
+
configure_from_options
|
20
|
+
Lopata::Loader.load_shared_steps
|
21
|
+
Lopata::Loader.load_scenarios(*args)
|
22
|
+
world = Lopata.world
|
23
|
+
world.notify_observers(:started, world)
|
24
|
+
world.scenarios.each { |s| s.run }
|
25
|
+
world.notify_observers(:finished, world)
|
26
|
+
end
|
27
|
+
|
28
|
+
default_task :test
|
29
|
+
|
30
|
+
register Generators::App, :new, 'lopata new project-name', 'Init new lopata projects'
|
31
|
+
|
32
|
+
def self.exit_on_failure?
|
33
|
+
true
|
34
|
+
end
|
35
|
+
|
36
|
+
no_commands do
|
37
|
+
def configure_from_options
|
38
|
+
Lopata.configure do |c|
|
39
|
+
c.env = options[:env].to_sym
|
40
|
+
c.keep = options[:keep]
|
41
|
+
c.load_environment
|
42
|
+
c.run_before_start_hooks
|
43
|
+
end
|
44
|
+
add_text_filter(options[:text]) if options[:text]
|
45
|
+
add_rerun_filter if options[:rerun]
|
46
|
+
end
|
47
|
+
|
48
|
+
def add_text_filter(text)
|
49
|
+
Lopata.configuration.filters << -> (scenario) { scenario.title.include?(text) }
|
50
|
+
end
|
51
|
+
|
52
|
+
def add_rerun_filter
|
53
|
+
to_rerun = Lopata::Client.new.to_rerun
|
54
|
+
Lopata.configuration.filters << -> (scenario) { to_rerun.include?(scenario.title) }
|
55
|
+
end
|
56
|
+
|
57
|
+
def trap_interrupt
|
58
|
+
trap('INT') { exit!(1) }
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
unless ARGV.first == 'new'
|
65
|
+
eval File.binread('./Lopatafile') if File.exists?('./Lopatafile')
|
66
|
+
end
|
67
|
+
|
data/lib/lopata/scenario.rb
CHANGED
@@ -1,136 +1,136 @@
|
|
1
|
-
require 'rspec/expectations'
|
2
|
-
|
3
|
-
# Scenario runtime class.
|
4
|
-
#
|
5
|
-
# All the scenarios are running in context of separate Lopata::Scenario object.
|
6
|
-
#
|
7
|
-
class Lopata::Scenario
|
8
|
-
include RSpec::Matchers
|
9
|
-
|
10
|
-
# @private
|
11
|
-
attr_reader :execution
|
12
|
-
|
13
|
-
# @private
|
14
|
-
def initialize(execution)
|
15
|
-
@execution = execution
|
16
|
-
end
|
17
|
-
|
18
|
-
# Marks current step as pending
|
19
|
-
# @example
|
20
|
-
# it 'pending step' do
|
21
|
-
# pending
|
22
|
-
# expect(1).to eq 2
|
23
|
-
# end
|
24
|
-
#
|
25
|
-
# Pending steps wont be failed
|
26
|
-
def pending(message = nil)
|
27
|
-
execution.current_step.pending!(message)
|
28
|
-
end
|
29
|
-
|
30
|
-
# @return [Hash] metadata available for current step
|
31
|
-
# @note The metadata keys also availalbe as methods (via method_missing)
|
32
|
-
def metadata
|
33
|
-
execution.metadata
|
34
|
-
end
|
35
|
-
|
36
|
-
private
|
37
|
-
|
38
|
-
# @private
|
39
|
-
def method_missing(method, *args, &block)
|
40
|
-
if execution.let_methods.include?(method)
|
41
|
-
instance_exec(*args, &execution.let_methods[method])
|
42
|
-
elsif metadata.keys.include?(method)
|
43
|
-
metadata[method]
|
44
|
-
else
|
45
|
-
super
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
# @private
|
50
|
-
def respond_to_missing?(method, *)
|
51
|
-
execution.let_methods.include?(method) or metadata.keys.include?(method) or super
|
52
|
-
end
|
53
|
-
|
54
|
-
# @private
|
55
|
-
# Scenario execution and live-cycle information
|
56
|
-
class Execution
|
57
|
-
attr_reader :scenario, :status, :steps, :title, :current_step
|
58
|
-
|
59
|
-
def initialize(title, options_title, metadata = {})
|
60
|
-
@title = [title, options_title].compact.reject(&:empty?).join(' ')
|
61
|
-
@metadata = metadata
|
62
|
-
@let_methods = {}
|
63
|
-
@status = :not_runned
|
64
|
-
@steps = []
|
65
|
-
@scenario = Lopata::Scenario.new(self)
|
66
|
-
end
|
67
|
-
|
68
|
-
def run
|
69
|
-
@status = :running
|
70
|
-
sort_steps
|
71
|
-
world.notify_observers(:scenario_started, self)
|
72
|
-
steps.each(&method(:run_step))
|
73
|
-
@status = steps.any?(&:failed?) ? :failed : :passed
|
74
|
-
world.notify_observers(:scenario_finished, self)
|
75
|
-
cleanup
|
76
|
-
end
|
77
|
-
|
78
|
-
def run_step(step)
|
79
|
-
return if step.skipped?
|
80
|
-
@current_step = step
|
81
|
-
step.run(scenario)
|
82
|
-
skip_rest if step.failed? && step.skip_rest_on_failure?
|
83
|
-
@current_step = nil
|
84
|
-
end
|
85
|
-
|
86
|
-
def world
|
87
|
-
Lopata.world
|
88
|
-
end
|
89
|
-
|
90
|
-
def failed?
|
91
|
-
status == :failed
|
92
|
-
end
|
93
|
-
|
94
|
-
def sort_steps
|
95
|
-
@steps = steps.reject(&:teardown_group?) + steps.select(&:teardown_group?)
|
96
|
-
end
|
97
|
-
|
98
|
-
def skip_rest
|
99
|
-
steps.select { |s| s.status == :not_runned && !s.teardown? }.each(&:skip!)
|
100
|
-
end
|
101
|
-
|
102
|
-
def metadata
|
103
|
-
if current_step
|
104
|
-
@metadata.merge(current_step.metadata)
|
105
|
-
else
|
106
|
-
@metadata
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
|
-
def let_methods
|
111
|
-
if current_step
|
112
|
-
@let_methods.merge(current_step.let_methods)
|
113
|
-
else
|
114
|
-
@let_methods
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
def let(method_name, &block)
|
119
|
-
# define_singleton_method method_name, &block
|
120
|
-
base =
|
121
|
-
if current_step && !current_step.groups.empty?
|
122
|
-
current_step.groups.last.let_methods
|
123
|
-
else
|
124
|
-
@let_methods
|
125
|
-
end
|
126
|
-
base[method_name] = block
|
127
|
-
end
|
128
|
-
|
129
|
-
def cleanup
|
130
|
-
@title = nil
|
131
|
-
@metadata = nil
|
132
|
-
@steps = nil
|
133
|
-
@scenario = nil
|
134
|
-
end
|
135
|
-
end
|
136
|
-
end
|
1
|
+
require 'rspec/expectations'
|
2
|
+
|
3
|
+
# Scenario runtime class.
|
4
|
+
#
|
5
|
+
# All the scenarios are running in context of separate Lopata::Scenario object.
|
6
|
+
#
|
7
|
+
class Lopata::Scenario
|
8
|
+
include RSpec::Matchers
|
9
|
+
|
10
|
+
# @private
|
11
|
+
attr_reader :execution
|
12
|
+
|
13
|
+
# @private
|
14
|
+
def initialize(execution)
|
15
|
+
@execution = execution
|
16
|
+
end
|
17
|
+
|
18
|
+
# Marks current step as pending
|
19
|
+
# @example
|
20
|
+
# it 'pending step' do
|
21
|
+
# pending
|
22
|
+
# expect(1).to eq 2
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
# Pending steps wont be failed
|
26
|
+
def pending(message = nil)
|
27
|
+
execution.current_step.pending!(message)
|
28
|
+
end
|
29
|
+
|
30
|
+
# @return [Hash] metadata available for current step
|
31
|
+
# @note The metadata keys also availalbe as methods (via method_missing)
|
32
|
+
def metadata
|
33
|
+
execution.metadata
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
# @private
|
39
|
+
def method_missing(method, *args, &block)
|
40
|
+
if execution.let_methods.include?(method)
|
41
|
+
instance_exec(*args, &execution.let_methods[method])
|
42
|
+
elsif metadata.keys.include?(method)
|
43
|
+
metadata[method]
|
44
|
+
else
|
45
|
+
super
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# @private
|
50
|
+
def respond_to_missing?(method, *)
|
51
|
+
execution.let_methods.include?(method) or metadata.keys.include?(method) or super
|
52
|
+
end
|
53
|
+
|
54
|
+
# @private
|
55
|
+
# Scenario execution and live-cycle information
|
56
|
+
class Execution
|
57
|
+
attr_reader :scenario, :status, :steps, :title, :current_step
|
58
|
+
|
59
|
+
def initialize(title, options_title, metadata = {})
|
60
|
+
@title = [title, options_title].compact.reject(&:empty?).join(' ')
|
61
|
+
@metadata = metadata
|
62
|
+
@let_methods = {}
|
63
|
+
@status = :not_runned
|
64
|
+
@steps = []
|
65
|
+
@scenario = Lopata::Scenario.new(self)
|
66
|
+
end
|
67
|
+
|
68
|
+
def run
|
69
|
+
@status = :running
|
70
|
+
sort_steps
|
71
|
+
world.notify_observers(:scenario_started, self)
|
72
|
+
steps.each(&method(:run_step))
|
73
|
+
@status = steps.any?(&:failed?) ? :failed : :passed
|
74
|
+
world.notify_observers(:scenario_finished, self)
|
75
|
+
cleanup
|
76
|
+
end
|
77
|
+
|
78
|
+
def run_step(step)
|
79
|
+
return if step.skipped?
|
80
|
+
@current_step = step
|
81
|
+
step.run(scenario)
|
82
|
+
skip_rest if step.failed? && step.skip_rest_on_failure?
|
83
|
+
@current_step = nil
|
84
|
+
end
|
85
|
+
|
86
|
+
def world
|
87
|
+
Lopata.world
|
88
|
+
end
|
89
|
+
|
90
|
+
def failed?
|
91
|
+
status == :failed
|
92
|
+
end
|
93
|
+
|
94
|
+
def sort_steps
|
95
|
+
@steps = steps.reject(&:teardown_group?) + steps.select(&:teardown_group?)
|
96
|
+
end
|
97
|
+
|
98
|
+
def skip_rest
|
99
|
+
steps.select { |s| s.status == :not_runned && !s.teardown? }.each(&:skip!)
|
100
|
+
end
|
101
|
+
|
102
|
+
def metadata
|
103
|
+
if current_step
|
104
|
+
@metadata.merge(current_step.metadata)
|
105
|
+
else
|
106
|
+
@metadata
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def let_methods
|
111
|
+
if current_step
|
112
|
+
@let_methods.merge(current_step.let_methods)
|
113
|
+
else
|
114
|
+
@let_methods
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def let(method_name, &block)
|
119
|
+
# define_singleton_method method_name, &block
|
120
|
+
base =
|
121
|
+
if current_step && !current_step.groups.empty?
|
122
|
+
current_step.groups.last.let_methods
|
123
|
+
else
|
124
|
+
@let_methods
|
125
|
+
end
|
126
|
+
base[method_name] = block
|
127
|
+
end
|
128
|
+
|
129
|
+
def cleanup
|
130
|
+
@title = nil
|
131
|
+
@metadata = nil
|
132
|
+
@steps = nil
|
133
|
+
@scenario = nil
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|