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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c94bb7f2fefa17c428807553a10595ef68cfcfc4
4
- data.tar.gz: 480a4a33b77799351417effaa2d8fbe9f41bb4e7
3
+ metadata.gz: 5d372116a3d958f4b63271540b60d41d035f270e
4
+ data.tar.gz: c9aa807fd63cae0abe92f9103c1c44ea4f431235
5
5
  SHA512:
6
- metadata.gz: f3aff69430e58ab6b5b4b175316e8dff36d1c84d0dc320fdc4fe9f0574a54245bd3a4121bc8aad8c017f6378acff6379de2d746f90fc6814b100d0e85d68b057
7
- data.tar.gz: 52d57ac54c25c563e40dc7fe316772055e3c9709ef571ccb1c624e9c219ff7e25aad7dc59468a912c1952c121cb6f28a4f7ddcbea87f55b4db3f41b46289c1a0
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
@@ -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
- @session = Capybara::Session.new(context.runner.my_config[:capybara][:default_driver])
17
- @pages = {}
18
- end
19
-
20
- def end_run
21
- @session.driver.browser.close # TODO: check that it really works
22
- end
23
-
24
- def start_test(test)
25
- # @context.current_test.logger.info("Hi mom, I'm opening some pages!")
26
- @session.reset_session!
27
- end
28
-
29
- def end_test(test)
30
- @session.reset_session!
31
- end
32
-
33
- def page(p)
34
- page_class_name = "#{self.class.name}Pages::#{p}"
35
- page_class_name.gsub!('Moto::', 'MotoApp::')
36
- if @pages[page_class_name].nil?
37
- a = page_class_name.underscore.split('/')
38
- page_path = a[1..20].join('/')
39
- require "#{MotoApp::DIR}/lib/#{page_path}"
40
- @pages[page_class_name] = page_class_name.constantize.new(self)
41
- end
42
- @pages[page_class_name]
43
- end
44
-
45
- end
46
- end
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
@@ -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
@@ -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
@@ -1,129 +1,132 @@
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
- # attr_reader :log_path
8
- attr_reader :current_test
9
-
10
- def initialize(runner, tests)
11
- @runner = runner
12
- @tests = tests
13
- @clients = {}
14
- @tests.each do |t|
15
- t.context = self
16
- end
17
- @config = {}
18
- Dir.glob("config/*.yml").each do |f|
19
- @config.deep_merge! YAML.load_file(f)
20
- end
21
- end
22
-
23
- def client(name)
24
- return @clients[name] if @clients.key? name
25
-
26
- name_app = 'MotoApp::Clients::' + name
27
- name_moto = 'Moto::Clients::' + name
28
-
29
- c = try_client(name_app, "#{MotoApp::DIR}/lib")
30
- unless c.nil?
31
- @clients[name] = c
32
- return c
33
- end
34
-
35
- c = try_client(name_moto, "#{Moto::DIR}/lib")
36
- unless c.nil?
37
- @clients[name] = c
38
- return c
39
- end
40
- raise "Could not find client class for name #{name}"
41
- end
42
-
43
- def try_client(name, dir)
44
- begin
45
- a = name.underscore.split('/')
46
- client_path = a[1..20].join('/')
47
- require "#{dir}/#{client_path}"
48
- client_const = name.constantize
49
- instance = client_const.new(self)
50
- instance.init
51
- instance.start_run
52
- instance.start_test(@current_test)
53
- return instance
54
- rescue Exception => e
55
- # puts e
56
- # puts e.backtrace
57
- return nil
58
- end
59
- end
60
-
61
- def const(key)
62
- key = key.to_s
63
- key = "#{@current_test.env.to_s}.#{key}" if @current_test.env != :__default
64
- code = if key.include? '.'
65
- "@config#{key.split('.').map{|a| "['#{a}']" }.join('')}"
66
- else
67
- "@config['#{key}']"
68
- end
69
- begin
70
- v = eval code
71
- raise if v.nil?
72
- rescue
73
- raise "There is no const defined for key: #{key}. Environment: #{ (@current_test.env == :__default) ? '<none>' : @current_test.env }"
74
- end
75
- v
76
- end
77
-
78
- def run
79
- @tests.each do |test|
80
- # remove log files from previous execution
81
- Dir.glob("#{test.dir}/*.log").each {|f| File.delete f }
82
- max_attempts = @runner.my_config[:max_attempts] || 1
83
- @runner.environments.each do |env|
84
- params_path = "#{test.dir}/#{test.filename}.yml"
85
- params_all = [{}]
86
- params_all = YAML.load_file(params_path) if File.exists?(params_path)
87
- # or convert keys to symbols?
88
- # params_all = YAML.load_file(params_path).map{|h| Hash[ h.map{|k,v| [ k.to_sym, v ] } ] } if File.exists?(params_path)
89
- params_all.each_with_index do |params, params_index|
90
- # TODO: add filtering out params that are specific to certain envs
91
- (1..max_attempts).each do |attempt|
92
- test.init(env, params, params_index)
93
- # TODO: log path might be specified (to some extent) by the configuration
94
- test.log_path = "#{test.dir}/#{test.name.gsub(/\s+/, '_').gsub('::', '_').gsub('/', '_')}.log"
95
- @logger = Logger.new(File.open(test.log_path, File::WRONLY | File::TRUNC | File::CREAT))
96
- # TODO: make logger level configurable
97
- @logger.level = @runner.my_config[:log_level]
98
- @current_test = test
99
- @runner.listeners.each { |l| l.start_test(test) }
100
- @clients.each_value { |c| c.start_test(test) }
101
- test.before
102
- @logger.info "Start: #{test.name} attempt #{attempt}/#{max_attempts}"
103
- begin
104
- test.run
105
- rescue Exceptions::TestForcedPassed, Exceptions::TestForcedFailure, Exceptions::TestSkipped => e
106
- logger.info(e.message)
107
- @runner.result.add_error(test, e)
108
- rescue Exception => e
109
- @logger.error("#{e.class.name}: #{e.message}")
110
- @logger.error(e.backtrace.join("\n"))
111
- @runner.result.add_error(test, e)
112
- end
113
- test.after
114
- @clients.each_value { |c| c.end_test(test) }
115
- # HAX: running end_test on results now, on other listeners after logger is closed
116
- @runner.listeners.first.end_test(test)
117
- @logger.info("Result: #{test.result}")
118
- @logger.close
119
- @runner.listeners[1..-1].each { |l| l.end_test(test) }
120
- break unless [Result::FAILURE, Result::ERROR].include? test.result
121
- end # RETRY
122
- end
123
- end
124
- end
125
- @clients.each_value { |c| c.end_run }
126
- end
127
-
128
- end
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.14
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-11-18 00:00:00.000000000 Z
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.15
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