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
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7fd7651cf81d31a19644da80e0837649daa58e57
|
|
4
|
+
data.tar.gz: a3ab1acad8e60e01cfb3ea2a40e2738226addb8a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8eca0bcbda114f618032f367494e1c53fa7d7fb9bfd5153baf40de7d8e487ec5889cb4a5c07f2f1e110711a122dd162c4c7294ffe3bdadd890c46befc5a7e281
|
|
7
|
+
data.tar.gz: 0e33fcc4ebbe3efcc9ca3142e00f70732edddf4c0f04d0516c4454b53dfbcc4ee366668462bcac0a2573c4d54478952f69ef7f3fd58dfc9b81e2aa2bb0847995
|
data/bin/moto
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env ruby
|
|
2
2
|
|
|
3
|
-
require_relative '../lib/
|
|
3
|
+
require_relative '../lib/test_logging'
|
|
4
|
+
require_relative '../lib/test/base'
|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
require_relative '../lib/reporting/listeners/base'
|
|
7
|
+
require_relative '../lib/reporting/listeners/console'
|
|
8
|
+
require_relative '../lib/reporting/listeners/console_dots'
|
|
9
|
+
require_relative '../lib/reporting/listeners/junit_xml'
|
|
10
|
+
require_relative '../lib/reporting/listeners/webui'
|
|
11
|
+
|
|
12
|
+
require_relative '../lib/parameter_parser'
|
|
13
|
+
Moto::ParameterParser.parse_user_input(ARGV)
|
data/lib/empty_listener.rb
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
module Moto
|
|
2
|
-
module EmptyListener
|
|
3
|
-
|
|
4
|
-
def start_run
|
|
5
|
-
end
|
|
6
|
-
|
|
7
|
-
def end_run
|
|
8
|
-
end
|
|
9
|
-
|
|
10
|
-
def start_test(test)
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
def end_test(test)
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
end
|
|
1
|
+
module Moto
|
|
2
|
+
module EmptyListener
|
|
3
|
+
|
|
4
|
+
def start_run
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def end_run
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def start_test(test)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def end_test(test)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
end
|
|
17
17
|
end
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
require 'fileutils'
|
|
2
|
+
|
|
3
|
+
module Moto
|
|
4
|
+
module Modes
|
|
5
|
+
module Generate
|
|
6
|
+
class TestTemplateGenerator
|
|
7
|
+
|
|
8
|
+
# Creates directories and file with class template for a test.
|
|
9
|
+
# @param options [Hash] Informations required perfrom the task.
|
|
10
|
+
# options[:app_name] Name of the application that uses Moto Framework.
|
|
11
|
+
# options[:dir] Subdirectories of MotoApp/tests/ where test should be placed.
|
|
12
|
+
# options[:base_class] Path and filename of class from which the test will derive.
|
|
13
|
+
# options[:force] Whether generator should forcibly overwrite previously existing file.
|
|
14
|
+
def self.run(options)
|
|
15
|
+
|
|
16
|
+
# Build list of modules basing on the name of the application and subdirectory provided by the user.
|
|
17
|
+
# Second module is always 'tests' since it's where they should be kept.
|
|
18
|
+
modules = [options[:app_name], 'tests'] + options[:dir].split('/')
|
|
19
|
+
modules.map!(&:camelize)
|
|
20
|
+
|
|
21
|
+
# Name of the class in the template
|
|
22
|
+
class_name = modules.last
|
|
23
|
+
|
|
24
|
+
# Evaluate fully qualified name of the class to derive from or, if not specified
|
|
25
|
+
# use Moto's default one
|
|
26
|
+
if options[:base_class].nil?
|
|
27
|
+
base_class_qualified_name = 'Moto::Test::Base'
|
|
28
|
+
else
|
|
29
|
+
base_class_qualified_name = "#{options[:app_name]}::Lib::Test::#{options[:base_class].split('/').join('::').camelize}"
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Where to put finished template
|
|
33
|
+
test_file = File.basename(options[:dir]) + '.rb'
|
|
34
|
+
test_dir = MotoApp::DIR + '/tests/' + options[:dir]
|
|
35
|
+
test_path = "#{test_dir}/#{test_file}"
|
|
36
|
+
|
|
37
|
+
# Create directory
|
|
38
|
+
FileUtils.mkdir_p(test_dir)
|
|
39
|
+
|
|
40
|
+
if !File.exist?(test_path) || options[:force]
|
|
41
|
+
# Create new file in specified location and add class' template to it
|
|
42
|
+
File.open(test_path, 'w+') do |file|
|
|
43
|
+
|
|
44
|
+
indent = 0
|
|
45
|
+
|
|
46
|
+
if options[:base_class].nil?
|
|
47
|
+
file << "\n"
|
|
48
|
+
else
|
|
49
|
+
file << "require './lib/test/#{options[:base_class]}.rb'\n\n"
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
modules.each do |m|
|
|
53
|
+
file << (' ' * indent) + "module #{m}\n"
|
|
54
|
+
indent += 2
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
file << (' ' * indent) + "# Class template genereated by 'moto generate'\n"
|
|
58
|
+
file << (' ' * indent) + "class #{class_name} < #{base_class_qualified_name}\n\n"
|
|
59
|
+
indent += 2
|
|
60
|
+
file << (' ' * indent) + "def run\n"
|
|
61
|
+
file << (' ' * indent) + "end\n\n"
|
|
62
|
+
indent -= 2
|
|
63
|
+
file << (' ' * indent) + "end\n"
|
|
64
|
+
|
|
65
|
+
modules.each do
|
|
66
|
+
indent -= 2
|
|
67
|
+
file << (' ' * indent) + "end\n"
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
puts 'Result:'
|
|
73
|
+
puts " File: #{test_path}"
|
|
74
|
+
puts " Class: #{class_name} < #{base_class_qualified_name}"
|
|
75
|
+
else
|
|
76
|
+
raise 'File already exists. Use -f or --force to overwrite existing contents.'
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
require_relative '../reporting/test_reporter'
|
|
2
|
+
|
|
3
|
+
require_relative '../test/metadata_generator'
|
|
4
|
+
|
|
5
|
+
require_relative 'generate/test_template_generator'
|
|
6
|
+
require_relative 'run/dry_runner'
|
|
7
|
+
require_relative 'run/test_runner'
|
|
8
|
+
require_relative 'validate/test_validator'
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
module Moto
|
|
12
|
+
module Modes
|
|
13
|
+
class ModeSelector
|
|
14
|
+
|
|
15
|
+
def run(parsed_arguments)
|
|
16
|
+
tests_metadata = prepare_metadata(parsed_arguments)
|
|
17
|
+
test_reporter = prepare_test_reporter(parsed_arguments)
|
|
18
|
+
|
|
19
|
+
if Moto::Lib::Config.moto[:test_runner][:dry_run]
|
|
20
|
+
runner = Moto::Modes::Run::DryRunner.new(tests_metadata, test_reporter)
|
|
21
|
+
else
|
|
22
|
+
runner = Moto::Modes::Run::TestRunner.new(tests_metadata, test_reporter, parsed_arguments[:stop_on])
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
runner.run
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def generate(parsed_arguments)
|
|
29
|
+
Moto::Modes::Generate::TestTemplateGenerator.run(parsed_arguments)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def validate(parsed_arguments)
|
|
33
|
+
tests_metadata = prepare_metadata(parsed_arguments)
|
|
34
|
+
test_reporter = prepare_test_reporter(parsed_arguments)
|
|
35
|
+
|
|
36
|
+
validation_options = {}
|
|
37
|
+
validation_options[:tags_regex_positive] = parsed_arguments[:validator_regex_positive] if parsed_arguments[:validator_regex_positive]
|
|
38
|
+
validation_options[:tags_regex_negative] = parsed_arguments[:validator_regex_negative] if parsed_arguments[:validator_regex_negative]
|
|
39
|
+
validation_options[:has_tags] = parsed_arguments.key?(:validate_has_tags)
|
|
40
|
+
validation_options[:has_description] = parsed_arguments.key?(:validate_has_description)
|
|
41
|
+
validation_options[:tag_whitelist] = parsed_arguments[:tag_whitelist] if parsed_arguments[:tag_whitelist]
|
|
42
|
+
|
|
43
|
+
validator = Moto::Modes::Validate::TestValidator.new(tests_metadata, validation_options, test_reporter)
|
|
44
|
+
validator.run
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def version
|
|
48
|
+
puts Moto::VERSION
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def prepare_metadata(parsed_arguments)
|
|
52
|
+
tests_metadata = Moto::Test::MetadataGenerator.generate(parsed_arguments[:tests],
|
|
53
|
+
parsed_arguments[:tags],
|
|
54
|
+
parsed_arguments[:filters])
|
|
55
|
+
|
|
56
|
+
# TODO Display criteria used
|
|
57
|
+
if tests_metadata.empty?
|
|
58
|
+
puts 'No tests found for given arguments.'
|
|
59
|
+
Kernel.exit(-1)
|
|
60
|
+
else
|
|
61
|
+
return tests_metadata
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
private :prepare_metadata
|
|
65
|
+
|
|
66
|
+
def prepare_test_reporter(parsed_arguments)
|
|
67
|
+
run_params = {}
|
|
68
|
+
run_params[:run_name] = parsed_arguments[:run_name]
|
|
69
|
+
run_params[:suite_name] = parsed_arguments[:suite_name]
|
|
70
|
+
run_params[:assignee] = parsed_arguments[:assignee]
|
|
71
|
+
|
|
72
|
+
Moto::Reporting::TestReporter.new(parsed_arguments[:listeners], run_params)
|
|
73
|
+
end
|
|
74
|
+
private :prepare_test_reporter
|
|
75
|
+
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
require_relative '../../reporting/test_reporter'
|
|
2
|
+
require_relative '../../test/generator'
|
|
3
|
+
|
|
4
|
+
module Moto
|
|
5
|
+
module Modes
|
|
6
|
+
module Run
|
|
7
|
+
class DryRunner
|
|
8
|
+
|
|
9
|
+
# @param [Array] tests_metadata Collection of [Moto::Test::Metadata] objects describing Tests
|
|
10
|
+
# @param [Moto::Reporting::TestReporter] test_reporter Reporter of test/run statuses that communicates with external status listeners
|
|
11
|
+
def initialize(tests_metadata, test_reporter)
|
|
12
|
+
@tests_metadata = tests_metadata
|
|
13
|
+
@test_reporter = test_reporter
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def run
|
|
17
|
+
@test_reporter.report_start_run
|
|
18
|
+
|
|
19
|
+
test_generator = Moto::Test::Generator.new
|
|
20
|
+
@tests_metadata.each do |metadata|
|
|
21
|
+
test_variants = test_generator.get_test_with_variants(metadata)
|
|
22
|
+
test_variants.each do |tc|
|
|
23
|
+
@test_reporter.report_start_test(tc.status, tc.metadata)
|
|
24
|
+
tc.status.initialize_run
|
|
25
|
+
tc.status.log_exception(Exceptions::TestSkipped.new('Dry run.'))
|
|
26
|
+
tc.status.finalize_run
|
|
27
|
+
@test_reporter.report_end_test(tc.status)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
@test_reporter.report_end_run
|
|
32
|
+
|
|
33
|
+
# Exit application with code that represents status of test run
|
|
34
|
+
Kernel.exit(@test_reporter.run_status.bitmap)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
require 'thread'
|
|
2
|
+
require_relative '../../test/generator'
|
|
3
|
+
|
|
4
|
+
# Thread safe provider of test instances
|
|
5
|
+
|
|
6
|
+
module Moto
|
|
7
|
+
module Modes
|
|
8
|
+
module Run
|
|
9
|
+
class TestProvider
|
|
10
|
+
|
|
11
|
+
# @param [Array] tests_metadata
|
|
12
|
+
def initialize(tests_metadata)
|
|
13
|
+
super()
|
|
14
|
+
@test_repeats = Moto::Lib::Config.moto[:test_runner][:test_repeats]
|
|
15
|
+
@current_test_repeat = 1
|
|
16
|
+
@queue = Queue.new
|
|
17
|
+
@tests_metadata = tests_metadata
|
|
18
|
+
@test_generator = Moto::Test::Generator.new
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Use this to retrieve tests safely in multithreaded environment
|
|
22
|
+
def get_test
|
|
23
|
+
create_tests
|
|
24
|
+
@queue.pop
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Pushes new tests to the queue if possible and the queue is already empty
|
|
28
|
+
def create_tests
|
|
29
|
+
if @queue.empty?
|
|
30
|
+
|
|
31
|
+
test_metadata = get_test_metadata
|
|
32
|
+
|
|
33
|
+
if test_metadata
|
|
34
|
+
test_variants = @test_generator.get_test_with_variants(test_metadata)
|
|
35
|
+
test_variants.each do |test|
|
|
36
|
+
@queue.push(test)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
private :create_tests
|
|
43
|
+
|
|
44
|
+
# Returns metadata of the test while supporting the number of repeats specified by the user
|
|
45
|
+
# return [Moto::Test::Metadata]
|
|
46
|
+
def get_test_metadata
|
|
47
|
+
|
|
48
|
+
if @current_test_repeat == 1
|
|
49
|
+
@test_metadata = @tests_metadata.shift
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
if @current_test_repeat == @test_repeats
|
|
53
|
+
@current_test_repeat = 1
|
|
54
|
+
else
|
|
55
|
+
@current_test_repeat += 1
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
@test_metadata
|
|
59
|
+
end
|
|
60
|
+
private :get_test_metadata
|
|
61
|
+
|
|
62
|
+
# Number of threads waiting for a job
|
|
63
|
+
def num_waiting
|
|
64
|
+
@queue.num_waiting
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
require_relative '../../reporting/test_reporter'
|
|
2
|
+
require_relative 'test_provider'
|
|
3
|
+
require_relative 'thread_context'
|
|
4
|
+
|
|
5
|
+
module Moto
|
|
6
|
+
module Modes
|
|
7
|
+
module Run
|
|
8
|
+
class TestRunner
|
|
9
|
+
|
|
10
|
+
attr_reader :test_reporter
|
|
11
|
+
|
|
12
|
+
# @param [Array] tests_metadata Collection of [Moto::Test::Metadata] objects describing Tests
|
|
13
|
+
# @param [Moto::Reporting::TestReporter] test_reporter Reporter of test/run statuses that communicates with external status listeners
|
|
14
|
+
# @param [Hash] stop_conditions Describe when TestRunner should abnormally stop its execution
|
|
15
|
+
# :error [Boolean]
|
|
16
|
+
# :fail [Boolean]
|
|
17
|
+
# :skip [Boolean]
|
|
18
|
+
def initialize(tests_metadata, test_reporter, stop_conditions)
|
|
19
|
+
@tests_metadata = tests_metadata
|
|
20
|
+
@test_reporter = test_reporter
|
|
21
|
+
@stop_conditions = stop_conditions
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def run
|
|
25
|
+
test_provider = TestProvider.new(@tests_metadata)
|
|
26
|
+
threads_max = Moto::Lib::Config.moto[:test_runner][:thread_count] || 1
|
|
27
|
+
|
|
28
|
+
# remove log/screenshot files from previous execution
|
|
29
|
+
@tests_metadata.each do |metadata|
|
|
30
|
+
FileUtils.rm_rf("#{File.dirname(metadata.test_path)}/logs")
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
@test_reporter.report_start_run
|
|
34
|
+
|
|
35
|
+
# Create as many threads as we're allowed by the config file.
|
|
36
|
+
# test_provider.get_test - will invoke Queue.pop thus putting the thread to sleep
|
|
37
|
+
# once there is no more work.
|
|
38
|
+
|
|
39
|
+
Thread.abort_on_exception = true
|
|
40
|
+
|
|
41
|
+
(1..threads_max).each do |index|
|
|
42
|
+
Thread.new do
|
|
43
|
+
Thread.current[:id] = index
|
|
44
|
+
loop do
|
|
45
|
+
tc = ThreadContext.new(test_provider.get_test, @test_reporter)
|
|
46
|
+
tc.run
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Waiting for all threads to run out of work so we can end the application
|
|
52
|
+
# or abonormal termination to be triggered based on options provided by the user
|
|
53
|
+
loop do
|
|
54
|
+
run_status = @test_reporter.run_status
|
|
55
|
+
if (test_provider.num_waiting == threads_max) ||
|
|
56
|
+
(@stop_conditions[:error] && run_status.tests_error.length > 0) ||
|
|
57
|
+
(@stop_conditions[:fail] && run_status.tests_failed.length > 0) ||
|
|
58
|
+
(@stop_conditions[:skip] && run_status.tests_skipped.length > 0)
|
|
59
|
+
break
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
sleep 2
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
@test_reporter.report_end_run
|
|
66
|
+
|
|
67
|
+
# Exit application with code that represents status of test run
|
|
68
|
+
Kernel.exit(@test_reporter.run_status.bitmap)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|