lopata 0.1.5 → 0.1.6
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 +6 -2
- data/exe/lopata +1 -1
- data/lib/lopata.rb +51 -2
- data/lib/lopata/active_record.rb +68 -5
- data/lib/lopata/condition.rb +2 -1
- data/lib/lopata/configuration.rb +126 -0
- data/lib/lopata/environment.rb +36 -0
- data/lib/lopata/factory_bot.rb +1 -1
- 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 +14 -0
- data/lib/lopata/observers/base_observer.rb +17 -6
- data/lib/lopata/observers/console_output_observer.rb +30 -8
- data/lib/lopata/observers/web_logger.rb +26 -33
- data/lib/lopata/role.rb +46 -0
- data/lib/lopata/runner.rb +10 -19
- data/lib/lopata/scenario.rb +30 -6
- data/lib/lopata/scenario_builder.rb +16 -59
- data/lib/lopata/step.rb +10 -7
- data/lib/lopata/version.rb +1 -1
- data/lib/lopata/world.rb +3 -1
- metadata +6 -8
- data/lib/lopata/config.rb +0 -97
- data/lib/lopata/generators/templates/.rspec +0 -3
- data/lib/lopata/generators/templates/spec/spec_helper.rb +0 -2
- data/lib/lopata/rspec/dsl.rb +0 -39
- data/lib/lopata/rspec/role.rb +0 -74
@@ -1,23 +1,34 @@
|
|
1
1
|
module Lopata
|
2
2
|
module Observers
|
3
|
+
# Lopata allows observe scenarios execution.
|
4
|
+
# All the observers are subclasses of Lopata::Observers::BaseObserver.
|
5
|
+
#
|
6
|
+
# @see Lopata::Observers::ConsoleOutputObserver for implementation example
|
3
7
|
class BaseObserver
|
8
|
+
# Called before scenarios execution.
|
9
|
+
# All the scenarios are prepared at the moment, so it may be used to get number of scenarios
|
10
|
+
# via world.scenarios.count
|
11
|
+
#
|
12
|
+
# @param world [Lopata::World]
|
4
13
|
def started(world)
|
5
14
|
end
|
6
15
|
|
16
|
+
# Called after all scenarios execution.
|
17
|
+
# All the scenarios are finished at the moment, so it may be used for output statistics.
|
18
|
+
#
|
19
|
+
# @param world [Lopata::World]
|
7
20
|
def finished(world)
|
8
21
|
end
|
9
22
|
|
23
|
+
# Called before single scenario execution.
|
24
|
+
# @param world [Lopata::Scenario::Execution]
|
10
25
|
def scenario_started(scenario)
|
11
26
|
end
|
12
27
|
|
28
|
+
# Called after single scenario execution.
|
29
|
+
# @param world [Lopata::Scenario::Execution]
|
13
30
|
def scenario_finished(scenario)
|
14
31
|
end
|
15
|
-
|
16
|
-
def step_started(step)
|
17
|
-
end
|
18
|
-
|
19
|
-
def step_finished(step)
|
20
|
-
end
|
21
32
|
end
|
22
33
|
end
|
23
34
|
end
|
@@ -2,26 +2,44 @@ require_relative 'backtrace_formatter'
|
|
2
2
|
|
3
3
|
module Lopata
|
4
4
|
module Observers
|
5
|
+
# @private
|
5
6
|
class ConsoleOutputObserver < BaseObserver
|
7
|
+
extend Forwardable
|
8
|
+
# @private
|
9
|
+
attr_reader :output
|
10
|
+
# @private
|
11
|
+
def_delegators :output, :puts, :flush
|
12
|
+
|
13
|
+
def initialize
|
14
|
+
@output = $stdout
|
15
|
+
end
|
16
|
+
|
17
|
+
# @see Lopata::Observers::BaseObserver#finished
|
6
18
|
def finished(world)
|
7
|
-
total =
|
8
|
-
|
9
|
-
|
10
|
-
colored("%d %s", status) % [statuses.count { |s| s == status }, status]
|
19
|
+
total = statuses.values.inject(0, &:+)
|
20
|
+
counts = statuses.map do |status, count|
|
21
|
+
colored("%d %s", status) % [count, status]
|
11
22
|
end
|
12
23
|
details = counts.empty? ? "" : "(%s)" % counts.join(', ')
|
13
24
|
puts "#{total} scenario%s %s" % [total == 1 ? '' : 's', details]
|
14
25
|
end
|
15
26
|
|
27
|
+
# @see Lopata::Observers::BaseObserver#scenario_finished
|
16
28
|
def scenario_finished(scenario)
|
17
29
|
message = "#{scenario.title} #{bold(scenario.status.to_s.upcase)}"
|
18
30
|
puts colored(message, scenario.status)
|
19
|
-
return unless scenario.failed?
|
20
31
|
|
21
|
-
scenario.
|
22
|
-
|
23
|
-
|
32
|
+
statuses[scenario.status] ||= 0
|
33
|
+
statuses[scenario.status] += 1
|
34
|
+
|
35
|
+
if scenario.failed?
|
36
|
+
scenario.steps.each do |step|
|
37
|
+
puts colored(" #{status_marker(step.status)} #{step.title}", step.status)
|
38
|
+
puts indent(4, backtrace_formatter.error_message(step.exception, include_backtrace: true)) if step.failed?
|
39
|
+
end
|
24
40
|
end
|
41
|
+
|
42
|
+
flush
|
25
43
|
end
|
26
44
|
|
27
45
|
private
|
@@ -72,6 +90,10 @@ module Lopata
|
|
72
90
|
def indent(cols, text)
|
73
91
|
text.split("\n").map { |line| " " * cols + line }.join("\n")
|
74
92
|
end
|
93
|
+
|
94
|
+
def statuses
|
95
|
+
@statuses ||= {}
|
96
|
+
end
|
75
97
|
end
|
76
98
|
end
|
77
99
|
end
|
@@ -4,21 +4,18 @@ require_relative 'backtrace_formatter'
|
|
4
4
|
|
5
5
|
module Lopata
|
6
6
|
module Observers
|
7
|
+
# @private
|
7
8
|
class WebLogger < BaseObserver
|
8
9
|
def started(world)
|
9
|
-
|
10
|
-
@client = Lopata::Client.new(Lopata::Config.build_number)
|
10
|
+
@client = Lopata::Client.new
|
11
11
|
@client.start(world.scenarios.count)
|
12
|
+
@finished = 0
|
12
13
|
end
|
13
14
|
|
14
15
|
def scenario_finished(scenario)
|
15
|
-
@
|
16
|
+
@finished += 1
|
17
|
+
@client.add_attempt(scenario, @finished)
|
16
18
|
end
|
17
|
-
|
18
|
-
# def example_pending(notification)
|
19
|
-
# example = notification.example
|
20
|
-
# @client.add_attempt(example, Lopata::PENDING, example.execution_result.pending_message)
|
21
|
-
# end
|
22
19
|
end
|
23
20
|
end
|
24
21
|
|
@@ -27,27 +24,30 @@ module Lopata
|
|
27
24
|
PENDING = 2
|
28
25
|
SKIPPED = 5
|
29
26
|
|
27
|
+
# @private
|
30
28
|
class Client
|
31
29
|
include HTTParty
|
32
|
-
base_uri Lopata::Config.lopata_host
|
33
30
|
|
34
|
-
|
31
|
+
attr_reader :url, :project_code, :build_number
|
35
32
|
|
36
|
-
def initialize
|
37
|
-
|
33
|
+
def initialize
|
34
|
+
params = Lopata.configuration.web_logging_params
|
35
|
+
raise "Web logging is not initailzed" unless params
|
36
|
+
@url = HTTParty.normalize_base_uri(params[:url])
|
37
|
+
@project_code = params[:project_code]
|
38
|
+
@build_number = params[:build_number]
|
38
39
|
end
|
39
40
|
|
40
41
|
def start(count)
|
41
42
|
@launch_id = JSON.parse(post("/projects/#{project_code}/builds/#{build_number}/launches.json", body: {total: count}).body)['id']
|
42
43
|
end
|
43
44
|
|
44
|
-
def add_attempt(scenario)
|
45
|
+
def add_attempt(scenario, finished)
|
45
46
|
status = scenario.failed? ? Lopata::FAILED : Lopata::PASSED
|
46
|
-
steps = scenario.
|
47
|
-
request = { status: status, steps: steps }
|
47
|
+
steps = scenario.steps.map { |s| step_hash(s) }
|
48
|
+
request = { status: status, steps: steps, launch: { id: @launch_id, finished: finished } }
|
48
49
|
test = test_id(scenario)
|
49
50
|
post("/tests/#{test}/attempts.json", body: request)
|
50
|
-
inc_finished
|
51
51
|
end
|
52
52
|
|
53
53
|
def step_hash(step)
|
@@ -82,32 +82,25 @@ module Lopata
|
|
82
82
|
|
83
83
|
private
|
84
84
|
|
85
|
-
def get_json(
|
86
|
-
JSON.parse(self.class.get(url).body)
|
85
|
+
def get_json(path)
|
86
|
+
JSON.parse(self.class.get(path, base_uri: url).body)
|
87
87
|
end
|
88
88
|
|
89
89
|
def post(*args)
|
90
|
-
self.class.post(*args)
|
90
|
+
self.class.post(*with_base_uri(args))
|
91
91
|
end
|
92
92
|
|
93
93
|
def patch(*args)
|
94
|
-
self.class.patch(*args)
|
94
|
+
self.class.patch(*with_base_uri(args))
|
95
95
|
end
|
96
96
|
|
97
|
-
def
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
headers: { 'Content-Type' => 'application/json', 'Accept' => 'application/json' })
|
103
|
-
if response.code == 404
|
104
|
-
puts 'Launch has been cancelled. Exit.'
|
105
|
-
exit!
|
97
|
+
def with_base_uri(args = [])
|
98
|
+
if args.last.is_a? Hash
|
99
|
+
args.last[:base_uri] = url
|
100
|
+
else
|
101
|
+
args << { base_uri: url }
|
106
102
|
end
|
107
|
-
|
108
|
-
|
109
|
-
def project_code
|
110
|
-
Lopata::Config.lopata_code
|
103
|
+
args
|
111
104
|
end
|
112
105
|
|
113
106
|
def error_message_for(step)
|
data/lib/lopata/role.rb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
module Lopata
|
2
|
+
# @see Lopata::Configuration#role_descriptions
|
3
|
+
# @see Lopata::Configuration#default_role
|
4
|
+
module Role
|
5
|
+
# To be included in Lopata::Scenario
|
6
|
+
module Methods
|
7
|
+
def current_role
|
8
|
+
metadata[:as]
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
# To be included in Lopata::ScenarioBuilder
|
13
|
+
module DSL
|
14
|
+
def as(*args, &block)
|
15
|
+
@roles = args.flatten
|
16
|
+
@roles << Lopata::ScenarioBuilder::CalculatedValue.new(&block) if block_given?
|
17
|
+
@role_options = nil
|
18
|
+
end
|
19
|
+
|
20
|
+
def role_options
|
21
|
+
@role_options ||= build_role_options
|
22
|
+
end
|
23
|
+
|
24
|
+
def without_user
|
25
|
+
@without_user = true
|
26
|
+
end
|
27
|
+
|
28
|
+
def build_role_options
|
29
|
+
return [] unless roles
|
30
|
+
[Lopata::ScenarioBuilder::Diagonal.new(:as, roles.map { |r| [Lopata.configuration.role_descriptions[r], r] })]
|
31
|
+
end
|
32
|
+
|
33
|
+
def roles
|
34
|
+
return false if @without_user
|
35
|
+
@roles ||= [Lopata.configuration.default_role].compact
|
36
|
+
end
|
37
|
+
|
38
|
+
def diagonals
|
39
|
+
super + role_options
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
Lopata::Scenario.include Lopata::Role::Methods
|
46
|
+
Lopata::ScenarioBuilder.prepend Lopata::Role::DSL
|
data/lib/lopata/runner.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
require 'thor'
|
2
2
|
require_relative 'generators/app'
|
3
|
-
require_relative 'config'
|
4
3
|
require_relative 'world'
|
5
4
|
require_relative 'loader'
|
6
5
|
require_relative '../lopata'
|
@@ -11,18 +10,14 @@ module Lopata
|
|
11
10
|
class Runner < Thor
|
12
11
|
desc 'test', 'Run tests'
|
13
12
|
option :env, default: :qa, aliases: 'e'
|
14
|
-
option :"no-log", type: :boolean, aliases: 'n'
|
15
|
-
option :focus, type: :boolean, aliases: 'f'
|
16
13
|
option :rerun, type: :boolean, aliases: 'r'
|
17
|
-
option :users, type: :array, aliases: 'u'
|
18
|
-
option :build, aliases: 'b'
|
19
14
|
option :keep, type: :boolean, aliases: 'k'
|
20
15
|
option :text, aliases: 't'
|
21
16
|
def test(*args)
|
22
17
|
configure_from_options
|
23
18
|
Lopata::Loader.load_shared_steps
|
24
19
|
Lopata::Loader.load_scenarios(*args)
|
25
|
-
world = Lopata
|
20
|
+
world = Lopata.world
|
26
21
|
world.start
|
27
22
|
world.scenarios.each { |s| s.run }
|
28
23
|
world.finish
|
@@ -38,27 +33,23 @@ module Lopata
|
|
38
33
|
|
39
34
|
no_commands do
|
40
35
|
def configure_from_options
|
41
|
-
Lopata
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
}
|
48
|
-
Lopata::Config.init(options[:env])
|
49
|
-
Lopata::Config.initialize_test
|
36
|
+
Lopata.configure do |c|
|
37
|
+
c.env = options[:env].to_sym
|
38
|
+
c.keep = options[:keep]
|
39
|
+
c.load_environment
|
40
|
+
c.run_before_start_hooks
|
41
|
+
end
|
50
42
|
add_text_filter(options[:text]) if options[:text]
|
51
43
|
add_rerun_filter if options[:rerun]
|
52
44
|
end
|
53
45
|
|
54
46
|
def add_text_filter(text)
|
55
|
-
Lopata
|
47
|
+
Lopata.configuration.filters << -> (scenario) { scenario.title.include?(text) }
|
56
48
|
end
|
57
49
|
|
58
50
|
def add_rerun_filter
|
59
|
-
to_rerun = Lopata::Client.new
|
60
|
-
|
61
|
-
Lopata::Config.filters << -> (scenario) { to_rerun.include?(scenario.title) }
|
51
|
+
to_rerun = Lopata::Client.new.to_rerun
|
52
|
+
Lopata.configuration.filters << -> (scenario) { to_rerun.include?(scenario.title) }
|
62
53
|
end
|
63
54
|
end
|
64
55
|
end
|
data/lib/lopata/scenario.rb
CHANGED
@@ -21,7 +21,9 @@ class Lopata::Scenario
|
|
21
21
|
private
|
22
22
|
|
23
23
|
def method_missing(method, *args, &block)
|
24
|
-
if
|
24
|
+
if execution.let_methods.include?(method)
|
25
|
+
instance_exec(*args, &execution.let_methods[method])
|
26
|
+
elsif metadata.keys.include?(method)
|
25
27
|
metadata[method]
|
26
28
|
else
|
27
29
|
super
|
@@ -29,7 +31,7 @@ class Lopata::Scenario
|
|
29
31
|
end
|
30
32
|
|
31
33
|
def respond_to_missing?(method, *)
|
32
|
-
metadata.keys.include?(method) or super
|
34
|
+
execution.let_methods.include?(method) or metadata.keys.include?(method) or super
|
33
35
|
end
|
34
36
|
|
35
37
|
class Execution
|
@@ -38,6 +40,7 @@ class Lopata::Scenario
|
|
38
40
|
def initialize(title, options_title, metadata = {})
|
39
41
|
@title = [title, options_title].compact.reject(&:empty?).join(' ')
|
40
42
|
@metadata = metadata
|
43
|
+
@let_methods = {}
|
41
44
|
@status = :not_runned
|
42
45
|
@steps = []
|
43
46
|
@scenario = Lopata::Scenario.new(self)
|
@@ -45,8 +48,9 @@ class Lopata::Scenario
|
|
45
48
|
|
46
49
|
def run
|
47
50
|
@status = :running
|
51
|
+
sort_steps
|
48
52
|
world.notify_observers(:scenario_started, self)
|
49
|
-
|
53
|
+
steps.each(&method(:run_step))
|
50
54
|
@status = steps.any?(&:failed?) ? :failed : :passed
|
51
55
|
world.notify_observers(:scenario_finished, self)
|
52
56
|
cleanup
|
@@ -57,18 +61,19 @@ class Lopata::Scenario
|
|
57
61
|
@current_step = step
|
58
62
|
step.run(scenario)
|
59
63
|
skip_rest if step.failed? && step.skip_rest_on_failure?
|
64
|
+
@current_step = nil
|
60
65
|
end
|
61
66
|
|
62
67
|
def world
|
63
|
-
|
68
|
+
Lopata.world
|
64
69
|
end
|
65
70
|
|
66
71
|
def failed?
|
67
72
|
status == :failed
|
68
73
|
end
|
69
74
|
|
70
|
-
def
|
71
|
-
steps.reject(&:teardown_group?) + steps.select(&:teardown_group?)
|
75
|
+
def sort_steps
|
76
|
+
@steps = steps.reject(&:teardown_group?) + steps.select(&:teardown_group?)
|
72
77
|
end
|
73
78
|
|
74
79
|
def skip_rest
|
@@ -83,6 +88,25 @@ class Lopata::Scenario
|
|
83
88
|
end
|
84
89
|
end
|
85
90
|
|
91
|
+
def let_methods
|
92
|
+
if current_step
|
93
|
+
@let_methods.merge(current_step.let_methods)
|
94
|
+
else
|
95
|
+
@let_methods
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def let(method_name, &block)
|
100
|
+
# define_singleton_method method_name, &block
|
101
|
+
base =
|
102
|
+
if current_step && !current_step.groups.empty?
|
103
|
+
current_step.groups.last.let_methods
|
104
|
+
else
|
105
|
+
@let_methods
|
106
|
+
end
|
107
|
+
base[method_name] = block
|
108
|
+
end
|
109
|
+
|
86
110
|
def cleanup
|
87
111
|
@title = nil
|
88
112
|
@metadata = nil
|
@@ -1,5 +1,5 @@
|
|
1
1
|
class Lopata::ScenarioBuilder
|
2
|
-
attr_reader :title, :common_metadata
|
2
|
+
attr_reader :title, :common_metadata, :options, :diagonals
|
3
3
|
attr_accessor :shared_step, :group
|
4
4
|
|
5
5
|
def self.define(title, metadata = {}, &block)
|
@@ -10,10 +10,12 @@ class Lopata::ScenarioBuilder
|
|
10
10
|
|
11
11
|
def initialize(title, metadata = {})
|
12
12
|
@title, @common_metadata = title, metadata
|
13
|
+
@diagonals = []
|
14
|
+
@options = []
|
13
15
|
end
|
14
16
|
|
15
17
|
def build
|
16
|
-
filters = Lopata
|
18
|
+
filters = Lopata.configuration.filters
|
17
19
|
option_combinations.each do |option_set|
|
18
20
|
metadata = common_metadata.merge(option_set.metadata)
|
19
21
|
scenario = Lopata::Scenario::Execution.new(title, option_set.title, metadata)
|
@@ -31,26 +33,12 @@ class Lopata::ScenarioBuilder
|
|
31
33
|
end
|
32
34
|
end
|
33
35
|
|
34
|
-
def as(*args, &block)
|
35
|
-
@roles = args.flatten
|
36
|
-
@roles << CalculatedValue.new(&block) if block_given?
|
37
|
-
@role_options = nil
|
38
|
-
end
|
39
|
-
|
40
|
-
def role_options
|
41
|
-
@role_options ||= build_role_options
|
42
|
-
end
|
43
|
-
|
44
36
|
def metadata(hash)
|
45
37
|
raise 'metadata expected to be a Hash' unless hash.is_a?(Hash)
|
46
38
|
@common_metadata ||= {}
|
47
39
|
@common_metadata.merge! hash
|
48
40
|
end
|
49
41
|
|
50
|
-
def without_user
|
51
|
-
@without_user = true
|
52
|
-
end
|
53
|
-
|
54
42
|
def skip_when(&block)
|
55
43
|
@skip_when = block
|
56
44
|
end
|
@@ -89,73 +77,42 @@ class Lopata::ScenarioBuilder
|
|
89
77
|
|
90
78
|
def steps_with_hooks
|
91
79
|
s = []
|
92
|
-
unless Lopata
|
93
|
-
s << Lopata::ActionStep.new(:setup, *Lopata
|
80
|
+
unless Lopata.configuration.before_scenario_steps.empty?
|
81
|
+
s << Lopata::ActionStep.new(:setup, *Lopata.configuration.before_scenario_steps)
|
94
82
|
end
|
95
83
|
|
96
84
|
s += steps
|
97
85
|
|
98
|
-
unless Lopata
|
99
|
-
s << Lopata::ActionStep.new(:teardown, *Lopata
|
86
|
+
unless Lopata.configuration.after_scenario_steps.empty?
|
87
|
+
s << Lopata::ActionStep.new(:teardown, *Lopata.configuration.after_scenario_steps)
|
100
88
|
end
|
101
89
|
|
102
90
|
s
|
103
91
|
end
|
104
92
|
|
105
|
-
def cleanup(*args, &block)
|
106
|
-
add_step_as_is(:cleanup, *args, &block)
|
107
|
-
end
|
108
|
-
|
109
|
-
def add_step_as_is(method_name, *args, &block)
|
110
|
-
steps << Lopata::Step.new(method_name, *args) do
|
111
|
-
# do not convert args - symbols mean name of instance variable
|
112
|
-
# run_step method_name, *args, &block
|
113
|
-
instance_exec(&block) if block
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
93
|
def let(method_name, &block)
|
118
|
-
steps << Lopata::Step.new(
|
119
|
-
|
94
|
+
steps << Lopata::Step.new(:let) do
|
95
|
+
execution.let(method_name, &block)
|
120
96
|
end
|
121
97
|
end
|
122
98
|
|
123
|
-
def build_role_options
|
124
|
-
return [] unless roles
|
125
|
-
[Diagonal.new(:as, roles.map { |r| [nil, r] })]
|
126
|
-
end
|
127
|
-
|
128
|
-
def roles
|
129
|
-
return false if @without_user
|
130
|
-
@roles ||= [Lopata::Config.default_role].compact
|
131
|
-
end
|
132
|
-
|
133
99
|
def option(metadata_key, variants)
|
134
|
-
options << Option.new(metadata_key, variants)
|
100
|
+
@options << Option.new(metadata_key, variants)
|
135
101
|
end
|
136
102
|
|
137
103
|
def diagonal(metadata_key, variants)
|
138
|
-
diagonals << Diagonal.new(metadata_key, variants)
|
139
|
-
end
|
140
|
-
|
141
|
-
def options
|
142
|
-
@options ||= []
|
143
|
-
end
|
144
|
-
|
145
|
-
def diagonals
|
146
|
-
@diagonals ||= []
|
104
|
+
@diagonals << Diagonal.new(metadata_key, variants)
|
147
105
|
end
|
148
106
|
|
149
107
|
def option_combinations
|
150
|
-
combinations = combine([OptionSet.new], options + diagonals
|
151
|
-
while !
|
152
|
-
combinations << OptionSet.new(*(options + diagonals
|
108
|
+
combinations = combine([OptionSet.new], options + diagonals)
|
109
|
+
while !diagonals.all?(&:complete?)
|
110
|
+
combinations << OptionSet.new(*(options + diagonals).map(&:next_variant))
|
153
111
|
end
|
154
112
|
combinations.reject { |option_set| skip?(option_set) }
|
155
113
|
end
|
156
114
|
|
157
115
|
def combine(source_combinations, rest_options)
|
158
|
-
# raise 'source_combinations cannot be empty' if source_combinations.blank?
|
159
116
|
return source_combinations if rest_options.empty?
|
160
117
|
combinations = []
|
161
118
|
current_option = rest_options.shift
|
@@ -168,7 +125,7 @@ class Lopata::ScenarioBuilder
|
|
168
125
|
end
|
169
126
|
|
170
127
|
def world
|
171
|
-
|
128
|
+
Lopata.world
|
172
129
|
end
|
173
130
|
|
174
131
|
# Набор вариантов, собранный для одного теста
|