moto 0.0.14 → 0.0.15

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