moto 0.9.11 → 0.9.17
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/bin/moto +10 -2
- data/lib/empty_listener.rb +16 -16
- data/lib/exceptions/{moto.rb → base.rb} +1 -1
- data/lib/exceptions/test_forced_failure.rb +3 -1
- data/lib/exceptions/test_forced_passed.rb +3 -1
- data/lib/exceptions/test_skipped.rb +3 -1
- data/lib/modes/generate/test_template_generator.rb +82 -0
- data/lib/modes/mode_selector.rb +78 -0
- data/lib/modes/run/dry_runner.rb +40 -0
- data/lib/modes/run/test_provider.rb +71 -0
- data/lib/modes/run/test_runner.rb +74 -0
- data/lib/modes/run/thread_context.rb +81 -0
- data/lib/modes/validate/test_validator.rb +87 -0
- data/lib/parameter_parser.rb +282 -0
- data/lib/reporting/test_reporter.rb +0 -1
- data/lib/test/base.rb +0 -2
- data/lib/{runner/test_generator.rb → test/generator.rb} +26 -23
- data/lib/test/metadata.rb +1 -1
- data/lib/test/metadata_generator.rb +78 -0
- data/lib/test/status.rb +0 -3
- data/lib/version.rb +1 -1
- metadata +14 -14
- data/lib/app_generator.rb +0 -80
- data/lib/cli.rb +0 -120
- data/lib/initializer.rb +0 -7
- data/lib/parser.rb +0 -182
- data/lib/reporting/listeners/webui_deprecated.rb +0 -127
- data/lib/runner/dry_runner.rb +0 -37
- data/lib/runner/test_provider.rb +0 -68
- data/lib/runner/test_runner.rb +0 -71
- data/lib/runner/thread_context.rb +0 -77
data/lib/initializer.rb
DELETED
data/lib/parser.rb
DELETED
|
@@ -1,182 +0,0 @@
|
|
|
1
|
-
require 'optparse'
|
|
2
|
-
require 'yaml'
|
|
3
|
-
|
|
4
|
-
require_relative '../lib/cli'
|
|
5
|
-
require_relative '../lib/app_generator'
|
|
6
|
-
require_relative '../lib/config'
|
|
7
|
-
module Moto
|
|
8
|
-
|
|
9
|
-
class Parser
|
|
10
|
-
|
|
11
|
-
def self.run(argv)
|
|
12
|
-
begin
|
|
13
|
-
|
|
14
|
-
if argv[0] == '--version'
|
|
15
|
-
puts Moto::VERSION
|
|
16
|
-
elsif argv[0] == 'run' && argv.length > 1
|
|
17
|
-
Moto::Cli.run(run_parse(argv))
|
|
18
|
-
elsif argv[0] == 'generate' && argv.length > 1
|
|
19
|
-
Moto::AppGenerator.run(generate_parse(argv))
|
|
20
|
-
else
|
|
21
|
-
show_help
|
|
22
|
-
end
|
|
23
|
-
rescue SystemExit => e
|
|
24
|
-
Kernel.exit(e.status)
|
|
25
|
-
rescue Exception => e
|
|
26
|
-
puts e.message + "\n\n"
|
|
27
|
-
puts e.backtrace.join("\n")
|
|
28
|
-
end
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
def self.run_parse(argv)
|
|
32
|
-
require 'bundler/setup'
|
|
33
|
-
Bundler.require
|
|
34
|
-
|
|
35
|
-
# Default options
|
|
36
|
-
options = {}
|
|
37
|
-
options[:listeners] = []
|
|
38
|
-
options[:run_name] = nil
|
|
39
|
-
options[:suite_name] = nil
|
|
40
|
-
options[:assignee] = nil
|
|
41
|
-
options[:stop_on] = {error: false, fail: false, skip: false}
|
|
42
|
-
|
|
43
|
-
# Parse arguments
|
|
44
|
-
OptionParser.new do |opts|
|
|
45
|
-
opts.on('-t', '--tests Tests', Array) { |v| options[:tests] = v }
|
|
46
|
-
opts.on('-g', '--tags Tags', Array) { |v| options[:tags] = v }
|
|
47
|
-
opts.on('-f', '--filters Filters', Array) { |v| options[:filters] = v }
|
|
48
|
-
opts.on('-l', '--listeners Listeners', Array) { |v| options[:listeners] = v }
|
|
49
|
-
opts.on('-e', '--environment Environment') { |v| options[:environment] = v }
|
|
50
|
-
opts.on('-r', '--runname RunName') { |v| options[:run_name] = v }
|
|
51
|
-
opts.on('-s', '--suitename SuiteName') { |v| options[:suite_name] = v }
|
|
52
|
-
opts.on('-a', '--assignee Assignee') { |v| options[:assignee] = v }
|
|
53
|
-
opts.on('-c', '--config Config') { |v| options[:config_name] = v }
|
|
54
|
-
opts.on('--threads ThreadCount', Integer) { |v| options[:threads] = v }
|
|
55
|
-
opts.on('--attempts AttemptCount', Integer) { |v| options[:attempts] = v }
|
|
56
|
-
opts.on('--stop-on-error') { options[:stop_on][:error] = true }
|
|
57
|
-
opts.on('--stop-on-fail') { options[:stop_on][:fail] = true }
|
|
58
|
-
opts.on('--stop-on-skip') { options[:stop_on][:skip] = true }
|
|
59
|
-
opts.on('--dry-run') { options[:dry_run] = true }
|
|
60
|
-
end.parse!
|
|
61
|
-
|
|
62
|
-
if options[:tests]
|
|
63
|
-
options[:tests].each do |path|
|
|
64
|
-
path.sub!(%r{\/$}, '') # remove trailing "/"
|
|
65
|
-
end
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
if options[:run_name].nil?
|
|
69
|
-
options[:run_name] = evaluate_name(options[:tests], options[:tags], options[:filters])
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
if options[:environment]
|
|
73
|
-
Moto::Lib::Config.environment = options[:environment]
|
|
74
|
-
Moto::Lib::Config.load_configuration(options[:config_name] ? options[:config_name] : 'moto')
|
|
75
|
-
else
|
|
76
|
-
puts 'ERROR: Environment is mandatory.'
|
|
77
|
-
Kernel.exit(-1)
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
Moto::Lib::Config.moto[:test_runner][:thread_count] = options[:threads] if options[:threads]
|
|
81
|
-
Moto::Lib::Config.moto[:test_runner][:test_attempt_max] = options[:attempts] if options[:attempts]
|
|
82
|
-
Moto::Lib::Config.moto[:test_runner][:dry_run] = options[:dry_run] if options[:dry_run]
|
|
83
|
-
|
|
84
|
-
return options
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
# Generate default name based on input parameters
|
|
88
|
-
def self.evaluate_name(tests, tags, filters)
|
|
89
|
-
name = ''
|
|
90
|
-
|
|
91
|
-
if tests
|
|
92
|
-
name << "Tests: #{tests.join(',')} "
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
if tags
|
|
96
|
-
name << "Tags: #{tags.join(',')} "
|
|
97
|
-
end
|
|
98
|
-
|
|
99
|
-
if filters
|
|
100
|
-
name << "Filters: #{filters.join(',')} "
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
return name
|
|
104
|
-
end
|
|
105
|
-
|
|
106
|
-
# Parses attributes passed to the application when run by 'moto generate'
|
|
107
|
-
def self.generate_parse(argv)
|
|
108
|
-
options = {}
|
|
109
|
-
|
|
110
|
-
OptionParser.new do |opts|
|
|
111
|
-
opts.on('-t', '--test Test') { |v| options[:dir ] = v }
|
|
112
|
-
opts.on('-a', '--appname AppName') { |v| options[:app_name ] = v }
|
|
113
|
-
opts.on('-b', '--baseclass BaseClass') { |v| options[:base_class] = v }
|
|
114
|
-
opts.on('-f', '--force') { options[:force ] = true }
|
|
115
|
-
end.parse!
|
|
116
|
-
|
|
117
|
-
options[:dir] = options[:dir].underscore
|
|
118
|
-
|
|
119
|
-
if options[:app_name].nil?
|
|
120
|
-
options[:app_name] = 'MotoApp'
|
|
121
|
-
end
|
|
122
|
-
|
|
123
|
-
return options
|
|
124
|
-
end
|
|
125
|
-
|
|
126
|
-
def self.show_help
|
|
127
|
-
puts """
|
|
128
|
-
Moto (#{Moto::VERSION}) CLI Help:
|
|
129
|
-
moto --version Display current version
|
|
130
|
-
|
|
131
|
-
MOTO RUN:
|
|
132
|
-
-t, --tests Tests to be executed.
|
|
133
|
-
-g, --tags Tags of tests to be executed.
|
|
134
|
-
Use # MOTO_TAGS: TAGNAME in test to assign tag.
|
|
135
|
-
-f, --filters Tags that filter tests passed via -t parameter.
|
|
136
|
-
Only tests in appropriate directory, having all of the specified tags will be executed.
|
|
137
|
-
Use # MOTO_TAGS: TAGNAME1 in test to assign tag.
|
|
138
|
-
Use ~ to filter tests that do not contain specific tag, e.g. ~tag
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
-e, --environment Mandatory environment. Environment constants and tests parametrized in certain way depend on this.
|
|
142
|
-
-c, --config Name of the config, without extension, to be loaded from MotoApp/config/CONFIG_NAME.rb
|
|
143
|
-
Default: moto (which loads: MotoApp/config/moto.rb)
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
-l, --listeners Reporters to be used.
|
|
147
|
-
Defaults are Moto::Reporting::Listeners::ConsoleDots, Moto::Reporting::Listeners::JunitXml
|
|
148
|
-
One reporter that is always used: Moto::Reporting::Listeners::KernelCode
|
|
149
|
-
-s, --suitename Name of the test suite to which should aggregate the results of current test run.
|
|
150
|
-
Required when specifying MotoWebUI as one of the listeners.
|
|
151
|
-
-r, --runname Name of the test run to which everything will be reported when using MotoWebUI.
|
|
152
|
-
Default: Value of -g or -t depending on which one was specified.
|
|
153
|
-
-a, --assignee ID of a person responsible for current test run.
|
|
154
|
-
Can have a default value set in config/webui section.
|
|
155
|
-
--threads Thread count. Run tests in parallel.
|
|
156
|
-
--attempts Attempt count. Max number of test execution times if failed.
|
|
157
|
-
|
|
158
|
-
--stop-on-error Moto will stop test execution when an error is encountered in test results
|
|
159
|
-
--stop-on-fail Moto will stop test execution when a failure is encountered in test results
|
|
160
|
-
--stop-on-skip Moto will stop test execution when a skip is encountered in test results
|
|
161
|
-
--dry-run Moto will list all test cases which would be run with provided arguments
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
MOTO GENERATE:
|
|
165
|
-
-t, --test Path and name of the test to be created.
|
|
166
|
-
Examples:
|
|
167
|
-
-ttest_name will create MotoApp/tests/test_name/test_name.rb
|
|
168
|
-
-tdir/test_name will create MotoApp/tests/dir/test_name/test_name.rb
|
|
169
|
-
-a, --appname Name of the application. Will be also used as topmost module in test file.
|
|
170
|
-
Default: MotoApp
|
|
171
|
-
-b, --baseclass File, without extension, with base class from which test will derive. Assumes one class per file.
|
|
172
|
-
Examples:
|
|
173
|
-
-btest_base will use the file in MotoApp/lib/test/test_base.rb
|
|
174
|
-
-bsubdir/test_base will use the file in MotoApp/lib/test/subdir/test_base.rb
|
|
175
|
-
By default class will derive from Moto::Test
|
|
176
|
-
-f, --force Forces generator to overwrite previously existing class file in specified location.
|
|
177
|
-
You have been warned.
|
|
178
|
-
"""
|
|
179
|
-
end
|
|
180
|
-
|
|
181
|
-
end
|
|
182
|
-
end
|
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
require 'rest-client'
|
|
2
|
-
require 'sys/uname'
|
|
3
|
-
|
|
4
|
-
module Moto
|
|
5
|
-
module Reporting
|
|
6
|
-
module Listeners
|
|
7
|
-
class WebuiDeprecated < Base
|
|
8
|
-
|
|
9
|
-
REST_MAX_TRIES = 3
|
|
10
|
-
REST_TIMEOUT = 15
|
|
11
|
-
|
|
12
|
-
def start_run
|
|
13
|
-
|
|
14
|
-
@url = config[:url]
|
|
15
|
-
@send_log_on_pass = config[:send_log_on_pass]
|
|
16
|
-
|
|
17
|
-
data = {
|
|
18
|
-
name: run_params[:name],
|
|
19
|
-
result: :running,
|
|
20
|
-
cnt_all: nil,
|
|
21
|
-
cnt_passed: nil,
|
|
22
|
-
cnt_failure: nil,
|
|
23
|
-
cnt_error: nil,
|
|
24
|
-
cnt_skipped: nil,
|
|
25
|
-
user: Sys::Uname.sysname.downcase.include?('windows') ? ENV['USERNAME'] : ENV['LOGNAME'],
|
|
26
|
-
host: Sys::Uname.nodename,
|
|
27
|
-
pid: Process.pid
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
result = try {
|
|
31
|
-
RestClient::Request.execute(method: :post, url: "#{@url}/api/runs", payload: data.to_json, timeout: REST_TIMEOUT, headers: {content_type: :json, accept: :json})
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
@run = JSON.parse(result)
|
|
35
|
-
@tests = {}
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
def end_run(run_status)
|
|
39
|
-
# PUT http://sandbox.dev:3000/api/runs/1
|
|
40
|
-
data = {
|
|
41
|
-
result: run_status.result,
|
|
42
|
-
cnt_all: run_status.tests_all.length,
|
|
43
|
-
cnt_passed: run_status.tests_passed.length,
|
|
44
|
-
cnt_failure: run_status.tests_failed.length,
|
|
45
|
-
cnt_error: run_status.tests_error.length,
|
|
46
|
-
cnt_skipped: run_status.tests_skipped.length,
|
|
47
|
-
duration: run_status.duration
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
result = try {
|
|
51
|
-
RestClient::Request.execute(method: :put, url: "#{@url}/api/runs/#{@run['id']}", payload: data.to_json, timeout: REST_TIMEOUT, headers: {content_type: :json, accept: :json})
|
|
52
|
-
}
|
|
53
|
-
@run = JSON.parse(result)
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
def start_test(test_status, test_metadata)
|
|
57
|
-
# POST http://sandbox.dev:3000/api/tests/create
|
|
58
|
-
data = {
|
|
59
|
-
name: test_status.name,
|
|
60
|
-
class_name: test_status.test_class_name,
|
|
61
|
-
log: nil,
|
|
62
|
-
run_id: @run['id'],
|
|
63
|
-
env: test_status.env,
|
|
64
|
-
parameters: test_status.params.to_s,
|
|
65
|
-
result: :running,
|
|
66
|
-
error: nil,
|
|
67
|
-
failures: nil
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
result = try {
|
|
71
|
-
RestClient::Request.execute(method: :post, url: "#{@url}/api/tests", payload: data.to_json, timeout: REST_TIMEOUT, headers: {content_type: :json, accept: :json})
|
|
72
|
-
}
|
|
73
|
-
@tests[test_status.name] = JSON.parse(result)
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
def end_test(test_status)
|
|
77
|
-
|
|
78
|
-
# don't send the log if the test has passed and appropriate flag is set to false
|
|
79
|
-
if test_status.results.last.code == Moto::Test::Result::PASSED && !@send_log_on_pass
|
|
80
|
-
full_log = nil
|
|
81
|
-
else
|
|
82
|
-
full_log = File.read(test_status.log_path)
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
data = {
|
|
86
|
-
log: full_log,
|
|
87
|
-
result: test_status.results.last.code,
|
|
88
|
-
error: test_status.results.last.code == Moto::Test::Result::ERROR ? nil : test_status.results.last.message,
|
|
89
|
-
failures: test_failures(test_status),
|
|
90
|
-
duration: test_status.duration
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
result = try {
|
|
94
|
-
RestClient::Request.execute(method: :put, url: "#{@url}/api/tests/#{@tests[test_status.name]['id']}", payload: data.to_json, timeout: REST_TIMEOUT, headers: {content_type: :json, accept: :json})
|
|
95
|
-
}
|
|
96
|
-
@tests[test_status.name] = JSON.parse(result)
|
|
97
|
-
end
|
|
98
|
-
|
|
99
|
-
# @return [String] string with messages of all failures in a test
|
|
100
|
-
def test_failures(test_status)
|
|
101
|
-
test_status.results.last.failures.join("\n\t")
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
# Tries to execute, without an error, block of code passed to the function.
|
|
105
|
-
# @param block Block of code to be executed up to MAX_REST_TRIES
|
|
106
|
-
def try(&block)
|
|
107
|
-
|
|
108
|
-
tries = REST_MAX_TRIES
|
|
109
|
-
|
|
110
|
-
begin
|
|
111
|
-
yield
|
|
112
|
-
rescue
|
|
113
|
-
tries -= 1
|
|
114
|
-
tries > 0 ? retry : raise
|
|
115
|
-
end
|
|
116
|
-
end
|
|
117
|
-
|
|
118
|
-
# @return [Hash] Hash with config for WebUI
|
|
119
|
-
def config
|
|
120
|
-
Moto::Lib::Config.moto[:test_reporter][:listeners][:webui]
|
|
121
|
-
end
|
|
122
|
-
private :config
|
|
123
|
-
|
|
124
|
-
end
|
|
125
|
-
end
|
|
126
|
-
end
|
|
127
|
-
end
|
data/lib/runner/dry_runner.rb
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
require_relative '../reporting/test_reporter'
|
|
2
|
-
|
|
3
|
-
module Moto
|
|
4
|
-
module Runner
|
|
5
|
-
class DryRunner
|
|
6
|
-
|
|
7
|
-
# @param [Array] tests_metadata Collection of [Moto::Test::Metadata] objects describing Tests
|
|
8
|
-
# @param [Moto::Reporting::TestReporter] test_reporter Reporter of test/run statuses that communicates with external status listeners
|
|
9
|
-
def initialize(tests_metadata, test_reporter)
|
|
10
|
-
@tests_metadata = tests_metadata
|
|
11
|
-
@test_reporter = test_reporter
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
def run
|
|
15
|
-
@test_reporter.report_start_run
|
|
16
|
-
|
|
17
|
-
test_generator = TestGenerator.new
|
|
18
|
-
@tests_metadata.each do |metadata|
|
|
19
|
-
test_variants = test_generator.get_test_with_variants(metadata)
|
|
20
|
-
test_variants.each do |tc|
|
|
21
|
-
@test_reporter.report_start_test(tc.status, tc.metadata)
|
|
22
|
-
tc.status.initialize_run
|
|
23
|
-
tc.status.log_exception(Exceptions::TestSkipped.new('Dry run.'))
|
|
24
|
-
tc.status.finalize_run
|
|
25
|
-
@test_reporter.report_end_test(tc.status)
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
@test_reporter.report_end_run
|
|
30
|
-
|
|
31
|
-
# Exit application with code that represents status of test run
|
|
32
|
-
Kernel.exit(@test_reporter.run_status.bitmap)
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
end
|
data/lib/runner/test_provider.rb
DELETED
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
require 'thread'
|
|
2
|
-
require_relative 'test_generator'
|
|
3
|
-
|
|
4
|
-
module Moto
|
|
5
|
-
module Runner
|
|
6
|
-
# Thread safe provider of test instances
|
|
7
|
-
class TestProvider
|
|
8
|
-
|
|
9
|
-
# @param [Array] tests_metadata
|
|
10
|
-
def initialize(tests_metadata)
|
|
11
|
-
super()
|
|
12
|
-
@test_repeats = Moto::Lib::Config.moto[:test_runner][:test_repeats]
|
|
13
|
-
@current_test_repeat = 1
|
|
14
|
-
@queue = Queue.new
|
|
15
|
-
@tests_metadata = tests_metadata
|
|
16
|
-
@test_generator = TestGenerator.new
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
# Use this to retrieve tests safely in multithreaded environment
|
|
20
|
-
def get_test
|
|
21
|
-
create_tests
|
|
22
|
-
@queue.pop
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
# Pushes new tests to the queue if possible and the queue is already empty
|
|
26
|
-
def create_tests
|
|
27
|
-
if @queue.empty?
|
|
28
|
-
|
|
29
|
-
test_metadata = get_test_metadata
|
|
30
|
-
|
|
31
|
-
if test_metadata
|
|
32
|
-
test_variants = @test_generator.get_test_with_variants(test_metadata)
|
|
33
|
-
test_variants.each do |test|
|
|
34
|
-
@queue.push(test)
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
|
-
private :create_tests
|
|
41
|
-
|
|
42
|
-
# Returns metadata of the test while supporting the number of repeats specified by the user
|
|
43
|
-
# return [Moto::Test::Metadata]
|
|
44
|
-
def get_test_metadata
|
|
45
|
-
|
|
46
|
-
if @current_test_repeat == 1
|
|
47
|
-
@test_metadata = @tests_metadata.shift
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
if @current_test_repeat == @test_repeats
|
|
51
|
-
@current_test_repeat = 1
|
|
52
|
-
else
|
|
53
|
-
@current_test_repeat += 1
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
@test_metadata
|
|
57
|
-
end
|
|
58
|
-
private :get_test_metadata
|
|
59
|
-
|
|
60
|
-
# Number of threads waiting for a job
|
|
61
|
-
def num_waiting
|
|
62
|
-
@queue.num_waiting
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
end
|
|
66
|
-
end
|
|
67
|
-
end
|
|
68
|
-
|
data/lib/runner/test_runner.rb
DELETED
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
require_relative '../reporting/test_reporter'
|
|
2
|
-
require_relative './test_provider'
|
|
3
|
-
|
|
4
|
-
module Moto
|
|
5
|
-
module Runner
|
|
6
|
-
class TestRunner
|
|
7
|
-
|
|
8
|
-
attr_reader :test_reporter
|
|
9
|
-
|
|
10
|
-
# @param [Array] tests_metadata Collection of [Moto::Test::Metadata] objects describing Tests
|
|
11
|
-
# @param [Moto::Reporting::TestReporter] test_reporter Reporter of test/run statuses that communicates with external status listeners
|
|
12
|
-
# @param [Hash] stop_conditions Describe when TestRunner should abnormally stop its execution
|
|
13
|
-
# :error [Boolean]
|
|
14
|
-
# :fail [Boolean]
|
|
15
|
-
# :skip [Boolean]
|
|
16
|
-
def initialize(tests_metadata, test_reporter, stop_conditions)
|
|
17
|
-
@tests_metadata = tests_metadata
|
|
18
|
-
@test_reporter = test_reporter
|
|
19
|
-
@stop_conditions = stop_conditions
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
def run
|
|
23
|
-
test_provider = TestProvider.new(@tests_metadata)
|
|
24
|
-
threads_max = Moto::Lib::Config.moto[:test_runner][:thread_count] || 1
|
|
25
|
-
|
|
26
|
-
# remove log/screenshot files from previous execution
|
|
27
|
-
@tests_metadata.each do |metadata|
|
|
28
|
-
FileUtils.rm_rf("#{File.dirname(metadata.test_path)}/logs")
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
@test_reporter.report_start_run
|
|
32
|
-
|
|
33
|
-
# Create as many threads as we're allowed by the config file.
|
|
34
|
-
# test_provider.get_test - will invoke Queue.pop thus putting the thread to sleep
|
|
35
|
-
# once there is no more work.
|
|
36
|
-
|
|
37
|
-
Thread.abort_on_exception = true
|
|
38
|
-
|
|
39
|
-
(1..threads_max).each do |index|
|
|
40
|
-
Thread.new do
|
|
41
|
-
Thread.current[:id] = index
|
|
42
|
-
loop do
|
|
43
|
-
tc = ThreadContext.new(test_provider.get_test, @test_reporter)
|
|
44
|
-
tc.run
|
|
45
|
-
end
|
|
46
|
-
end
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
# Waiting for all threads to run out of work so we can end the application
|
|
50
|
-
# or abonormal termination to be triggered based on options provided by the user
|
|
51
|
-
loop do
|
|
52
|
-
run_status = @test_reporter.run_status
|
|
53
|
-
if (test_provider.num_waiting == threads_max) ||
|
|
54
|
-
(@stop_conditions[:error] && run_status.tests_error.length > 0) ||
|
|
55
|
-
(@stop_conditions[:fail] && run_status.tests_failed.length > 0) ||
|
|
56
|
-
(@stop_conditions[:skip] && run_status.tests_skipped.length > 0)
|
|
57
|
-
break
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
sleep 2
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
@test_reporter.report_end_run
|
|
64
|
-
|
|
65
|
-
# Exit application with code that represents status of test run
|
|
66
|
-
Kernel.exit(@test_reporter.run_status.bitmap)
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
end
|
|
70
|
-
end
|
|
71
|
-
end
|