moto 0.0.17 → 0.0.18

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: 67513bc98ab3246d5619d69d560a15956f4d01f7
4
- data.tar.gz: e062119f15ac74b5012c701525a0e2ff6c1463ab
3
+ metadata.gz: 3799edbb3011aab7abc3f801548862865d5dc196
4
+ data.tar.gz: 49183582720dd86f5f1fd4335a5e5ca3d9228731
5
5
  SHA512:
6
- metadata.gz: 93f8ce00760e6ea9e2c37d7f873d5a1e2bc1fa6a4f9f316e365ba0584a98eeff49445822683fb2e9da608f22424e14a5818b732e075cefcea8a1ff0e6908b026
7
- data.tar.gz: dad258914f1fd10fa21f30614621c9dc9ab2f552a87d420cf848ab33880765dbc52aac23412e674e20018d92baf3b1c6728853a7281bbaebf9acc6514c8aa4f7
6
+ metadata.gz: 49c6e8a0e15ee3275fced887be1e25296be84dedf652e54f372040b1d5b8fe55593efe32a0b659a3a707d4b3289491b0bff10a77c741decdc4b003491164335d
7
+ data.tar.gz: 32d7e271f59cbdbc46f8712b5ef2bc0c141f38057c1a633fc8f85c7f679f5799065390d9965810939d0a249fdec6894314bf73811004d9f55d317a77ce6e667c
data/lib/cli.rb CHANGED
@@ -18,6 +18,7 @@ require_relative './test_logging'
18
18
  require_relative './runner_logging'
19
19
  require_relative './runner'
20
20
  require_relative './thread_context'
21
+ require_relative './thread_pool'
21
22
  require_relative './result'
22
23
  require_relative './assert'
23
24
  require_relative './test'
@@ -51,29 +52,21 @@ module Moto
51
52
  end
52
53
 
53
54
  # TODO Optimization for files without #MOTO_TAGS
54
- unless argv[ :tags ].nil?
55
+ unless argv[:tags].nil?
55
56
  tests_total = Dir.glob("#{MotoApp::DIR}/tests/**/*.rb")
56
- argv[ :tags ].each do |tag_name|
57
- tests_total.each do |test_dir|
58
- test_body = File.read(test_dir)
59
- test_body.each_line do |line|
60
- line = line.delete(' ')
61
- if line.include?( '#MOTO_TAGS')
62
- if line.include?(tag_name + ',')
63
- test_paths_absolute.include?(test_dir) || test_paths_absolute << test_dir
64
- break
65
- else
66
- break
67
- end
68
- end
69
- end
57
+ tests_total.each do |test_path|
58
+ test_body = File.read(test_path)
59
+ matches = test_body.match(/^#(\s*)MOTO_TAGS:([^\n\r]+)$/m)
60
+ if matches
61
+ test_tags = matches.to_a[2].gsub(/\s*/, '').split(',')
62
+ test_paths_absolute << test_path unless (argv[:tags]&test_tags).empty?
70
63
  end
71
64
  end
72
65
  end
73
66
 
74
67
  #TODO Display criteria used
75
68
  if test_paths_absolute.empty?
76
- puts 'No tests found for given arguments'
69
+ puts 'No tests found for given arguments.'
77
70
  exit 1
78
71
  end
79
72
 
@@ -0,0 +1,7 @@
1
+ module Moto
2
+ class Initializer
3
+ def initialize(runner)
4
+ @runner = runner
5
+ end
6
+ end
7
+ end
data/lib/result.rb CHANGED
@@ -35,7 +35,7 @@ module Moto
35
35
  @summary[:duration] = @summary[:finished_at] - @summary[:started_at]
36
36
  @summary[:result] = PASSED
37
37
  @summary[:result] = FAILURE unless @results.values.select{ |v| v[:failures].count > 0 }.empty?
38
- @summary[:result] = ERROR unless @results.values.select{ |v| !v[:error].nil? }.empty?
38
+ @summary[:result] = ERROR unless @results.values.select{ |v| v[:result] == ERROR }.empty?
39
39
  @summary[:cnt_all] = @results.count
40
40
  @summary[:tests_passed] = @results.select{ |k,v| v[:result] == PASSED }
41
41
  @summary[:tests_failure] = @results.select{ |k,v| v[:result] == FAILURE }
data/lib/runner.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  module Moto
2
2
  class Runner
3
-
3
+
4
4
  attr_reader :result
5
5
  attr_reader :listeners
6
6
  attr_reader :logger
@@ -8,24 +8,24 @@ module Moto
8
8
  attr_reader :assert
9
9
  attr_reader :config
10
10
  attr_reader :name
11
-
11
+
12
12
  def initialize(tests, listeners, environments, config, name)
13
13
  @tests = tests
14
14
  @config = config
15
- @threads = []
15
+ @thread_pool = ThreadPool.new(my_config[:thread_count] || 1)
16
16
  @name = name
17
-
17
+
18
18
  # TODO: initialize logger from config (yml or just ruby code)
19
19
  # @logger = Logger.new(STDOUT)
20
20
  @logger = Logger.new(File.open("#{MotoApp::DIR}/moto.log", File::WRONLY | File::APPEND | File::CREAT))
21
21
  # @logger.level = Logger::WARN
22
-
22
+
23
23
  @result = Result.new(self)
24
-
24
+
25
25
  # TODO: validate envs, maybe no-env should be supported as well?
26
26
  environments << :__default if environments.empty?
27
27
  @environments = environments
28
-
28
+
29
29
  @listeners = []
30
30
  if listeners.empty?
31
31
  my_config[:default_listeners].each do |l|
@@ -38,7 +38,7 @@ module Moto
38
38
  end
39
39
  @listeners.unshift(@result)
40
40
  end
41
-
41
+
42
42
  def my_config
43
43
  caller_path = caller.first.to_s.split(/:\d/)[0]
44
44
  keys = []
@@ -55,19 +55,23 @@ module Moto
55
55
  eval "@config#{keys.map{|k| "[:#{k}]" }.join('')}"
56
56
  end
57
57
 
58
- # TODO: assigning tests to threads dynamically
59
58
  def run
59
+ if File.exists?( "#{MotoApp::DIR}/lib/initializer.rb" )
60
+ require("#{Moto::DIR}/lib/initializer.rb")
61
+ require("#{MotoApp::DIR}/lib/initializer.rb")
62
+ initializer = MotoApp::Initializer.new(self)
63
+ initializer.init
64
+ end
60
65
  @listeners.each { |l| l.start_run }
61
- test_slices = @tests.each_slice((@tests.size.to_f/my_config[:thread_count]).ceil).to_a
62
- test_slices.each do |slice|
63
- @threads << Thread.new do
64
- tc = ThreadContext.new(self, slice)
66
+ @tests.each do |test|
67
+ @thread_pool.schedule do
68
+ tc = ThreadContext.new(self, test)
65
69
  tc.run
66
70
  end
67
71
  end
68
- @threads.each{ |t| t.join }
72
+ @thread_pool.shutdown
69
73
  @listeners.each { |l| l.end_run }
70
74
  end
71
-
75
+
72
76
  end
73
77
  end
@@ -23,6 +23,7 @@ module Moto
23
23
  end
24
24
 
25
25
  def create_module_tree(root_module, next_modules)
26
+ return root_module if next_modules.empty?
26
27
  next_module_name = next_modules.shift
27
28
  if root_module.const_defined?(next_module_name.to_sym)
28
29
  m = root_module.const_get(next_module_name.to_sym)
@@ -30,7 +31,6 @@ module Moto
30
31
  m = Module.new
31
32
  root_module.const_set(next_module_name.to_sym, m)
32
33
  end
33
- return m if next_modules.empty?
34
34
  create_module_tree(m, next_modules)
35
35
  end
36
36
 
@@ -2,32 +2,30 @@ require 'erb'
2
2
 
3
3
  module Moto
4
4
  class ThreadContext
5
-
5
+
6
6
  # all resources specific for single thread will be initialized here. E.g. browser session
7
7
  attr_reader :runner
8
8
  attr_reader :logger
9
9
  # attr_reader :log_path
10
10
  attr_reader :current_test
11
-
12
- def initialize(runner, tests)
11
+
12
+ def initialize(runner, test)
13
13
  @runner = runner
14
- @tests = tests
14
+ @test = test
15
15
  @clients = {}
16
- @tests.each do |t|
17
- t.context = self
18
- end
16
+ @test.context = self
19
17
  @config = {}
20
18
  Dir.glob("config/*.yml").each do |f|
21
19
  @config.deep_merge! YAML.load_file(f)
22
20
  end
23
21
  end
24
-
22
+
25
23
  def client(name)
26
24
  return @clients[name] if @clients.key? name
27
-
25
+
28
26
  name_app = 'MotoApp::Clients::' + name
29
27
  name_moto = 'Moto::Clients::' + name
30
-
28
+
31
29
  c = try_client(name_app, "#{MotoApp::DIR}/lib")
32
30
  unless c.nil?
33
31
  @clients[name] = c
@@ -41,11 +39,11 @@ module Moto
41
39
  end
42
40
  raise "Could not find client class for name #{name}"
43
41
  end
44
-
42
+
45
43
  def try_client(name, dir)
46
- begin
44
+ begin
47
45
  a = name.underscore.split('/')
48
- client_path = a[1..20].join('/')
46
+ client_path = a[1..-1].join('/')
49
47
  require "#{dir}/#{client_path}"
50
48
  client_const = name.constantize
51
49
  instance = client_const.new(self)
@@ -53,13 +51,13 @@ module Moto
53
51
  instance.start_run
54
52
  instance.start_test(@current_test)
55
53
  return instance
56
- rescue Exception => e
54
+ rescue Exception => e
57
55
  # puts e
58
- # puts e.backtrace
56
+ # puts e.backtrace
59
57
  return nil
60
58
  end
61
59
  end
62
-
60
+
63
61
  def const(key)
64
62
  key = key.to_s
65
63
  key = "#{@current_test.env.to_s}.#{key}" if @current_test.env != :__default
@@ -76,57 +74,56 @@ module Moto
76
74
  end
77
75
  v
78
76
  end
79
-
77
+
80
78
  def run
81
- @tests.each do |test|
82
- # remove log files from previous execution
83
- Dir.glob("#{test.dir}/*.log").each {|f| File.delete f }
84
- max_attempts = @runner.my_config[:max_attempts] || 1
85
- @runner.environments.each do |env|
86
- params_path = "#{test.dir}/#{test.filename}.yml"
87
- params_all = [{}]
88
- params_all = YAML.load(ERB.new(File.read(params_path)).result) if File.exists?(params_path)
89
- #params_all = YAML.load_file(params_path) if File.exists?(params_path)
90
- # or convert keys to symbols?
91
- # params_all = YAML.load_file(params_path).map{|h| Hash[ h.map{|k,v| [ k.to_sym, v ] } ] } if File.exists?(params_path)
92
- params_all.each_with_index do |params, params_index|
93
- # TODO: add filtering out params that are specific to certain envs
94
- (1..max_attempts).each do |attempt|
95
- test.init(env, params, params_index)
96
- # TODO: log path might be specified (to some extent) by the configuration
97
- test.log_path = "#{test.dir}/#{test.name.gsub(/\s+/, '_').gsub('::', '_').gsub('/', '_')}.log"
98
- @logger = Logger.new(File.open(test.log_path, File::WRONLY | File::TRUNC | File::CREAT))
99
- # TODO: make logger level configurable
100
- @logger.level = @runner.my_config[:log_level]
101
- @current_test = test
102
- @runner.listeners.each { |l| l.start_test(test) }
103
- @clients.each_value { |c| c.start_test(test) }
104
- test.before
105
- @logger.info "Start: #{test.name} attempt #{attempt}/#{max_attempts}"
106
- begin
107
- test.run
108
- rescue Exceptions::TestForcedPassed, Exceptions::TestForcedFailure, Exceptions::TestSkipped => e
109
- logger.info(e.message)
110
- @runner.result.add_error(test, e)
111
- rescue Exception => e
112
- @logger.error("#{e.class.name}: #{e.message}")
113
- @logger.error(e.backtrace.join("\n"))
114
- @runner.result.add_error(test, e)
115
- end
116
- test.after
117
- @clients.each_value { |c| c.end_test(test) }
118
- # HAX: running end_test on results now, on other listeners after logger is closed
119
- @runner.listeners.first.end_test(test)
120
- @logger.info("Result: #{test.result}")
121
- @logger.close
122
- @runner.listeners[1..-1].each { |l| l.end_test(test) }
123
- break unless [Result::FAILURE, Result::ERROR].include? test.result
124
- end # RETRY
79
+ # remove log files from previous execution
80
+ Dir.glob("#{@test.dir}/*.log").each {|f| File.delete f }
81
+ max_attempts = @runner.my_config[:max_attempts] || 1
82
+ @runner.environments.each do |env|
83
+ params_path = "#{@test.dir}/#{@test.filename}.yml"
84
+ params_all = [{}]
85
+ params_all = YAML.load(ERB.new(File.read(params_path)).result) if File.exists?(params_path)
86
+ #params_all = YAML.load_file(params_path) if File.exists?(params_path)
87
+ params_all.each_with_index do |params, params_index|
88
+ # Filtering out param sets that are specific to certain envs
89
+ unless params['__env'].nil?
90
+ allowed_envs = params['__env'].is_a?(String) ? [params['__env']] : params['__env']
91
+ next unless allowed_envs.include? env
125
92
  end
93
+ (1..max_attempts).each do |attempt|
94
+ @test.init(env, params, params_index)
95
+ # TODO: log path might be specified (to some extent) by the configuration
96
+ @test.log_path = "#{@test.dir}/#{@test.name.gsub(/\s+/, '_').gsub('::', '_').gsub('/', '_')}.log"
97
+ @logger = Logger.new(File.open(@test.log_path, File::WRONLY | File::TRUNC | File::CREAT))
98
+ @logger.level = @runner.my_config[:log_level] || Logger::DEBUG
99
+ @current_test = @test
100
+ @runner.listeners.each { |l| l.start_test(@test) }
101
+ @clients.each_value { |c| c.start_test(@test) }
102
+ @test.before
103
+ @logger.info "Start: #{@test.name} attempt #{attempt}/#{max_attempts}"
104
+ begin
105
+ @test.run
106
+ rescue Exceptions::TestForcedPassed, Exceptions::TestForcedFailure, Exceptions::TestSkipped => e
107
+ logger.info(e.message)
108
+ @runner.result.add_error(@test, e)
109
+ rescue Exception => e
110
+ @logger.error("#{e.class.name}: #{e.message}")
111
+ @logger.error(e.backtrace.join("\n"))
112
+ @runner.result.add_error(@test, e)
113
+ end
114
+ @test.after
115
+ @clients.each_value { |c| c.end_test(@test) }
116
+ # HAX: running end_test on results now, on other listeners after logger is closed
117
+ @runner.listeners.first.end_test(@test)
118
+ @logger.info("Result: #{@test.result}")
119
+ @logger.close
120
+ @runner.listeners[1..-1].each { |l| l.end_test(@test) }
121
+ break unless [Result::FAILURE, Result::ERROR].include? @test.result
122
+ end # RETRY
126
123
  end
127
124
  end
128
125
  @clients.each_value { |c| c.end_run }
129
126
  end
130
-
127
+
131
128
  end
132
129
  end
@@ -0,0 +1,32 @@
1
+ module Moto
2
+ class ThreadPool
3
+
4
+ def initialize(size=1)
5
+ @size = size
6
+ @jobs = Queue.new
7
+ @pool = Array.new(@size) do |i|
8
+ Thread.new do
9
+ Thread.current[:id] = i
10
+ catch(:exit) do
11
+ loop do
12
+ job, args = @jobs.pop
13
+ job.call(*args)
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+
20
+ def schedule(*args, &block)
21
+ @jobs << [block, args]
22
+ end
23
+
24
+ def shutdown
25
+ @size.times do
26
+ schedule { throw :exit }
27
+ end
28
+ @pool.each(&:join)
29
+ end
30
+
31
+ end
32
+ end
data/lib/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Moto
2
- VERSION = '0.0.17'
2
+ VERSION = '0.0.18'
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: moto
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.17
4
+ version: 0.0.18
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bartek Wilczek
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2015-12-31 00:00:00.000000000 Z
13
+ date: 2016-01-11 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activesupport
@@ -86,6 +86,7 @@ files:
86
86
  - lib/cli.rb
87
87
  - lib/empty_listener.rb
88
88
  - lib/forward_context_methods.rb
89
+ - lib/initializer.rb
89
90
  - lib/page.rb
90
91
  - lib/parser.rb
91
92
  - lib/result.rb
@@ -95,6 +96,7 @@ files:
95
96
  - lib/test_generator.rb
96
97
  - lib/test_logging.rb
97
98
  - lib/thread_context.rb
99
+ - lib/thread_pool.rb
98
100
  - lib/version.rb
99
101
  - lib/clients/base.rb
100
102
  - lib/clients/website.rb