moto 0.0.31 → 0.0.32
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/app_generator.rb +2 -2
- data/lib/cli.rb +8 -14
- data/lib/parser.rb +4 -3
- data/lib/reporting/listeners/base.rb +44 -0
- data/lib/reporting/listeners/console.rb +31 -0
- data/lib/reporting/listeners/console_dots.rb +60 -0
- data/lib/reporting/listeners/junit_xml.rb +52 -0
- data/lib/reporting/listeners/webui.rb +81 -0
- data/lib/reporting/run_status.rb +98 -0
- data/lib/reporting/test_reporter.rb +83 -0
- data/lib/runner.rb +10 -21
- data/lib/test/base.rb +168 -0
- data/lib/test/result.rb +28 -0
- data/lib/test/status.rb +106 -0
- data/lib/test_generator.rb +4 -7
- data/lib/thread_context.rb +52 -33
- data/lib/version.rb +1 -1
- metadata +14 -10
- data/lib/assert.rb +0 -32
- data/lib/listeners/base.rb +0 -26
- data/lib/listeners/console.rb +0 -29
- data/lib/listeners/console_dots.rb +0 -63
- data/lib/listeners/junit_xml.rb +0 -37
- data/lib/listeners/webui.rb +0 -71
- data/lib/result.rb +0 -84
- data/lib/test.rb +0 -107
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d23349f0a57bf09f12e54b6421cc34722300eae9
|
4
|
+
data.tar.gz: 4fdd6816603719eced2cef716639ea709531c44a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1dd1416efd912208d68ecc4ff1080b64d7354ee36fdf6292d99d5b776a89a171a92399c8eea88445c3851926f19df8ea0337f6d6748ff230f985baed45bffb2c
|
7
|
+
data.tar.gz: 502c169e152bf8ee805e1bbf81f19ff54bf87e52362cb8de8ba16ee14985124c12cd285b19f710e7f3702e340a39d12c834d8fe10d33d9c4ba4185c09ab686af
|
data/lib/app_generator.rb
CHANGED
@@ -19,10 +19,10 @@ module Moto
|
|
19
19
|
# Name of the class in the template
|
20
20
|
class_name = modules.last
|
21
21
|
|
22
|
-
# Evaluate fully
|
22
|
+
# Evaluate fully qualified name of the class to derive from or, if not specified
|
23
23
|
# use Moto's default one
|
24
24
|
if options[:base_class].nil?
|
25
|
-
base_class_qualified_name = 'Moto::Test'
|
25
|
+
base_class_qualified_name = 'Moto::Test::Base'
|
26
26
|
else
|
27
27
|
base_class_qualified_name = "#{options[:app_name]}::Lib::Test::#{options[:base_class].split('/').join('::').camelize}"
|
28
28
|
end
|
data/lib/cli.rb
CHANGED
@@ -19,17 +19,15 @@ require_relative './runner_logging'
|
|
19
19
|
require_relative './runner'
|
20
20
|
require_relative './thread_context'
|
21
21
|
require_relative './thread_pool'
|
22
|
-
require_relative './
|
23
|
-
require_relative './assert'
|
24
|
-
require_relative './test'
|
22
|
+
require_relative './test/base'
|
25
23
|
require_relative './page'
|
26
24
|
require_relative './version'
|
27
25
|
require_relative './clients/base'
|
28
|
-
require_relative './listeners/base'
|
29
|
-
require_relative './listeners/console'
|
30
|
-
require_relative './listeners/console_dots'
|
31
|
-
require_relative './listeners/junit_xml'
|
32
|
-
require_relative './listeners/webui'
|
26
|
+
require_relative './reporting/listeners/base'
|
27
|
+
require_relative './reporting/listeners/console'
|
28
|
+
require_relative './reporting/listeners/console_dots'
|
29
|
+
require_relative './reporting/listeners/junit_xml'
|
30
|
+
require_relative './reporting/listeners/webui'
|
33
31
|
require_relative './test_generator'
|
34
32
|
require_relative './exceptions/moto'
|
35
33
|
require_relative './exceptions/test_skipped'
|
@@ -83,13 +81,9 @@ module Moto
|
|
83
81
|
test_classes << tg.generate(test_path)
|
84
82
|
end
|
85
83
|
|
86
|
-
|
87
|
-
argv[ :reporters ].each do |r|
|
88
|
-
listener = 'Moto::Listeners::' + r.camelize
|
89
|
-
listeners << listener.constantize
|
90
|
-
end
|
84
|
+
@test_reporter = Moto::Reporting::TestReporter.new(argv[:listeners], argv[:config], argv[:name])
|
91
85
|
|
92
|
-
runner = Moto::Runner.new(test_classes,
|
86
|
+
runner = Moto::Runner.new(test_classes, argv[:environments], argv[:config], @test_reporter)
|
93
87
|
runner.run
|
94
88
|
end
|
95
89
|
|
data/lib/parser.rb
CHANGED
@@ -22,7 +22,8 @@ module Moto
|
|
22
22
|
end
|
23
23
|
|
24
24
|
rescue Exception => e
|
25
|
-
puts e.message
|
25
|
+
puts e.message + "\n\n"
|
26
|
+
puts e.backtrace.join("\n")
|
26
27
|
end
|
27
28
|
end
|
28
29
|
|
@@ -40,7 +41,7 @@ module Moto
|
|
40
41
|
|
41
42
|
# Default options
|
42
43
|
options = {}
|
43
|
-
options[:
|
44
|
+
options[:listeners] = []
|
44
45
|
# TODO Mandatory env var in app config
|
45
46
|
options[:config] = eval(File.read("#{MotoApp::DIR}/config/moto.rb"))
|
46
47
|
options[:environments] = []
|
@@ -53,7 +54,7 @@ module Moto
|
|
53
54
|
OptionParser.new do |opts|
|
54
55
|
opts.on('-t', '--tests Tests', Array) { |v| options[:tests ] = v }
|
55
56
|
opts.on('-g', '--tags Tags', Array) { |v| options[:tags ] = v }
|
56
|
-
opts.on('-
|
57
|
+
opts.on('-l', '--listeners Listeners', Array) { |v| options[:listeners] = v }
|
57
58
|
opts.on('-e', '--environments Environment', Array) { |v| options[:environments] = v }
|
58
59
|
opts.on('-c', '--const Const') { |v| options[:const] = v }
|
59
60
|
opts.on('-n', '--name Name') { |v| options[:name] = v }
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Moto
|
2
|
+
module Reporting
|
3
|
+
module Listeners
|
4
|
+
|
5
|
+
# Base class for listeners that report results of testing 'outside' of the application.
|
6
|
+
class Base
|
7
|
+
|
8
|
+
attr_reader :config
|
9
|
+
attr_reader :custom_run_name
|
10
|
+
|
11
|
+
# @param [Hash] config
|
12
|
+
# @param [String] custom_run_name Optional run name to be passed to listeners
|
13
|
+
def initialize(config, custom_run_name = '')
|
14
|
+
@config = config
|
15
|
+
@custom_run_name = custom_run_name
|
16
|
+
end
|
17
|
+
|
18
|
+
# Invoked when whole batch of tests starts
|
19
|
+
def start_run
|
20
|
+
# Abstract
|
21
|
+
end
|
22
|
+
|
23
|
+
# Abstract
|
24
|
+
# Invoked when whole batch of tests ends
|
25
|
+
def end_run(run_status)
|
26
|
+
# Abstract
|
27
|
+
end
|
28
|
+
|
29
|
+
# Abstract
|
30
|
+
# Invoked when a single test is started
|
31
|
+
def start_test(test_status)
|
32
|
+
# Abstract
|
33
|
+
end
|
34
|
+
|
35
|
+
# Abstract
|
36
|
+
# Invoked when a single test is finished
|
37
|
+
def end_test(test_status)
|
38
|
+
# Abstract
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Moto
|
2
|
+
module Reporting
|
3
|
+
module Listeners
|
4
|
+
class Console < Base
|
5
|
+
|
6
|
+
def start_run
|
7
|
+
puts 'START'
|
8
|
+
end
|
9
|
+
|
10
|
+
def end_run(run_status)
|
11
|
+
puts ''
|
12
|
+
puts "FINISHED: #{run_status.to_s}, duration: #{Time.at(run_status.duration).utc.strftime("%H:%M:%S")}"
|
13
|
+
puts "Tests executed: #{run_status.tests_all.length}"
|
14
|
+
puts " Passed: #{run_status.tests_passed.length}"
|
15
|
+
puts " Failure: #{run_status.tests_failed.length}"
|
16
|
+
puts " Error: #{run_status.tests_error.length}"
|
17
|
+
puts " Skipped: #{run_status.tests_skipped.length}"
|
18
|
+
end
|
19
|
+
|
20
|
+
def start_test(test_status)
|
21
|
+
print test_status.name
|
22
|
+
end
|
23
|
+
|
24
|
+
def end_test(test_status)
|
25
|
+
puts "\t#{test_status.to_s}"
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module Moto
|
2
|
+
module Reporting
|
3
|
+
module Listeners
|
4
|
+
class ConsoleDots < Base
|
5
|
+
|
6
|
+
def end_run(run_status)
|
7
|
+
puts ''
|
8
|
+
puts ''
|
9
|
+
puts "FINISHED: #{run_status.to_s}, duration: #{Time.at(run_status.duration).utc.strftime("%H:%M:%S")}"
|
10
|
+
puts "Tests executed: #{run_status.tests_all.length}"
|
11
|
+
puts " Passed: #{run_status.tests_passed.length}"
|
12
|
+
puts " Failure: #{run_status.tests_failed.length}"
|
13
|
+
puts " Error: #{run_status.tests_error.length}"
|
14
|
+
puts " Skipped: #{run_status.tests_skipped.length}"
|
15
|
+
|
16
|
+
if run_status.tests_failed.length > 0
|
17
|
+
puts ''
|
18
|
+
puts 'FAILURES: '
|
19
|
+
run_status.tests_failed.each do |test_status|
|
20
|
+
puts test_status.name
|
21
|
+
puts "\t" + test_status.results.last.failures.join("\n\t")
|
22
|
+
puts ''
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
if run_status.tests_error.length > 0
|
27
|
+
puts ''
|
28
|
+
puts 'ERRORS: '
|
29
|
+
run_status.tests_error.each do |test_status|
|
30
|
+
puts test_status.name
|
31
|
+
puts test_status.results.last.message
|
32
|
+
puts ''
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
if run_status.tests_skipped.length > 0
|
37
|
+
puts ''
|
38
|
+
puts 'SKIPPED: '
|
39
|
+
run_status.tests_skipped.each do |test_status|
|
40
|
+
puts test_status.name
|
41
|
+
puts test_status.results.last.message
|
42
|
+
puts ''
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
def end_test(test_status)
|
49
|
+
print case test_status.results.last.code
|
50
|
+
when Moto::Test::Result::PASSED then '.'
|
51
|
+
when Moto::Test::Result::FAILURE then 'F'
|
52
|
+
when Moto::Test::Result::ERROR then 'E'
|
53
|
+
when Moto::Test::Result::SKIPPED then 's'
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
|
3
|
+
module Moto
|
4
|
+
module Reporting
|
5
|
+
module Listeners
|
6
|
+
class JunitXml < Base
|
7
|
+
|
8
|
+
def end_run(run_status)
|
9
|
+
path = config[:output_file]
|
10
|
+
|
11
|
+
run_status_hash = {
|
12
|
+
errors: run_status.tests_error.length,
|
13
|
+
failures: run_status.tests_error.length,
|
14
|
+
name: custom_run_name,
|
15
|
+
tests: run_status.tests_all.length,
|
16
|
+
time: run_status.duration,
|
17
|
+
timestamp: Time.at(run_status.time_start)
|
18
|
+
}
|
19
|
+
|
20
|
+
builder = Nokogiri::XML::Builder.new { |xml|
|
21
|
+
xml.testsuite(run_status_hash) do
|
22
|
+
run_status.tests_all.each do |test_status|
|
23
|
+
|
24
|
+
test_status_hash = {
|
25
|
+
name: test_status.name,
|
26
|
+
time: test_status.duration,
|
27
|
+
classname: test_status.test_class_name,
|
28
|
+
moto_result: test_status.to_s
|
29
|
+
}
|
30
|
+
|
31
|
+
xml.testcase(test_status_hash) do
|
32
|
+
if test_status.results.last.code == Moto::Test::Result::ERROR
|
33
|
+
xml.error(message: test_status.results.last.message)
|
34
|
+
elsif test_status.results.last.code == Moto::Test::Result::FAILURE
|
35
|
+
|
36
|
+
test_status.results.last.failures.each do |failure_message|
|
37
|
+
xml.failure(message: failure_message)
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
}
|
45
|
+
|
46
|
+
File.open(path, 'w') {|f| f.write(builder.to_xml) }
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'rest-client'
|
2
|
+
require 'sys/uname'
|
3
|
+
|
4
|
+
module Moto
|
5
|
+
module Reporting
|
6
|
+
module Listeners
|
7
|
+
class Webui < Base
|
8
|
+
|
9
|
+
def start_run
|
10
|
+
# POST http://sandbox.dev:3000/api/runs/create
|
11
|
+
@url = config[:url]
|
12
|
+
data = {
|
13
|
+
name: custom_run_name,
|
14
|
+
result: :running,
|
15
|
+
cnt_all: nil,
|
16
|
+
cnt_passed: nil,
|
17
|
+
cnt_failure: nil,
|
18
|
+
cnt_error: nil,
|
19
|
+
cnt_skipped: nil,
|
20
|
+
user: Sys::Uname.sysname.downcase.include?('windows') ? ENV['USERNAME'] : ENV['LOGNAME'],
|
21
|
+
host: Sys::Uname.nodename,
|
22
|
+
pid: Process.pid
|
23
|
+
}
|
24
|
+
|
25
|
+
@run = JSON.parse( RestClient.post( "#{@url}/api/runs", data.to_json, :content_type => :json, :accept => :json ) )
|
26
|
+
@tests = {}
|
27
|
+
end
|
28
|
+
|
29
|
+
def end_run(run_status)
|
30
|
+
# PUT http://sandbox.dev:3000/api/runs/1
|
31
|
+
data = {
|
32
|
+
result: run_status.result,
|
33
|
+
cnt_all: run_status.tests_all.length,
|
34
|
+
cnt_passed: run_status.tests_passed.length,
|
35
|
+
cnt_failure: run_status.tests_failed.length,
|
36
|
+
cnt_error: run_status.tests_error.length,
|
37
|
+
cnt_skipped: run_status.tests_skipped.length,
|
38
|
+
duration: run_status.duration
|
39
|
+
}
|
40
|
+
|
41
|
+
@run = JSON.parse( RestClient.put( "#{@url}/api/runs/#{@run['id']}", data.to_json, :content_type => :json, :accept => :json ) )
|
42
|
+
end
|
43
|
+
|
44
|
+
def start_test(test_status)
|
45
|
+
# POST http://sandbox.dev:3000/api/tests/create
|
46
|
+
data = {
|
47
|
+
name: test_status.name,
|
48
|
+
class_name: test_status.test_class_name,
|
49
|
+
log: nil,
|
50
|
+
run_id: @run['id'],
|
51
|
+
env: test_status.env,
|
52
|
+
parameters: test_status.params.to_s,
|
53
|
+
result: :running,
|
54
|
+
error: nil,
|
55
|
+
failures: nil
|
56
|
+
}
|
57
|
+
|
58
|
+
@tests[test_status.name] = JSON.parse( RestClient.post( "#{@url}/api/tests", data.to_json, :content_type => :json, :accept => :json ) )
|
59
|
+
end
|
60
|
+
|
61
|
+
def end_test(test_status)
|
62
|
+
data = {
|
63
|
+
log: File.read(test_status.log_path),
|
64
|
+
result: test_status.results.last.code,
|
65
|
+
error: test_status.results.last.code == Moto::Test::Result::ERROR ? nil : test_status.results.last.message,
|
66
|
+
failures: test_failures(test_status),
|
67
|
+
duration: test_status.duration
|
68
|
+
}
|
69
|
+
|
70
|
+
@tests[test_status.name] = JSON.parse( RestClient.put( "#{@url}/api/tests/#{@tests[test_status.name]['id']}", data.to_json, :content_type => :json, :accept => :json ) )
|
71
|
+
end
|
72
|
+
|
73
|
+
# @return [String] string with messages of all failures in a test
|
74
|
+
def test_failures(test_status)
|
75
|
+
test_status.results.last.failures.join("\n\t")
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
module Moto
|
2
|
+
module Reporting
|
3
|
+
|
4
|
+
# Value object holding information about whole 'run' of tests.
|
5
|
+
class RunStatus
|
6
|
+
|
7
|
+
# Array of all statuses [Moto::Test:Status] from current run
|
8
|
+
attr_reader :tests_all
|
9
|
+
|
10
|
+
# Array of [Moto::Test:Status] with @results.last.code == [Moto::Test::Result::PASSED]
|
11
|
+
attr_reader :tests_passed
|
12
|
+
|
13
|
+
# Array of [Moto::Test:Status] with @results.last.code == [Moto::Test::Result::SKIPPED]
|
14
|
+
attr_reader :tests_skipped
|
15
|
+
|
16
|
+
# Array of [Moto::Test:Status] with @results.last.code == [Moto::Test::Result::FAILURE]
|
17
|
+
attr_reader :tests_failed
|
18
|
+
|
19
|
+
# Array of [Moto::Test:Status] with @results.last.code == [Moto::Test::Result::ERROR]
|
20
|
+
attr_reader :tests_error
|
21
|
+
|
22
|
+
# Time of run's start
|
23
|
+
attr_reader :time_start
|
24
|
+
|
25
|
+
# Time of run's end
|
26
|
+
attr_reader :time_end
|
27
|
+
|
28
|
+
# Run's duration
|
29
|
+
attr_reader :duration
|
30
|
+
|
31
|
+
def initialize
|
32
|
+
@tests_all = []
|
33
|
+
@tests_passed = []
|
34
|
+
@tests_skipped = []
|
35
|
+
@tests_failed = []
|
36
|
+
@tests_error = []
|
37
|
+
end
|
38
|
+
|
39
|
+
def initialize_run
|
40
|
+
@time_start = Time.now.to_f
|
41
|
+
end
|
42
|
+
|
43
|
+
def finalize_run
|
44
|
+
@time_end = Time.now.to_f
|
45
|
+
@duration = @time_end - @time_start
|
46
|
+
end
|
47
|
+
|
48
|
+
# Summarized result of whole run
|
49
|
+
# @return [String] one of the values defined as constants in this class in cohesion with [Moto::Test::Result]
|
50
|
+
def result
|
51
|
+
|
52
|
+
if @tests_error.length > 0
|
53
|
+
return Moto::Test::Result::ERROR
|
54
|
+
elsif @tests_failed.length > 0
|
55
|
+
return Moto::Test::Result::FAILURE
|
56
|
+
elsif tests_all.length == @tests_skipped.length
|
57
|
+
return Moto::Test::Result::SKIPPED
|
58
|
+
end
|
59
|
+
|
60
|
+
Moto::Test::Result::PASSED
|
61
|
+
end
|
62
|
+
|
63
|
+
# Adds single test's status to the collection which describes whole run
|
64
|
+
# @param [Moto::Test::Status] test_status to be incorporated into final run result
|
65
|
+
def add_test_status(test_status)
|
66
|
+
|
67
|
+
# Separate collections are kept and data is doubled in order to avoid
|
68
|
+
# calling Array.collect in getter for each type of results
|
69
|
+
|
70
|
+
case test_status.results.last.code
|
71
|
+
when Moto::Test::Result::PASSED
|
72
|
+
@tests_passed << test_status
|
73
|
+
when Moto::Test::Result::SKIPPED
|
74
|
+
@tests_skipped << test_status
|
75
|
+
when Moto::Test::Result::FAILURE
|
76
|
+
@tests_failed << test_status
|
77
|
+
when Moto::Test::Result::ERROR
|
78
|
+
@tests_error << test_status
|
79
|
+
else
|
80
|
+
raise 'Incorrect value of field: "code" in [Moto::Test::Status]'
|
81
|
+
end
|
82
|
+
|
83
|
+
@tests_all << test_status
|
84
|
+
end
|
85
|
+
|
86
|
+
# Overwritten definition of to string.
|
87
|
+
# @return [String] string with readable form of result field
|
88
|
+
def to_s
|
89
|
+
case result
|
90
|
+
when Moto::Test::Result::PASSED then return 'PASSED'
|
91
|
+
when Moto::Test::Result::FAILURE then return 'FAILED'
|
92
|
+
when Moto::Test::Result::ERROR then return 'ERROR'
|
93
|
+
when Moto::Test::Result::SKIPPED then return 'SKIPPED'
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|