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 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