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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e7d75bfa8620395beba5bd52ac893556c9662519
4
- data.tar.gz: f47066f906dc8b4e8edc6ad3581ff57f49425113
3
+ metadata.gz: 7fd7651cf81d31a19644da80e0837649daa58e57
4
+ data.tar.gz: a3ab1acad8e60e01cfb3ea2a40e2738226addb8a
5
5
  SHA512:
6
- metadata.gz: 7bf1de8ba4eea78865dd1c64323f069ddf9f61602bbc44b0e7e48a30bccabbbc9e0eeeb54a19f9e935d680ee7a6c08cb4e3201bd271fa8d37ef2e91c99030c77
7
- data.tar.gz: ac99006b16ea7f86f00651a24a7a4186970f99aeb6df0d4f2306e0e921d3c23b850a95a1d8afb0f3d5bc3a5f714b0e980b5229e6b6cdb45c88eb189b0329b8d9
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/parser'
3
+ require_relative '../lib/test_logging'
4
+ require_relative '../lib/test/base'
4
5
 
5
- Moto::Parser.run ARGV
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)
@@ -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
@@ -1,6 +1,6 @@
1
1
  module Moto
2
2
  module Exceptions
3
- class MotoException < RuntimeError
3
+ class Base < RuntimeError
4
4
 
5
5
  end
6
6
  end
@@ -1,6 +1,8 @@
1
+ require_relative 'base'
2
+
1
3
  module Moto
2
4
  module Exceptions
3
- class TestForcedFailure < MotoException
5
+ class TestForcedFailure < Base
4
6
 
5
7
  end
6
8
  end
@@ -1,6 +1,8 @@
1
+ require_relative 'base'
2
+
1
3
  module Moto
2
4
  module Exceptions
3
- class TestForcedPassed < MotoException
5
+ class TestForcedPassed < Base
4
6
 
5
7
  end
6
8
  end
@@ -1,6 +1,8 @@
1
+ require_relative 'base'
2
+
1
3
  module Moto
2
4
  module Exceptions
3
- class TestSkipped < MotoException
5
+ class TestSkipped < Base
4
6
 
5
7
  end
6
8
  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