moto 0.0.0

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e048efe2a7dae21ba01da0503fdeb40e56755827
4
+ data.tar.gz: 00882f74920d1fab0729c015e8260ecba2b115ff
5
+ SHA512:
6
+ metadata.gz: 8b89e9d40644d2a751c9e4fd7455d40395f3c2a7d682cec532e6ac8dd9cf02497338e26952ae8156eee510d9289a21dc61f286fcb8c071e29400d9f2fb88931f
7
+ data.tar.gz: e8710637b4dbbb2ccd4e2d9412f932033e79fc7baee4713b82926a4e6ac5c83732b1b76f9a02521bb714cc1835ea436171f3d7677a4e339bddcdb18b6ddca3ed
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'moto'
4
+ MotoCliRunner.run ARGV
@@ -0,0 +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
17
+ end
@@ -0,0 +1,26 @@
1
+ module Moto
2
+ module Listeners
3
+ class Base
4
+
5
+ def initialize(runner)
6
+ @runner=runner
7
+ end
8
+
9
+ def start_run
10
+ # abstract
11
+ end
12
+
13
+ def end_run
14
+ # abstract
15
+ end
16
+
17
+ def start_test(test)
18
+ # abstract
19
+ end
20
+
21
+ def end_test(test)
22
+ # abstract
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,23 @@
1
+ module Moto
2
+ module Listeners
3
+ class Console < Base
4
+
5
+ def start_run
6
+ @runner.logger.info("Starting...")
7
+ end
8
+
9
+ def end_run
10
+ @runner.logger.info("...done: #{@runner.result.summary[:result]}, duration: #{@runner.result.summary[:duration]}")
11
+ end
12
+
13
+ def start_test(test)
14
+ @runner.logger.info("Starting test #{test.name}")
15
+ end
16
+
17
+ def end_test(test)
18
+ @runner.logger.info("Ending test #{test.name} with result #{@runner.result[test.name][:result]}")
19
+ end
20
+
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,42 @@
1
+ require 'logger'
2
+ require 'yaml'
3
+ require 'active_support/inflector'
4
+ require 'active_support/core_ext/object/blank'
5
+
6
+ require_relative '../lib/empty_listener'
7
+ require_relative '../lib/runner'
8
+ require_relative '../lib/thread_context'
9
+ require_relative '../lib/result'
10
+ require_relative '../lib/test'
11
+ require_relative '../lib/listeners/base'
12
+ require_relative '../lib/listeners/console'
13
+
14
+ APP_DIR = Dir.pwd
15
+
16
+ class MotoCliRunner
17
+
18
+ def self.run(argv)
19
+ t = argv[0]
20
+ t = 'MotoApp::Tests::'+t
21
+ a = t.underscore.split('/')
22
+ test_path = (a[1..20]+[a[-1]]).join('/')
23
+
24
+ # TODO: check if this path and constat exists
25
+ require "#{APP_DIR}/#{test_path}"
26
+ test_const = t.safe_constantize
27
+
28
+ tests = [
29
+ test_const.new
30
+ ]
31
+
32
+ # parsing ARGV and creating config will come here
33
+ # instantiation of tests for ARGV params also happens here
34
+ # instantiate listeners/reporters
35
+
36
+ # listeners = []
37
+ listeners = [Moto::Listeners::Console]
38
+ runner = Moto::Runner.new(tests, listeners, thread_cnt: 3, environments: [:qa2, :qa])
39
+ runner.run
40
+ end
41
+
42
+ end
@@ -0,0 +1,59 @@
1
+ module Moto
2
+ class Result
3
+
4
+ PENDING = :pending # -2
5
+ RUNNING = :running # -1
6
+ PASSED = :passed # 0
7
+ FAILURE = :failure # 1
8
+ ERROR = :error # 2
9
+
10
+ attr_reader :summary
11
+
12
+ def [](key)
13
+ @results[key]
14
+ end
15
+
16
+ def initialize(runner)
17
+ @runner = runner
18
+ @results = {}
19
+ @summary = {}
20
+ end
21
+
22
+ def start_run
23
+ # start timer
24
+ @summary[:started_at] = Time.now.to_f
25
+ end
26
+
27
+ def end_run
28
+ # info about duration and overall execution result
29
+ @summary[:finished_at] = Time.now.to_f
30
+ @summary[:duration] = @summary[:finished_at] - @summary[:started_at]
31
+ @summary[:result] = PASSED
32
+ @summary[:result] = FAILURE unless @results.values.select{ |v| v[:failures].count > 0 }.empty?
33
+ @summary[:result] = ERROR unless @results.values.select{ |v| !v[:error].nil? }.empty?
34
+ # TODO: calculate count and percentage of errors/failures
35
+ end
36
+
37
+ def start_test(test)
38
+ @results[test.name] = { class: test.class, result: RUNNING, env: nil, params: nil, name: test.name, error: nil, failures: [] }
39
+ end
40
+
41
+ def end_test(test)
42
+ # calculate result basing on errors/failures
43
+ test.result = PASSED
44
+ test.result = FAILURE unless @results[test.name][:failures].empty?
45
+ test.result = ERROR unless @results[test.name][:error].nil?
46
+ @results[test.name][:result] = test.result
47
+ test.logger.info("Result: #{test.result}")
48
+ end
49
+
50
+ def add_failure(test, msg)
51
+ @results[test.name][:failures] << msg
52
+ end
53
+
54
+ def add_error(test, e)
55
+
56
+ end
57
+
58
+ end
59
+ end
@@ -0,0 +1,52 @@
1
+ module Moto
2
+ class Runner
3
+
4
+ attr_reader :result
5
+ attr_reader :listeners
6
+ attr_reader :logger
7
+ attr_reader :environments
8
+
9
+ def initialize(tests, listeners, config = {})
10
+ @tests = tests
11
+ @config = config
12
+ @threads = []
13
+
14
+ # TODO: initialize logger from config (yml or just ruby code)
15
+ @logger = Logger.new(STDOUT)
16
+ # @logger.level = Logger::WARN
17
+
18
+ @result = Moto::Result.new(self)
19
+
20
+ # TODO: validate envs, maybe no-env should be supported as well?
21
+ @environments = config[:environments]
22
+
23
+ @listeners = []
24
+ listeners.each do |l|
25
+ @listeners << l.new(self)
26
+ end
27
+ @listeners.unshift(@result)
28
+ end
29
+
30
+ def run
31
+ @listeners.each { |l| l.start_run }
32
+ test_slices = @tests.each_slice((@tests.size.to_f/@config[:thread_cnt]).ceil).to_a
33
+ (0...test_slices.count).each do |i|
34
+ @threads << Thread.new do
35
+ tc = ThreadContext.new(self, test_slices[i])
36
+ tc.run
37
+ end
38
+ end
39
+ @threads.each{ |t| t.join }
40
+ @listeners.each { |l| l.end_run }
41
+ # aggregate result from @tests list
42
+ end
43
+
44
+ def assert(test, condition, message)
45
+ unless condition
46
+ @result.add_failure(test, message)
47
+ test.logger.error("ASSERTION FAILED: #{message}")
48
+ end
49
+ end
50
+
51
+ end
52
+ end
@@ -0,0 +1,71 @@
1
+ module Moto
2
+ class Test
3
+
4
+ attr_writer :context
5
+ attr_accessor :result
6
+ attr_reader :name
7
+
8
+ class << self
9
+ attr_accessor :_path
10
+ end
11
+
12
+ def self.inherited(k)
13
+ k._path = caller.first.match( /(.+):\d+:in/ )[1]
14
+ end
15
+
16
+ def path
17
+ self.class._path
18
+ end
19
+
20
+ def initialize
21
+ # @context = context
22
+ @result = Moto::Result::PENDING
23
+ end
24
+
25
+ def init(env, params)
26
+ @env = env
27
+ @params = params
28
+ set_name
29
+ end
30
+
31
+ def logger
32
+ @context.logger
33
+ end
34
+
35
+ def set_name
36
+ return @name = "#{self.class.to_s}/#{@env}" if @params.empty?
37
+ return @name = "#{self.class.to_s}/#{@env}/#{@params[:__name]}" if @params.key?(:__name)
38
+ @name = self.class.to_s
39
+ end
40
+
41
+ def dir
42
+ # puts self.class.path
43
+ File.dirname(self.path)
44
+ end
45
+
46
+ def filename
47
+ File.basename(path, ".*")
48
+ end
49
+
50
+ def run
51
+ # abstract
52
+ end
53
+
54
+ def before
55
+ # abstract
56
+ end
57
+
58
+ def after
59
+ # abstract
60
+ end
61
+
62
+ def assert(*args)
63
+ @context.runner.assert(self,*args)
64
+ end
65
+
66
+ def client(name)
67
+ @context.client(name)
68
+ end
69
+
70
+ end
71
+ end
@@ -0,0 +1,54 @@
1
+ module Moto
2
+ class ThreadContext
3
+
4
+ # all resources specific for single thread will be initialized here. E.g. browser session
5
+ attr_reader :runner
6
+ attr_reader :logger
7
+
8
+ def initialize(runner, tests)
9
+ @runner = runner
10
+ @tests = tests
11
+ @tests.each do |t|
12
+ t.context = self
13
+ end
14
+ end
15
+
16
+ def client(name)
17
+ # TODO: implement registry caching per name+env
18
+ name = 'MotoApp::Clients::' + name
19
+ a = name.underscore.split('/')
20
+ test_path = (a[1..20]+[a[-1]]).join('/')
21
+ require "#{APP_DIR}/#{test_path}"
22
+ client_const = name.safe_constantize
23
+ client_const.new
24
+ end
25
+
26
+ def run
27
+ @tests.each do |test|
28
+ # TODO: handle running same test in different environments / parameters - set name and logger
29
+ @runner.environments.each do |env|
30
+ params_path = "#{test.dir}/#{test.filename}.yml"
31
+ params_all = [{}]
32
+ params_all = YAML.load_file(params_path).map{|h| Hash[ h.map{|k,v| [ k.to_sym, v ] } ] } if File.exists?(params_path)
33
+ params_all.each do |params|
34
+ test.init(env, params)
35
+ # TODO: log path might be specified (to some extent) by the configuration
36
+ log_path = "#{test.dir}/#{test.name.gsub(/\s+/, '_').gsub('::', '_').gsub('/', '_')}.log"
37
+ @logger = Logger.new(File.open(log_path, File::WRONLY | File::TRUNC | File::CREAT))
38
+ # TODO: make logger level configurable
39
+ # @logger.level = Logger::INFO
40
+ @current_test = test
41
+ @runner.listeners.each { |l| l.start_test(test) }
42
+ test.before
43
+ # TODO: handle exception thrown during test run
44
+ test.run
45
+ test.after
46
+ @runner.listeners.each { |l| l.end_test(test) }
47
+ @logger.close
48
+ end
49
+ end
50
+ end
51
+ end
52
+
53
+ end
54
+ end
metadata ADDED
@@ -0,0 +1,54 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: moto
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Bartek Wilczek
8
+ - Maciej Przybylski
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2015-08-07 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: With a fancy description
15
+ email: bw@vouk.info
16
+ executables:
17
+ - moto
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - lib/empty_listener.rb
22
+ - lib/moto.rb
23
+ - lib/result.rb
24
+ - lib/runner.rb
25
+ - lib/test.rb
26
+ - lib/thread_context.rb
27
+ - lib/listeners/base.rb
28
+ - lib/listeners/console.rb
29
+ - bin/moto
30
+ homepage: http://vouk.info
31
+ licenses:
32
+ - MIT
33
+ metadata: {}
34
+ post_install_message:
35
+ rdoc_options: []
36
+ require_paths:
37
+ - lib
38
+ required_ruby_version: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - '>='
41
+ - !ruby/object:Gem::Version
42
+ version: '0'
43
+ required_rubygems_version: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ requirements: []
49
+ rubyforge_project:
50
+ rubygems_version: 2.0.14
51
+ signing_key:
52
+ specification_version: 4
53
+ summary: Moto - yet another testing framework
54
+ test_files: []