moto 0.0.14 → 0.0.15
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/cli.rb +105 -105
- data/lib/clients/website.rb +49 -47
- data/lib/listeners/webui.rb +70 -70
- data/lib/runner.rb +72 -72
- data/lib/test.rb +101 -101
- data/lib/test_generator.rb +68 -68
- data/lib/thread_context.rb +131 -128
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5d372116a3d958f4b63271540b60d41d035f270e
|
4
|
+
data.tar.gz: c9aa807fd63cae0abe92f9103c1c44ea4f431235
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 274cc49288e9aaf523e23c64b9fd572d127c469f45213d234039e4fefc4cec598d97755e3208caea948cd2f24975b75dc74f857c18ae43f853b10422cd64eb1d
|
7
|
+
data.tar.gz: e101a87b1351073c09ac40cefc1fe76613a94783d25db13f2b4494c18756acce963d98f5639a429e2d684f83ce1139c0f81197958589e5b4b15bab75ad9c1a5a
|
data/lib/cli.rb
CHANGED
@@ -1,105 +1,105 @@
|
|
1
|
-
# TODO: fix this dumb verification of current working directory
|
2
|
-
unless File.exists? "#{Dir.pwd}/config/moto.rb"
|
3
|
-
puts 'Config file (config/moto.rb) not present.'
|
4
|
-
puts 'Does current working directory contain Moto application?'
|
5
|
-
exit 1
|
6
|
-
end
|
7
|
-
|
8
|
-
require 'logger'
|
9
|
-
require 'pp'
|
10
|
-
require 'yaml'
|
11
|
-
require 'active_support/inflector'
|
12
|
-
require 'active_support/core_ext/object/blank'
|
13
|
-
|
14
|
-
require 'bundler/setup'
|
15
|
-
Bundler.require
|
16
|
-
|
17
|
-
module MotoApp
|
18
|
-
DIR = Dir.pwd
|
19
|
-
end
|
20
|
-
|
21
|
-
module Moto
|
22
|
-
DIR = File.dirname(File.dirname(__FILE__))
|
23
|
-
end
|
24
|
-
|
25
|
-
require_relative './empty_listener'
|
26
|
-
require_relative './forward_context_methods'
|
27
|
-
require_relative './test_logging'
|
28
|
-
require_relative './runner_logging'
|
29
|
-
require_relative './runner'
|
30
|
-
require_relative './thread_context'
|
31
|
-
require_relative './result'
|
32
|
-
require_relative './assert'
|
33
|
-
require_relative './test'
|
34
|
-
require_relative './page'
|
35
|
-
require_relative './clients/base'
|
36
|
-
require_relative './listeners/base'
|
37
|
-
require_relative './listeners/console'
|
38
|
-
require_relative './listeners/console_dots'
|
39
|
-
require_relative './listeners/junit_xml'
|
40
|
-
require_relative './listeners/webui'
|
41
|
-
require_relative './test_generator'
|
42
|
-
require_relative './exceptions/moto'
|
43
|
-
require_relative './exceptions/test_skipped'
|
44
|
-
require_relative './exceptions/test_forced_failure'
|
45
|
-
require_relative './exceptions/test_forced_passed'
|
46
|
-
|
47
|
-
module Moto
|
48
|
-
|
49
|
-
class Cli
|
50
|
-
def self.run(argv)
|
51
|
-
test_paths_absolute = []
|
52
|
-
test_classes = []
|
53
|
-
|
54
|
-
unless argv[ :tests ].nil?
|
55
|
-
argv[ :tests ].each do |dir_name|
|
56
|
-
test_paths = Dir.glob("#{MotoApp::DIR}/tests/#{dir_name}/**/*.rb")
|
57
|
-
test_paths -= test_paths_absolute
|
58
|
-
test_paths_absolute += test_paths
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
# TODO Optimization for files without #MOTO_TAGS
|
63
|
-
unless argv[ :tags ].nil?
|
64
|
-
tests_total = Dir.glob("#{MotoApp::DIR}/tests/**/*.rb")
|
65
|
-
argv[ :tags ].each do |tag_name|
|
66
|
-
tests_total.each do |test_dir|
|
67
|
-
test_body = File.read(test_dir)
|
68
|
-
test_body.each_line do |line|
|
69
|
-
line = line.delete(' ')
|
70
|
-
if line.include?( '#MOTO_TAGS')
|
71
|
-
if line.include?(tag_name + ',')
|
72
|
-
test_paths_absolute.include?(test_dir) || test_paths_absolute << test_dir
|
73
|
-
break
|
74
|
-
else
|
75
|
-
break
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
79
|
-
end
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
#TODO Display criteria used
|
84
|
-
if test_paths_absolute.empty?
|
85
|
-
puts 'No tests found for given arguments'
|
86
|
-
exit 1
|
87
|
-
end
|
88
|
-
|
89
|
-
tg = TestGenerator.new(MotoApp::DIR)
|
90
|
-
test_paths_absolute.each do |test_path|
|
91
|
-
test_classes << tg.generate(test_path)
|
92
|
-
end
|
93
|
-
|
94
|
-
listeners = []
|
95
|
-
argv[ :reporters ].each do |r|
|
96
|
-
listener = 'Moto::Listeners::' + r.camelize
|
97
|
-
listeners << listener.constantize
|
98
|
-
end
|
99
|
-
|
100
|
-
runner = Moto::Runner.new(test_classes, listeners, argv[:environments], argv[:config], argv[:name])
|
101
|
-
runner.run
|
102
|
-
end
|
103
|
-
|
104
|
-
end
|
105
|
-
end
|
1
|
+
# TODO: fix this dumb verification of current working directory
|
2
|
+
unless File.exists? "#{Dir.pwd}/config/moto.rb"
|
3
|
+
puts 'Config file (config/moto.rb) not present.'
|
4
|
+
puts 'Does current working directory contain Moto application?'
|
5
|
+
exit 1
|
6
|
+
end
|
7
|
+
|
8
|
+
require 'logger'
|
9
|
+
require 'pp'
|
10
|
+
require 'yaml'
|
11
|
+
require 'active_support/inflector'
|
12
|
+
require 'active_support/core_ext/object/blank'
|
13
|
+
|
14
|
+
require 'bundler/setup'
|
15
|
+
Bundler.require
|
16
|
+
|
17
|
+
module MotoApp
|
18
|
+
DIR = Dir.pwd
|
19
|
+
end
|
20
|
+
|
21
|
+
module Moto
|
22
|
+
DIR = File.dirname(File.dirname(__FILE__))
|
23
|
+
end
|
24
|
+
|
25
|
+
require_relative './empty_listener'
|
26
|
+
require_relative './forward_context_methods'
|
27
|
+
require_relative './test_logging'
|
28
|
+
require_relative './runner_logging'
|
29
|
+
require_relative './runner'
|
30
|
+
require_relative './thread_context'
|
31
|
+
require_relative './result'
|
32
|
+
require_relative './assert'
|
33
|
+
require_relative './test'
|
34
|
+
require_relative './page'
|
35
|
+
require_relative './clients/base'
|
36
|
+
require_relative './listeners/base'
|
37
|
+
require_relative './listeners/console'
|
38
|
+
require_relative './listeners/console_dots'
|
39
|
+
require_relative './listeners/junit_xml'
|
40
|
+
require_relative './listeners/webui'
|
41
|
+
require_relative './test_generator'
|
42
|
+
require_relative './exceptions/moto'
|
43
|
+
require_relative './exceptions/test_skipped'
|
44
|
+
require_relative './exceptions/test_forced_failure'
|
45
|
+
require_relative './exceptions/test_forced_passed'
|
46
|
+
|
47
|
+
module Moto
|
48
|
+
|
49
|
+
class Cli
|
50
|
+
def self.run(argv)
|
51
|
+
test_paths_absolute = []
|
52
|
+
test_classes = []
|
53
|
+
|
54
|
+
unless argv[ :tests ].nil?
|
55
|
+
argv[ :tests ].each do |dir_name|
|
56
|
+
test_paths = Dir.glob("#{MotoApp::DIR}/tests/#{dir_name}/**/*.rb")
|
57
|
+
test_paths -= test_paths_absolute
|
58
|
+
test_paths_absolute += test_paths
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# TODO Optimization for files without #MOTO_TAGS
|
63
|
+
unless argv[ :tags ].nil?
|
64
|
+
tests_total = Dir.glob("#{MotoApp::DIR}/tests/**/*.rb")
|
65
|
+
argv[ :tags ].each do |tag_name|
|
66
|
+
tests_total.each do |test_dir|
|
67
|
+
test_body = File.read(test_dir)
|
68
|
+
test_body.each_line do |line|
|
69
|
+
line = line.delete(' ')
|
70
|
+
if line.include?( '#MOTO_TAGS')
|
71
|
+
if line.include?(tag_name + ',')
|
72
|
+
test_paths_absolute.include?(test_dir) || test_paths_absolute << test_dir
|
73
|
+
break
|
74
|
+
else
|
75
|
+
break
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
#TODO Display criteria used
|
84
|
+
if test_paths_absolute.empty?
|
85
|
+
puts 'No tests found for given arguments'
|
86
|
+
exit 1
|
87
|
+
end
|
88
|
+
|
89
|
+
tg = TestGenerator.new(MotoApp::DIR)
|
90
|
+
test_paths_absolute.each do |test_path|
|
91
|
+
test_classes << tg.generate(test_path)
|
92
|
+
end
|
93
|
+
|
94
|
+
listeners = []
|
95
|
+
argv[ :reporters ].each do |r|
|
96
|
+
listener = 'Moto::Listeners::' + r.camelize
|
97
|
+
listeners << listener.constantize
|
98
|
+
end
|
99
|
+
|
100
|
+
runner = Moto::Runner.new(test_classes, listeners, argv[:environments], argv[:config], argv[:name])
|
101
|
+
runner.run
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
105
|
+
end
|
data/lib/clients/website.rb
CHANGED
@@ -1,47 +1,49 @@
|
|
1
|
-
require 'capybara'
|
2
|
-
|
3
|
-
module Moto
|
4
|
-
module Clients
|
5
|
-
|
6
|
-
class Website < Moto::Clients::Base
|
7
|
-
|
8
|
-
attr_reader :session
|
9
|
-
|
10
|
-
ignore_logging(:page)
|
11
|
-
ignore_logging(:context)
|
12
|
-
ignore_logging(:session)
|
13
|
-
|
14
|
-
def start_run
|
15
|
-
# TODO: make session driver configurable
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
end
|
1
|
+
require 'capybara'
|
2
|
+
|
3
|
+
module Moto
|
4
|
+
module Clients
|
5
|
+
|
6
|
+
class Website < Moto::Clients::Base
|
7
|
+
|
8
|
+
attr_reader :session
|
9
|
+
|
10
|
+
ignore_logging(:page)
|
11
|
+
ignore_logging(:context)
|
12
|
+
ignore_logging(:session)
|
13
|
+
|
14
|
+
def start_run
|
15
|
+
# TODO: make session driver configurable
|
16
|
+
context.runner.my_config[:capybara][:default_selector] &&
|
17
|
+
Capybara.default_selector = context.runner.my_config[:capybara][:default_selector]
|
18
|
+
@session = Capybara::Session.new(context.runner.my_config[:capybara][:default_driver])
|
19
|
+
@pages = {}
|
20
|
+
end
|
21
|
+
|
22
|
+
def end_run
|
23
|
+
@session.driver.browser.close # TODO: check that it really works
|
24
|
+
end
|
25
|
+
|
26
|
+
def start_test(test)
|
27
|
+
# @context.current_test.logger.info("Hi mom, I'm opening some pages!")
|
28
|
+
@session.reset_session!
|
29
|
+
end
|
30
|
+
|
31
|
+
def end_test(test)
|
32
|
+
@session.reset_session!
|
33
|
+
end
|
34
|
+
|
35
|
+
def page(p)
|
36
|
+
page_class_name = "#{self.class.name}::Pages::#{p}"
|
37
|
+
page_class_name.gsub!('Moto::', 'MotoApp::')
|
38
|
+
if @pages[page_class_name].nil?
|
39
|
+
a = page_class_name.underscore.split('/')
|
40
|
+
page_path = a[1..20].join('/')
|
41
|
+
require "#{MotoApp::DIR}/lib/#{page_path}"
|
42
|
+
@pages[page_class_name] = page_class_name.constantize.new(self)
|
43
|
+
end
|
44
|
+
@pages[page_class_name]
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
data/lib/listeners/webui.rb
CHANGED
@@ -1,71 +1,71 @@
|
|
1
|
-
require 'rest-client'
|
2
|
-
require 'sys/uname'
|
3
|
-
|
4
|
-
module Moto
|
5
|
-
module Listeners
|
6
|
-
class Webui < Base
|
7
|
-
|
8
|
-
def start_run
|
9
|
-
# POST http://sandbox.dev:3000/api/runs/create
|
10
|
-
@url = @runner.my_config[:url]
|
11
|
-
data = {
|
12
|
-
name: @runner.name,
|
13
|
-
result: Moto::Result::RUNNING,
|
14
|
-
cnt_all: nil,
|
15
|
-
cnt_passed: nil,
|
16
|
-
cnt_failure: nil,
|
17
|
-
cnt_error: nil,
|
18
|
-
cnt_skipped: nil,
|
19
|
-
user: Sys::Uname.sysname.downcase.include?('windows') ? ENV['USERNAME'] : ENV['LOGNAME'],
|
20
|
-
host: Sys::Uname.nodename,
|
21
|
-
pid: Process.pid
|
22
|
-
}
|
23
|
-
@run = JSON.parse( RestClient.post( "#{@url}/api/runs", data.to_json, :content_type => :json, :accept => :json ) )
|
24
|
-
@tests = {}
|
25
|
-
end
|
26
|
-
|
27
|
-
def end_run
|
28
|
-
# PUT http://sandbox.dev:3000/api/runs/1
|
29
|
-
data = {
|
30
|
-
result: @runner.result.summary[:result],
|
31
|
-
cnt_all: @runner.result.summary[:cnt_all],
|
32
|
-
cnt_passed: @runner.result.summary[:cnt_passed],
|
33
|
-
cnt_failure: @runner.result.summary[:cnt_failure],
|
34
|
-
cnt_error: @runner.result.summary[:cnt_error],
|
35
|
-
cnt_skipped: @runner.result.summary[:cnt_skipped],
|
36
|
-
duration: @runner.result.summary[:duration]
|
37
|
-
}
|
38
|
-
@run = JSON.parse( RestClient.put( "#{@url}/api/runs/#{@run['id']}", data.to_json, :content_type => :json, :accept => :json ) )
|
39
|
-
end
|
40
|
-
|
41
|
-
def start_test(test)
|
42
|
-
# POST http://sandbox.dev:3000/api/tests/create
|
43
|
-
data = {
|
44
|
-
name: test.name,
|
45
|
-
class_name: test.class.name,
|
46
|
-
log: nil,
|
47
|
-
run_id: @run['id'],
|
48
|
-
env: test.env,
|
49
|
-
parameters: test.params.to_s,
|
50
|
-
result: Moto::Result::RUNNING,
|
51
|
-
error: nil,
|
52
|
-
failures: nil,
|
53
|
-
}
|
54
|
-
@tests[test.name] = JSON.parse( RestClient.post( "#{@url}/api/tests", data.to_json, :content_type => :json, :accept => :json ) )
|
55
|
-
end
|
56
|
-
|
57
|
-
def end_test(test)
|
58
|
-
log = File.read(test.log_path)
|
59
|
-
data = {
|
60
|
-
log: log,
|
61
|
-
result: @runner.result[test.name][:result],
|
62
|
-
error: @runner.result[test.name][:error].nil? ? nil : @runner.result[test.name][:error].message,
|
63
|
-
failures: @runner.result[test.name][:failures].join("\n\t"),
|
64
|
-
duration: @runner.result[test.name][:duration]
|
65
|
-
}
|
66
|
-
@tests[test.name] = JSON.parse( RestClient.put( "#{@url}/api/tests/#{@tests[test.name]['id']}", data.to_json, :content_type => :json, :accept => :json ) )
|
67
|
-
end
|
68
|
-
|
69
|
-
end
|
70
|
-
end
|
1
|
+
require 'rest-client'
|
2
|
+
require 'sys/uname'
|
3
|
+
|
4
|
+
module Moto
|
5
|
+
module Listeners
|
6
|
+
class Webui < Base
|
7
|
+
|
8
|
+
def start_run
|
9
|
+
# POST http://sandbox.dev:3000/api/runs/create
|
10
|
+
@url = @runner.my_config[:url]
|
11
|
+
data = {
|
12
|
+
name: @runner.name,
|
13
|
+
result: Moto::Result::RUNNING,
|
14
|
+
cnt_all: nil,
|
15
|
+
cnt_passed: nil,
|
16
|
+
cnt_failure: nil,
|
17
|
+
cnt_error: nil,
|
18
|
+
cnt_skipped: nil,
|
19
|
+
user: Sys::Uname.sysname.downcase.include?('windows') ? ENV['USERNAME'] : ENV['LOGNAME'],
|
20
|
+
host: Sys::Uname.nodename,
|
21
|
+
pid: Process.pid
|
22
|
+
}
|
23
|
+
@run = JSON.parse( RestClient.post( "#{@url}/api/runs", data.to_json, :content_type => :json, :accept => :json ) )
|
24
|
+
@tests = {}
|
25
|
+
end
|
26
|
+
|
27
|
+
def end_run
|
28
|
+
# PUT http://sandbox.dev:3000/api/runs/1
|
29
|
+
data = {
|
30
|
+
result: @runner.result.summary[:result],
|
31
|
+
cnt_all: @runner.result.summary[:cnt_all],
|
32
|
+
cnt_passed: @runner.result.summary[:cnt_passed],
|
33
|
+
cnt_failure: @runner.result.summary[:cnt_failure],
|
34
|
+
cnt_error: @runner.result.summary[:cnt_error],
|
35
|
+
cnt_skipped: @runner.result.summary[:cnt_skipped],
|
36
|
+
duration: @runner.result.summary[:duration]
|
37
|
+
}
|
38
|
+
@run = JSON.parse( RestClient.put( "#{@url}/api/runs/#{@run['id']}", data.to_json, :content_type => :json, :accept => :json ) )
|
39
|
+
end
|
40
|
+
|
41
|
+
def start_test(test)
|
42
|
+
# POST http://sandbox.dev:3000/api/tests/create
|
43
|
+
data = {
|
44
|
+
name: test.name,
|
45
|
+
class_name: test.class.name,
|
46
|
+
log: nil,
|
47
|
+
run_id: @run['id'],
|
48
|
+
env: test.env,
|
49
|
+
parameters: test.params.to_s,
|
50
|
+
result: Moto::Result::RUNNING,
|
51
|
+
error: nil,
|
52
|
+
failures: nil,
|
53
|
+
}
|
54
|
+
@tests[test.name] = JSON.parse( RestClient.post( "#{@url}/api/tests", data.to_json, :content_type => :json, :accept => :json ) )
|
55
|
+
end
|
56
|
+
|
57
|
+
def end_test(test)
|
58
|
+
log = File.read(test.log_path)
|
59
|
+
data = {
|
60
|
+
log: log,
|
61
|
+
result: @runner.result[test.name][:result],
|
62
|
+
error: @runner.result[test.name][:error].nil? ? nil : @runner.result[test.name][:error].message,
|
63
|
+
failures: @runner.result[test.name][:failures].join("\n\t"),
|
64
|
+
duration: @runner.result[test.name][:duration]
|
65
|
+
}
|
66
|
+
@tests[test.name] = JSON.parse( RestClient.put( "#{@url}/api/tests/#{@tests[test.name]['id']}", data.to_json, :content_type => :json, :accept => :json ) )
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
end
|
71
71
|
end
|
data/lib/runner.rb
CHANGED
@@ -1,73 +1,73 @@
|
|
1
|
-
module Moto
|
2
|
-
class Runner
|
3
|
-
|
4
|
-
attr_reader :result
|
5
|
-
attr_reader :listeners
|
6
|
-
attr_reader :logger
|
7
|
-
attr_reader :environments
|
8
|
-
attr_reader :assert
|
9
|
-
attr_reader :config
|
10
|
-
attr_reader :name
|
11
|
-
|
12
|
-
def initialize(tests, listeners, environments, config, name)
|
13
|
-
@tests = tests
|
14
|
-
@config = config
|
15
|
-
@threads = []
|
16
|
-
@name = name
|
17
|
-
|
18
|
-
# TODO: initialize logger from config (yml or just ruby code)
|
19
|
-
# @logger = Logger.new(STDOUT)
|
20
|
-
@logger = Logger.new(File.open("#{MotoApp::DIR}/moto.log", File::WRONLY | File::APPEND | File::CREAT))
|
21
|
-
# @logger.level = Logger::WARN
|
22
|
-
|
23
|
-
@result = Result.new(self)
|
24
|
-
|
25
|
-
# TODO: validate envs, maybe no-env should be supported as well?
|
26
|
-
environments << :__default if environments.empty?
|
27
|
-
@environments = environments
|
28
|
-
|
29
|
-
@listeners = []
|
30
|
-
if listeners.empty?
|
31
|
-
my_config[:default_listeners].each do |l|
|
32
|
-
@listeners << l.new(self)
|
33
|
-
end
|
34
|
-
else
|
35
|
-
listeners.each do |l|
|
36
|
-
@listeners << l.new(self)
|
37
|
-
end
|
38
|
-
end
|
39
|
-
@listeners.unshift(@result)
|
40
|
-
end
|
41
|
-
|
42
|
-
def my_config
|
43
|
-
caller_path = caller.first.to_s.split(/:\d/)[0]
|
44
|
-
keys = []
|
45
|
-
if caller_path.include? MotoApp::DIR
|
46
|
-
caller_path.sub!( "#{MotoApp::DIR}/lib/", '' )
|
47
|
-
keys << 'moto_app'
|
48
|
-
elsif caller_path.include? Moto::DIR
|
49
|
-
caller_path.sub!( "#{Moto::DIR}/lib/", '' )
|
50
|
-
keys << 'moto'
|
51
|
-
end
|
52
|
-
caller_path.sub!('.rb', '')
|
53
|
-
keys << caller_path.split('/')
|
54
|
-
keys.flatten!
|
55
|
-
eval "@config#{keys.map{|k| "[:#{k}]" }.join('')}"
|
56
|
-
end
|
57
|
-
|
58
|
-
# TODO: assigning tests to threads dynamically
|
59
|
-
def run
|
60
|
-
@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)
|
65
|
-
tc.run
|
66
|
-
end
|
67
|
-
end
|
68
|
-
@threads.each{ |t| t.join }
|
69
|
-
@listeners.each { |l| l.end_run }
|
70
|
-
end
|
71
|
-
|
72
|
-
end
|
1
|
+
module Moto
|
2
|
+
class Runner
|
3
|
+
|
4
|
+
attr_reader :result
|
5
|
+
attr_reader :listeners
|
6
|
+
attr_reader :logger
|
7
|
+
attr_reader :environments
|
8
|
+
attr_reader :assert
|
9
|
+
attr_reader :config
|
10
|
+
attr_reader :name
|
11
|
+
|
12
|
+
def initialize(tests, listeners, environments, config, name)
|
13
|
+
@tests = tests
|
14
|
+
@config = config
|
15
|
+
@threads = []
|
16
|
+
@name = name
|
17
|
+
|
18
|
+
# TODO: initialize logger from config (yml or just ruby code)
|
19
|
+
# @logger = Logger.new(STDOUT)
|
20
|
+
@logger = Logger.new(File.open("#{MotoApp::DIR}/moto.log", File::WRONLY | File::APPEND | File::CREAT))
|
21
|
+
# @logger.level = Logger::WARN
|
22
|
+
|
23
|
+
@result = Result.new(self)
|
24
|
+
|
25
|
+
# TODO: validate envs, maybe no-env should be supported as well?
|
26
|
+
environments << :__default if environments.empty?
|
27
|
+
@environments = environments
|
28
|
+
|
29
|
+
@listeners = []
|
30
|
+
if listeners.empty?
|
31
|
+
my_config[:default_listeners].each do |l|
|
32
|
+
@listeners << l.new(self)
|
33
|
+
end
|
34
|
+
else
|
35
|
+
listeners.each do |l|
|
36
|
+
@listeners << l.new(self)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
@listeners.unshift(@result)
|
40
|
+
end
|
41
|
+
|
42
|
+
def my_config
|
43
|
+
caller_path = caller.first.to_s.split(/:\d/)[0]
|
44
|
+
keys = []
|
45
|
+
if caller_path.include? MotoApp::DIR
|
46
|
+
caller_path.sub!( "#{MotoApp::DIR}/lib/", '' )
|
47
|
+
keys << 'moto_app'
|
48
|
+
elsif caller_path.include? Moto::DIR
|
49
|
+
caller_path.sub!( "#{Moto::DIR}/lib/", '' )
|
50
|
+
keys << 'moto'
|
51
|
+
end
|
52
|
+
caller_path.sub!('.rb', '')
|
53
|
+
keys << caller_path.split('/')
|
54
|
+
keys.flatten!
|
55
|
+
eval "@config#{keys.map{|k| "[:#{k}]" }.join('')}"
|
56
|
+
end
|
57
|
+
|
58
|
+
# TODO: assigning tests to threads dynamically
|
59
|
+
def run
|
60
|
+
@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)
|
65
|
+
tc.run
|
66
|
+
end
|
67
|
+
end
|
68
|
+
@threads.each{ |t| t.join }
|
69
|
+
@listeners.each { |l| l.end_run }
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
73
|
end
|
data/lib/test.rb
CHANGED
@@ -1,102 +1,102 @@
|
|
1
|
-
module Moto
|
2
|
-
class Test
|
3
|
-
|
4
|
-
include Moto::Assert
|
5
|
-
include Moto::ForwardContextMethods
|
6
|
-
|
7
|
-
attr_writer :context
|
8
|
-
attr_accessor :result
|
9
|
-
attr_reader :name
|
10
|
-
attr_reader :env
|
11
|
-
attr_reader :params
|
12
|
-
attr_writer :static_path
|
13
|
-
attr_accessor :log_path
|
14
|
-
|
15
|
-
class << self
|
16
|
-
attr_accessor :_path
|
17
|
-
end
|
18
|
-
|
19
|
-
def self.inherited(k)
|
20
|
-
k._path = caller.first.match( /(.+):\d+:in/ )[1]
|
21
|
-
end
|
22
|
-
|
23
|
-
def path
|
24
|
-
self.class._path
|
25
|
-
end
|
26
|
-
|
27
|
-
def initialize
|
28
|
-
# @context = context
|
29
|
-
@result = Moto::Result::PENDING
|
30
|
-
end
|
31
|
-
|
32
|
-
def init(env, params, params_index)
|
33
|
-
@env = env
|
34
|
-
@params = params
|
35
|
-
set_name(params_index)
|
36
|
-
end
|
37
|
-
|
38
|
-
def set_name(params_index)
|
39
|
-
if @env == :__default
|
40
|
-
return @name = "#{self.class.to_s}" if @params.empty?
|
41
|
-
return @name = "#{self.class.to_s}/#{@params['__name']}" if @params.key?('__name')
|
42
|
-
return @name = "#{self.class.to_s}/params_#{params_index}" unless @params.key?('__name')
|
43
|
-
else
|
44
|
-
return @name = "#{self.class.to_s}/#{@env}" if @params.empty?
|
45
|
-
return @name = "#{self.class.to_s}/#{@env}/#{@params['__name']}" if @params.key?('__name')
|
46
|
-
return @name = "#{self.class.to_s}/#{@env}/params_#{params_index}" unless @params.key?('__name')
|
47
|
-
end
|
48
|
-
@name = self.class.to_s
|
49
|
-
end
|
50
|
-
|
51
|
-
def dir
|
52
|
-
# puts self.class.path
|
53
|
-
return File.dirname(@static_path) unless @static_path.nil?
|
54
|
-
File.dirname(self.path)
|
55
|
-
end
|
56
|
-
|
57
|
-
def filename
|
58
|
-
return File.basename(@static_path, ".*") unless @static_path.nil?
|
59
|
-
File.basename(path, ".*")
|
60
|
-
end
|
61
|
-
|
62
|
-
def run
|
63
|
-
# abstract
|
64
|
-
end
|
65
|
-
|
66
|
-
def before
|
67
|
-
# abstract
|
68
|
-
end
|
69
|
-
|
70
|
-
def after
|
71
|
-
# abstract
|
72
|
-
end
|
73
|
-
|
74
|
-
def skip(msg = nil)
|
75
|
-
if msg.nil?
|
76
|
-
msg = "Test skipped with no reason given."
|
77
|
-
else
|
78
|
-
msg = "Skip reason: #{msg}"
|
79
|
-
end
|
80
|
-
raise Exceptions::TestSkipped.new msg
|
81
|
-
end
|
82
|
-
|
83
|
-
def fail(msg = nil)
|
84
|
-
if msg.nil?
|
85
|
-
msg = "Test forcibly failed with no reason given."
|
86
|
-
else
|
87
|
-
msg = "Forced failure, reason: #{msg}"
|
88
|
-
end
|
89
|
-
raise Exceptions::TestForcedFailure.new msg
|
90
|
-
end
|
91
|
-
|
92
|
-
def pass(msg = nil)
|
93
|
-
if msg.nil?
|
94
|
-
msg = "Test forcibly passed with no reason given."
|
95
|
-
else
|
96
|
-
msg = "Forced passed, reason: #{msg}"
|
97
|
-
end
|
98
|
-
raise Exceptions::TestForcedPassed.new msg
|
99
|
-
end
|
100
|
-
|
101
|
-
end
|
1
|
+
module Moto
|
2
|
+
class Test
|
3
|
+
|
4
|
+
include Moto::Assert
|
5
|
+
include Moto::ForwardContextMethods
|
6
|
+
|
7
|
+
attr_writer :context
|
8
|
+
attr_accessor :result
|
9
|
+
attr_reader :name
|
10
|
+
attr_reader :env
|
11
|
+
attr_reader :params
|
12
|
+
attr_writer :static_path
|
13
|
+
attr_accessor :log_path
|
14
|
+
|
15
|
+
class << self
|
16
|
+
attr_accessor :_path
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.inherited(k)
|
20
|
+
k._path = caller.first.match( /(.+):\d+:in/ )[1]
|
21
|
+
end
|
22
|
+
|
23
|
+
def path
|
24
|
+
self.class._path
|
25
|
+
end
|
26
|
+
|
27
|
+
def initialize
|
28
|
+
# @context = context
|
29
|
+
@result = Moto::Result::PENDING
|
30
|
+
end
|
31
|
+
|
32
|
+
def init(env, params, params_index)
|
33
|
+
@env = env
|
34
|
+
@params = params
|
35
|
+
set_name(params_index)
|
36
|
+
end
|
37
|
+
|
38
|
+
def set_name(params_index)
|
39
|
+
if @env == :__default
|
40
|
+
return @name = "#{self.class.to_s}" if @params.empty?
|
41
|
+
return @name = "#{self.class.to_s}/#{@params['__name']}" if @params.key?('__name')
|
42
|
+
return @name = "#{self.class.to_s}/params_#{params_index}" unless @params.key?('__name')
|
43
|
+
else
|
44
|
+
return @name = "#{self.class.to_s}/#{@env}" if @params.empty?
|
45
|
+
return @name = "#{self.class.to_s}/#{@env}/#{@params['__name']}" if @params.key?('__name')
|
46
|
+
return @name = "#{self.class.to_s}/#{@env}/params_#{params_index}" unless @params.key?('__name')
|
47
|
+
end
|
48
|
+
@name = self.class.to_s
|
49
|
+
end
|
50
|
+
|
51
|
+
def dir
|
52
|
+
# puts self.class.path
|
53
|
+
return File.dirname(@static_path) unless @static_path.nil?
|
54
|
+
File.dirname(self.path)
|
55
|
+
end
|
56
|
+
|
57
|
+
def filename
|
58
|
+
return File.basename(@static_path, ".*") unless @static_path.nil?
|
59
|
+
File.basename(path, ".*")
|
60
|
+
end
|
61
|
+
|
62
|
+
def run
|
63
|
+
# abstract
|
64
|
+
end
|
65
|
+
|
66
|
+
def before
|
67
|
+
# abstract
|
68
|
+
end
|
69
|
+
|
70
|
+
def after
|
71
|
+
# abstract
|
72
|
+
end
|
73
|
+
|
74
|
+
def skip(msg = nil)
|
75
|
+
if msg.nil?
|
76
|
+
msg = "Test skipped with no reason given."
|
77
|
+
else
|
78
|
+
msg = "Skip reason: #{msg}"
|
79
|
+
end
|
80
|
+
raise Exceptions::TestSkipped.new msg
|
81
|
+
end
|
82
|
+
|
83
|
+
def fail(msg = nil)
|
84
|
+
if msg.nil?
|
85
|
+
msg = "Test forcibly failed with no reason given."
|
86
|
+
else
|
87
|
+
msg = "Forced failure, reason: #{msg}"
|
88
|
+
end
|
89
|
+
raise Exceptions::TestForcedFailure.new msg
|
90
|
+
end
|
91
|
+
|
92
|
+
def pass(msg = nil)
|
93
|
+
if msg.nil?
|
94
|
+
msg = "Test forcibly passed with no reason given."
|
95
|
+
else
|
96
|
+
msg = "Forced passed, reason: #{msg}"
|
97
|
+
end
|
98
|
+
raise Exceptions::TestForcedPassed.new msg
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
102
|
end
|
data/lib/test_generator.rb
CHANGED
@@ -1,69 +1,69 @@
|
|
1
|
-
module MotoApp
|
2
|
-
module Tests
|
3
|
-
end
|
4
|
-
end
|
5
|
-
|
6
|
-
module Moto
|
7
|
-
class TestGenerator
|
8
|
-
|
9
|
-
def initialize(app_dir)
|
10
|
-
@app_dir = app_dir
|
11
|
-
end
|
12
|
-
|
13
|
-
# assuming that target file includes full valid ruby class
|
14
|
-
def create(class_name)
|
15
|
-
class_name = 'MotoApp::Tests::'+class_name
|
16
|
-
a = class_name.underscore.split('/')
|
17
|
-
test_path = (a[1..20]+[a[-1]]).join('/')
|
18
|
-
|
19
|
-
# TODO: check if this path and constant exists
|
20
|
-
require "#{MotoApp::DIR}/#{test_path}"
|
21
|
-
test_const = class_name.safe_constantize
|
22
|
-
test_const.new
|
23
|
-
end
|
24
|
-
|
25
|
-
def create_module_tree(root_module, next_modules)
|
26
|
-
next_module_name = next_modules.shift
|
27
|
-
if root_module.const_defined?(next_module_name.to_sym)
|
28
|
-
m = root_module.const_get(next_module_name.to_sym)
|
29
|
-
else
|
30
|
-
m = Module.new
|
31
|
-
root_module.const_set(next_module_name.to_sym, m)
|
32
|
-
end
|
33
|
-
return m if next_modules.empty?
|
34
|
-
create_module_tree(m, next_modules)
|
35
|
-
end
|
36
|
-
|
37
|
-
# assuming that target file includes only content of method 'run' and some magic comments
|
38
|
-
def generate(test_path_absolute)
|
39
|
-
method_body = File.read(test_path_absolute) + "\n"
|
40
|
-
|
41
|
-
base = Moto::Test
|
42
|
-
base_class_string = method_body.match( /^#\s*BASE_CLASS:\s(\S+)/ )
|
43
|
-
unless base_class_string.nil?
|
44
|
-
base_class_string = base_class_string[1].strip
|
45
|
-
|
46
|
-
a = base_class_string.underscore.split('/')
|
47
|
-
base_test_path = a[1..-1].join('/')
|
48
|
-
|
49
|
-
require "#{MotoApp::DIR}/lib/#{base_test_path}"
|
50
|
-
base = base_class_string.constantize
|
51
|
-
end
|
52
|
-
|
53
|
-
# MotoApp::Tests::Login::Short
|
54
|
-
consts = test_path_absolute.camelize.split('Tests::')[1].split('::')
|
55
|
-
consts.pop
|
56
|
-
class_name = consts.pop
|
57
|
-
|
58
|
-
m = create_module_tree(MotoApp::Tests, consts)
|
59
|
-
cls = Class.new(base)
|
60
|
-
m.const_set(class_name.to_sym, cls)
|
61
|
-
|
62
|
-
test_object = cls.new
|
63
|
-
test_object.instance_eval( "def run\n #{method_body} \n end" )
|
64
|
-
test_object.static_path = test_path_absolute
|
65
|
-
test_object
|
66
|
-
end
|
67
|
-
|
68
|
-
end
|
1
|
+
module MotoApp
|
2
|
+
module Tests
|
3
|
+
end
|
4
|
+
end
|
5
|
+
|
6
|
+
module Moto
|
7
|
+
class TestGenerator
|
8
|
+
|
9
|
+
def initialize(app_dir)
|
10
|
+
@app_dir = app_dir
|
11
|
+
end
|
12
|
+
|
13
|
+
# assuming that target file includes full valid ruby class
|
14
|
+
def create(class_name)
|
15
|
+
class_name = 'MotoApp::Tests::'+class_name
|
16
|
+
a = class_name.underscore.split('/')
|
17
|
+
test_path = (a[1..20]+[a[-1]]).join('/')
|
18
|
+
|
19
|
+
# TODO: check if this path and constant exists
|
20
|
+
require "#{MotoApp::DIR}/#{test_path}"
|
21
|
+
test_const = class_name.safe_constantize
|
22
|
+
test_const.new
|
23
|
+
end
|
24
|
+
|
25
|
+
def create_module_tree(root_module, next_modules)
|
26
|
+
next_module_name = next_modules.shift
|
27
|
+
if root_module.const_defined?(next_module_name.to_sym)
|
28
|
+
m = root_module.const_get(next_module_name.to_sym)
|
29
|
+
else
|
30
|
+
m = Module.new
|
31
|
+
root_module.const_set(next_module_name.to_sym, m)
|
32
|
+
end
|
33
|
+
return m if next_modules.empty?
|
34
|
+
create_module_tree(m, next_modules)
|
35
|
+
end
|
36
|
+
|
37
|
+
# assuming that target file includes only content of method 'run' and some magic comments
|
38
|
+
def generate(test_path_absolute)
|
39
|
+
method_body = File.read(test_path_absolute) + "\n"
|
40
|
+
|
41
|
+
base = Moto::Test
|
42
|
+
base_class_string = method_body.match( /^#\s*BASE_CLASS:\s(\S+)/ )
|
43
|
+
unless base_class_string.nil?
|
44
|
+
base_class_string = base_class_string[1].strip
|
45
|
+
|
46
|
+
a = base_class_string.underscore.split('/')
|
47
|
+
base_test_path = a[1..-1].join('/')
|
48
|
+
|
49
|
+
require "#{MotoApp::DIR}/lib/#{base_test_path}"
|
50
|
+
base = base_class_string.constantize
|
51
|
+
end
|
52
|
+
|
53
|
+
# MotoApp::Tests::Login::Short
|
54
|
+
consts = test_path_absolute.camelize.split('Tests::')[1].split('::')
|
55
|
+
consts.pop
|
56
|
+
class_name = consts.pop
|
57
|
+
|
58
|
+
m = create_module_tree(MotoApp::Tests, consts)
|
59
|
+
cls = Class.new(base)
|
60
|
+
m.const_set(class_name.to_sym, cls)
|
61
|
+
|
62
|
+
test_object = cls.new
|
63
|
+
test_object.instance_eval( "def run\n #{method_body} \n end" )
|
64
|
+
test_object.static_path = test_path_absolute
|
65
|
+
test_object
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
69
|
end
|
data/lib/thread_context.rb
CHANGED
@@ -1,129 +1,132 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
attr_reader :
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
@
|
14
|
-
@tests
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
instance.
|
52
|
-
instance.
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
"@config['#{
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
raise
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
params_all.
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
# TODO:
|
97
|
-
|
98
|
-
@
|
99
|
-
|
100
|
-
@
|
101
|
-
test
|
102
|
-
@
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
rescue
|
109
|
-
|
110
|
-
@
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
@
|
118
|
-
|
119
|
-
@runner.listeners
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
1
|
+
require 'erb'
|
2
|
+
|
3
|
+
module Moto
|
4
|
+
class ThreadContext
|
5
|
+
|
6
|
+
# all resources specific for single thread will be initialized here. E.g. browser session
|
7
|
+
attr_reader :runner
|
8
|
+
attr_reader :logger
|
9
|
+
# attr_reader :log_path
|
10
|
+
attr_reader :current_test
|
11
|
+
|
12
|
+
def initialize(runner, tests)
|
13
|
+
@runner = runner
|
14
|
+
@tests = tests
|
15
|
+
@clients = {}
|
16
|
+
@tests.each do |t|
|
17
|
+
t.context = self
|
18
|
+
end
|
19
|
+
@config = {}
|
20
|
+
Dir.glob("config/*.yml").each do |f|
|
21
|
+
@config.deep_merge! YAML.load_file(f)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def client(name)
|
26
|
+
return @clients[name] if @clients.key? name
|
27
|
+
|
28
|
+
name_app = 'MotoApp::Clients::' + name
|
29
|
+
name_moto = 'Moto::Clients::' + name
|
30
|
+
|
31
|
+
c = try_client(name_app, "#{MotoApp::DIR}/lib")
|
32
|
+
unless c.nil?
|
33
|
+
@clients[name] = c
|
34
|
+
return c
|
35
|
+
end
|
36
|
+
|
37
|
+
c = try_client(name_moto, "#{Moto::DIR}/lib")
|
38
|
+
unless c.nil?
|
39
|
+
@clients[name] = c
|
40
|
+
return c
|
41
|
+
end
|
42
|
+
raise "Could not find client class for name #{name}"
|
43
|
+
end
|
44
|
+
|
45
|
+
def try_client(name, dir)
|
46
|
+
begin
|
47
|
+
a = name.underscore.split('/')
|
48
|
+
client_path = a[1..20].join('/')
|
49
|
+
require "#{dir}/#{client_path}"
|
50
|
+
client_const = name.constantize
|
51
|
+
instance = client_const.new(self)
|
52
|
+
instance.init
|
53
|
+
instance.start_run
|
54
|
+
instance.start_test(@current_test)
|
55
|
+
return instance
|
56
|
+
rescue Exception => e
|
57
|
+
# puts e
|
58
|
+
# puts e.backtrace
|
59
|
+
return nil
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def const(key)
|
64
|
+
key = key.to_s
|
65
|
+
key = "#{@current_test.env.to_s}.#{key}" if @current_test.env != :__default
|
66
|
+
code = if key.include? '.'
|
67
|
+
"@config#{key.split('.').map{|a| "['#{a}']" }.join('')}"
|
68
|
+
else
|
69
|
+
"@config['#{key}']"
|
70
|
+
end
|
71
|
+
begin
|
72
|
+
v = eval code
|
73
|
+
raise if v.nil?
|
74
|
+
rescue
|
75
|
+
raise "There is no const defined for key: #{key}. Environment: #{ (@current_test.env == :__default) ? '<none>' : @current_test.env }"
|
76
|
+
end
|
77
|
+
v
|
78
|
+
end
|
79
|
+
|
80
|
+
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
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
@clients.each_value { |c| c.end_run }
|
129
|
+
end
|
130
|
+
|
131
|
+
end
|
129
132
|
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.
|
4
|
+
version: 0.0.15
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bartek Wilczek
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2015-
|
12
|
+
date: 2015-12-08 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activesupport
|
@@ -125,7 +125,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
125
125
|
version: '0'
|
126
126
|
requirements: []
|
127
127
|
rubyforge_project:
|
128
|
-
rubygems_version: 2.0.
|
128
|
+
rubygems_version: 2.0.14.1
|
129
129
|
signing_key:
|
130
130
|
specification_version: 4
|
131
131
|
summary: Moto - yet another web testing framework
|