moto 0.9.11 → 0.9.17
Sign up to get free protection for your applications and to get access to all the features.
- 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
|