minitest-reporters 0.14.24 → 1.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,7 +1,7 @@
1
1
  require 'ansi/code'
2
2
  require 'builder'
3
3
  require 'fileutils'
4
- module MiniTest
4
+ module Minitest
5
5
  module Reporters
6
6
  # A reporter for writing JUnit test reports
7
7
  # Intended for easy integration with CI servers - tested on JetBrains TeamCity
@@ -9,10 +9,9 @@ module MiniTest
9
9
  # Inspired by ci_reporter (see https://github.com/nicksieger/ci_reporter)
10
10
  # Also inspired by Marc Seeger's attempt at producing a JUnitReporter (see https://github.com/rb2k/minitest-reporters/commit/e13d95b5f884453a9c77f62bc5cba3fa1df30ef5)
11
11
  # Also inspired by minitest-ci (see https://github.com/bhenderson/minitest-ci)
12
- class JUnitReporter
13
- include Reporter
14
-
12
+ class JUnitReporter < BaseReporter
15
13
  def initialize(reports_dir = "test/reports", empty = true)
14
+ super({})
16
15
  @reports_path = File.absolute_path(reports_dir)
17
16
 
18
17
  if empty
@@ -22,20 +21,24 @@ module MiniTest
22
21
  end
23
22
  end
24
23
 
25
- def after_suites(suites, type)
24
+ def report
25
+ super
26
+
26
27
  puts "Writing XML reports to #{@reports_path}"
27
- runner.test_results.each do |suite, tests|
28
- suite_result = analyze_suite(suite, tests)
28
+ suites = tests.group_by(&:class)
29
+
30
+ suites.each do |suite, tests|
31
+ suite_result = analyze_suite(tests)
29
32
 
30
33
  xml = Builder::XmlMarkup.new(:indent => 2)
31
34
  xml.instruct!
32
- xml.testsuite(:name => suite, :skipped => suite_result[:skip_count], :failures => suite_result[:failure_count],
35
+ xml.testsuite(:name => suite, :skipped => suite_result[:skip_count], :failures => suite_result[:fail_count],
33
36
  :errors => suite_result[:error_count], :tests => suite_result[:test_count],
34
37
  :assertions => suite_result[:assertion_count], :time => suite_result[:time]) do
35
- tests.each do |test, test_runner|
36
- xml.testcase(:name => test_runner.test.to_s, :classname => suite, :assertions => test_runner.assertions,
37
- :time => test_runner.time) do
38
- xml << xml_message_for(test_runner) if test_runner.result != :pass
38
+ tests.each do |test|
39
+ xml.testcase(:name => test.name, :classname => suite, :assertions => test.assertions,
40
+ :time => test.time) do
41
+ xml << xml_message_for(test) unless test.passed?
39
42
  end
40
43
  end
41
44
  end
@@ -45,7 +48,7 @@ module MiniTest
45
48
 
46
49
  private
47
50
 
48
- def xml_message_for(test_runner)
51
+ def xml_message_for(test)
49
52
  # This is a trick lifted from ci_reporter
50
53
  xml = Builder::XmlMarkup.new(:indent => 2, :margin => 2)
51
54
 
@@ -53,42 +56,38 @@ module MiniTest
53
56
  txt.sub(/\n.*/m, '...')
54
57
  end
55
58
 
56
- test = test_runner.test
57
- e = test_runner.exception
59
+ e = test.failure
58
60
 
59
- case test_runner.result
60
- when :skip
61
- xml.skipped(:type => test)
62
- when :error
63
- xml.error(:type => test, :message => xml.trunc!(e.message)) do
64
- xml.text!(message_for(test_runner))
61
+ if test.skipped?
62
+ xml.skipped(:type => test.name)
63
+ elsif test.error?
64
+ xml.error(:type => test.name, :message => xml.trunc!(e.message)) do
65
+ xml.text!(message_for(test))
65
66
  end
66
- when :failure
67
- xml.failure(:type => test, :message => xml.trunc!(e.message)) do
68
- xml.text!(message_for(test_runner))
67
+ elsif test.failure
68
+ xml.failure(:type => test.name, :message => xml.trunc!(e.message)) do
69
+ xml.text!(message_for(test))
69
70
  end
70
71
  end
71
72
  end
72
73
 
73
- def message_for(test_runner)
74
- suite = test_runner.suite
75
- test = test_runner.test
76
- e = test_runner.exception
74
+ def message_for(test)
75
+ suite = test.class
76
+ name = test.name
77
+ e = test.failure
77
78
 
78
- case test_runner.result
79
- when :pass then
79
+ if test.passed?
80
80
  nil
81
- when :skip then
82
- "Skipped:\n#{test}(#{suite}) [#{location(e)}]:\n#{e.message}\n"
83
- when :failure then
84
- "Failure:\n#{test}(#{suite}) [#{location(e)}]:\n#{e.message}\n"
85
- when :error
86
- bt = filter_backtrace(test_runner.exception.backtrace).join "\n "
87
- "Error:\n#{test}(#{suite}):\n#{e.class}: #{e.message}\n #{bt}\n"
81
+ elsif test.skipped?
82
+ "Skipped:\n#{name}(#{suite}) [#{location(e)}]:\n#{e.message}\n"
83
+ elsif test.failure
84
+ "Failure:\n#{name}(#{suite}) [#{location(e)}]:\n#{e.message}\n"
85
+ elsif test.error?
86
+ bt = filter_backtrace(test.exception.backtrace).join "\n "
87
+ "Error:\n#{name}(#{suite}):\n#{e.class}: #{e.message}\n #{bt}\n"
88
88
  end
89
89
  end
90
90
 
91
-
92
91
  def location(exception)
93
92
  last_before_assertion = ''
94
93
  exception.backtrace.reverse_each do |s|
@@ -98,13 +97,13 @@ module MiniTest
98
97
  last_before_assertion.sub(/:in .*$/, '')
99
98
  end
100
99
 
101
- def analyze_suite(suite, tests)
100
+ def analyze_suite(tests)
102
101
  result = Hash.new(0)
103
- tests.each do |test, test_runner|
104
- result[:"#{test_runner.result}_count"] += 1
105
- result[:assertion_count] += test_runner.assertions
102
+ tests.each do |test|
103
+ result[:"#{result(test)}_count"] += 1
104
+ result[:assertion_count] += test.assertions
106
105
  result[:test_count] += 1
107
- result[:time] += test_runner.time
106
+ result[:time] += test.time
108
107
  end
109
108
  result
110
109
  end
@@ -1,7 +1,7 @@
1
1
  require 'ansi/code'
2
2
  require 'powerbar'
3
3
 
4
- module MiniTest
4
+ module Minitest
5
5
  module Reporters
6
6
  # Fuubar-like reporter with a progress bar.
7
7
  #
@@ -10,16 +10,17 @@ module MiniTest
10
10
  #
11
11
  # @see https://github.com/jeffkreeftmeijer/fuubar Fuubar
12
12
  # @see https://gist.github.com/356945 paydro's monkey-patch
13
- class ProgressReporter
14
- include Reporter
13
+ class ProgressReporter < BaseReporter
14
+ include RelativePosition
15
15
  include ANSI::Code
16
16
 
17
17
  INFO_PADDING = 2
18
18
 
19
19
  def initialize(options = {})
20
+ super
20
21
  @detailed_skip = options.fetch(:detailed_skip, true)
21
22
 
22
- @progress = PowerBar.new(:msg => "0/#{runner.test_count}")
23
+ @progress = PowerBar.new(:msg => "0/#{count}")
23
24
  @progress.settings.tty.finite.output = lambda { |s| print(s) }
24
25
  @progress.settings.tty.finite.template.barchar = "="
25
26
  @progress.settings.tty.finite.template.padchar = " "
@@ -27,102 +28,65 @@ module MiniTest
27
28
  @progress.settings.tty.finite.template.post = CLEAR
28
29
  end
29
30
 
30
- def before_suites(suites, type)
31
+ def start
32
+ super
31
33
  puts 'Started'
32
34
  puts
33
-
34
- @finished_count = 0
35
35
  show
36
36
  end
37
37
 
38
- def increment
39
- @finished_count += 1
40
- show
41
- end
42
-
43
- def show
44
- return if runner.test_count == 0
45
-
46
- @progress.show({
47
- :msg => "#{@finished_count}/#{runner.test_count}",
48
- :done => @finished_count,
49
- :total => runner.test_count,
50
- }, true)
51
- end
52
-
53
- def after_test(suite, test)
54
- increment
55
- end
56
-
57
- def skip(suite, test, test_runner)
58
- if @detailed_skip
38
+ def record(test)
39
+ super
40
+ if (test.skipped? && @detailed_skip) || test.failure
59
41
  wipe
60
- print(yellow { 'SKIP' })
61
- print_test_with_time(suite, test)
42
+ print(yellow { result(test).to_s.upcase })
43
+ print_test_with_time(test)
62
44
  puts
45
+ print_info(test.failure, test.error?) if test.failure
63
46
  puts
64
47
  end
65
48
 
66
- self.color = YELLOW unless color == RED
67
- end
68
-
69
- def failure(suite, test, test_runner)
70
- wipe
71
- print(red { 'FAIL' })
72
- print_test_with_time(suite, test)
73
- puts
74
- print_info(test_runner.exception, false)
75
- puts
76
-
77
- self.color = RED
78
- end
79
-
80
- def error(suite, test, test_runner)
81
- wipe
82
- print(red { 'ERROR' })
83
- print_test_with_time(suite, test)
84
- puts
85
- print_info(test_runner.exception)
86
- puts
49
+ if test.skipped? && color != RED
50
+ self.color = YELLOW
51
+ elsif test.failure
52
+ self.color = RED
53
+ end
87
54
 
88
- self.color = RED
55
+ show
89
56
  end
90
57
 
91
- def after_suites(suites, type)
58
+ def report
59
+ super
92
60
  @progress.close
93
61
 
94
- total_time = Time.now - runner.suites_start_time
95
-
96
62
  wipe
97
63
  puts
98
64
  puts('Finished in %.5fs' % total_time)
99
- print('%d tests, %d assertions, ' % [runner.test_count, runner.assertion_count])
100
- print(red { '%d failures, %d errors, ' } % [runner.failures, runner.errors])
101
- print(yellow { '%d skips' } % runner.skips)
65
+ print('%d tests, %d assertions, ' % [count, assertions])
66
+ print(red { '%d failures, %d errors, ' } % [failures, errors])
67
+ print(yellow { '%d skips' } % skips)
102
68
  puts
103
69
  end
104
70
 
105
71
  private
106
72
 
107
- def wipe
108
- @progress.wipe
109
- end
73
+ def show
74
+ return if count == 0
110
75
 
111
- def print_test_with_time(suite, test)
112
- total_time = Time.now - (runner.test_start_time || Time.now)
113
- print(" %s#%s (%.2fs)%s" % [suite, test, total_time, clr])
76
+ @progress.show({
77
+ :msg => "#{total_count}/#{count}",
78
+ :done => count,
79
+ :total => total_count,
80
+ }, true)
114
81
  end
115
82
 
116
- def print_info(e, name = true)
117
- print pad("#{e.exception.class.to_s}: ") if name
118
- e.message.each_line { |line| puts pad(line) }
119
-
120
- trace = filter_backtrace(e.backtrace)
121
- trace.each { |line| puts pad(line) }
83
+ def wipe
84
+ @progress.wipe
122
85
  end
123
86
 
124
- def pad(str)
125
- ' ' * INFO_PADDING + str
87
+ def print_test_with_time(test)
88
+ puts [test.name, test.class, total_time, ENDCODE].inspect
89
+ print(" %s#%s (%.2fs)%s" % [test.name, test.class, total_time, ENDCODE])
126
90
  end
127
91
 
128
92
  def color
@@ -1,69 +1,55 @@
1
1
  require 'ansi/code'
2
2
 
3
- module MiniTest
3
+ module Minitest
4
4
  module Reporters
5
5
  # Simple reporter designed for RubyMate.
6
- class RubyMateReporter
7
- include Reporter
6
+ class RubyMateReporter < BaseReporter
7
+ include RelativePosition
8
8
 
9
9
  INFO_PADDING = 2
10
10
 
11
- def before_suites(suites, type)
11
+ def start
12
+ super
12
13
  puts 'Started'
13
14
  puts
14
15
  end
15
16
 
16
- def skip(suite, test, test_runner)
17
- print 'SKIP'
18
- print_test_with_time(suite, test)
19
- puts
20
- puts
21
- end
22
-
23
- def failure(suite, test, test_runner)
24
- print 'FAIL'
25
- print_test_with_time(suite, test)
26
- puts
27
- print_info(test_runner.exception, false)
28
- puts
29
- end
30
-
31
- def error(suite, test, test_runner)
32
- print 'ERROR'
33
- print_test_with_time(suite, test)
34
- puts
35
- print_info(test_runner.exception)
36
- puts
37
- end
38
-
39
- def after_suites(suites, type)
40
- total_time = Time.now - runner.suites_start_time
41
-
17
+ def record(test)
18
+ super
19
+ if test.skipped?
20
+ print 'SKIP'
21
+ print_test_with_time(test)
22
+ puts
23
+ puts
24
+ elsif test.error?
25
+ print 'ERROR'
26
+ print_test_with_time(test)
27
+ puts
28
+ print_info(test.failure)
29
+ puts
30
+ elsif test.failure
31
+ print 'FAIL'
32
+ print_test_with_time(test)
33
+ puts
34
+ print_info(test.failure, false)
35
+ puts
36
+ end
37
+ end
38
+
39
+ def report
40
+ super
42
41
  puts
43
42
  puts('Finished in %.5fs' % total_time)
44
- print('%d tests, %d assertions, ' % [runner.test_count, runner.assertion_count])
45
- print('%d failures, %d errors, ' % [runner.failures, runner.errors])
46
- print('%d skips' % runner.skips)
43
+ print('%d tests, %d assertions, ' % [count, assertions])
44
+ print('%d failures, %d errors, ' % [failures, errors])
45
+ print('%d skips' % skips)
47
46
  puts
48
47
  end
49
48
 
50
49
  private
51
50
 
52
- def print_test_with_time(suite, test)
53
- total_time = Time.now - (runner.test_start_time || Time.now)
54
- print(" #{suite}##{test} (%.2fs)" % total_time)
55
- end
56
-
57
- def print_info(e, name = true)
58
- print "#{e.exception.class.to_s}: " if name
59
- e.message.each_line { |line| puts pad(line) }
60
-
61
- trace = filter_backtrace(e.backtrace)
62
- trace.each { |line| puts pad(line) }
63
- end
64
-
65
- def pad(str)
66
- ' ' * INFO_PADDING + str
51
+ def print_test_with_time(test)
52
+ print(" #{test.class}##{test.name} (%.2fs)" % test.time)
67
53
  end
68
54
  end
69
55
  end
@@ -8,52 +8,32 @@ begin
8
8
  require 'teamcity/utils/runner_utils'
9
9
  require 'teamcity/utils/url_formatter'
10
10
  rescue LoadError
11
- MiniTest::Unit.runner.output.puts("====================================================================================================\n")
12
- MiniTest::Unit.runner.output.puts("RubyMine reporter works only if it test was launched using RubyMine IDE or TeamCity CI server !!!\n")
13
- MiniTest::Unit.runner.output.puts("====================================================================================================\n")
14
- MiniTest::Unit.runner.output.puts("Using default results reporter...\n")
11
+ puts("====================================================================================================\n")
12
+ puts("RubyMine reporter works only if it test was launched using RubyMine IDE or TeamCity CI server !!!\n")
13
+ puts("====================================================================================================\n")
14
+ puts("Using default results reporter...\n")
15
15
 
16
16
  require "minitest/reporters/default_reporter"
17
17
 
18
18
  # delegate to default reporter
19
- module MiniTest
19
+ module Minitest
20
20
  module Reporters
21
21
  class RubyMineReporter < DefaultReporter
22
22
  end
23
23
  end
24
24
  end
25
25
  else
26
- module MiniTest
26
+ module Minitest
27
27
  module Reporters
28
- class RubyMineReporter
29
- include Reporter
28
+ class RubyMineReporter < BaseReporter
30
29
  include ANSI::Code
31
30
 
32
31
  include ::Rake::TeamCity::RunnerCommon
33
32
  include ::Rake::TeamCity::RunnerUtils
34
33
  include ::Rake::TeamCity::Utils::UrlFormatter
35
34
 
36
- def runner
37
- MiniTest::Unit.runner
38
- end
39
-
40
- def output
41
- runner.output
42
- end
43
-
44
- def verbose?
45
- runner.verbose
46
- end
47
-
48
- def print(*args)
49
- runner.output.print(*args)
50
- end
51
-
52
- def puts(*args)
53
- runner.output.puts(*args)
54
- end
55
-
56
- def before_suites(suites, type)
35
+ def start
36
+ super
57
37
  puts 'Started'
58
38
  puts
59
39
 
@@ -62,27 +42,43 @@ else
62
42
  log_test_reporter_attached()
63
43
 
64
44
  # Report tests count:
65
- test_count = runner.test_count
66
45
  if ::Rake::TeamCity.is_in_idea_mode
67
- log(@message_factory.create_tests_count(test_count))
46
+ log(@message_factory.create_tests_count(total_count))
68
47
  elsif ::Rake::TeamCity.is_in_buildserver_mode
69
48
  log(@message_factory.create_progress_message("Starting.. (#{test_count} tests)"))
70
49
  end
71
50
 
72
51
  end
73
52
 
74
- def after_suites(suites, type)
75
- total_time = Time.now - runner.suites_start_time
53
+ def report
54
+ super
76
55
 
77
56
  puts('Finished in %.5fs' % total_time)
78
- print('%d tests, %d assertions, ' % [runner.test_count, runner.assertion_count])
79
- print(red { '%d failures, %d errors, ' } % [runner.failures, runner.errors])
80
- print(yellow { '%d skips' } % runner.skips)
57
+ print('%d tests, %d assertions, ' % [count, assertions])
58
+ print(red { '%d failures, %d errors, ' } % [failures, errors])
59
+ print(yellow { '%d skips' } % skips)
81
60
  puts
82
61
  end
83
62
 
63
+ def record(test)
64
+ super
65
+ unless test.passed?
66
+ with_result(test) do |exception_msg, backtrace|
67
+ if test.skipped?
68
+ log(@message_factory.create_test_ignored(test, exception_msg, backtrace))
69
+ elsif test.error?
70
+ log(@message_factory.create_test_error(test, exception_msg, backtrace))
71
+ else
72
+ log(@message_factory.create_test_failed(test, exception_msg, backtrace))
73
+ end
74
+ end
75
+ end
76
+ end
77
+
78
+ alias_method :output, :io
79
+
84
80
  def before_suite(suite)
85
- fqn = suite.name
81
+ fqn = suite.class
86
82
  log(@message_factory.create_suite_started(suite.name, location_from_ruby_qualified_name(fqn)))
87
83
  end
88
84
 
@@ -90,32 +86,15 @@ else
90
86
  log(@message_factory.create_suite_finished(suite.name))
91
87
  end
92
88
 
93
- def before_test(suite, test)
94
- fqn = "#{suite.name}.#{test.to_s}"
89
+ def before_test(test)
90
+ super
91
+ fqn = "#{test.class.name}.#{test.to_s}"
95
92
  log(@message_factory.create_test_started(test, minitest_test_location(fqn)))
96
93
  end
97
94
 
98
- def after_test(suite, test)
99
- duration_ms = get_current_time_in_ms() - get_time_in_ms(runner.test_start_time || Time.now)
100
- log(@message_factory.create_test_finished(test, duration_ms.nil? ? 0 : duration_ms))
101
- end
102
-
103
- def skip(suite, test, test_runner)
104
- with_result(test, test_runner) do |exception_msg, backtrace|
105
- log(@message_factory.create_test_ignored(test, exception_msg, backtrace))
106
- end
107
- end
108
-
109
- def failure(suite, test, test_runner)
110
- with_result(test, test_runner) do |exception_msg, backtrace|
111
- log(@message_factory.create_test_failed(test, exception_msg, backtrace))
112
- end
113
- end
114
-
115
- def error(suite, test, test_runner)
116
- with_result(test, test_runner) do |exception_msg, backtrace|
117
- log(@message_factory.create_test_error(test, exception_msg, backtrace))
118
- end
95
+ def after_test(test)
96
+ super
97
+ log(@message_factory.create_test_finished(test, test.time))
119
98
  end
120
99
 
121
100
  #########
@@ -133,20 +112,13 @@ else
133
112
  "ruby_minitest_qn://#{fqn}"
134
113
  end
135
114
 
136
- def with_result(test, test_runner)
137
- exception = test_runner.exception
115
+ def with_result(test)
116
+ exception = test.failure
138
117
  msg = exception.nil? ? "" : "#{exception.class.name}: #{exception.message}"
139
118
  backtrace = exception.nil? ? "" : filter_backtrace(exception.backtrace).join("\n")
140
119
 
141
120
  yield(msg, backtrace)
142
121
  end
143
-
144
- def filter_backtrace(bt)
145
- result = super
146
- return result if result.nil? || result.empty?
147
- # let's reject test/unit/assetions from the backtrace
148
- result.reject { |line| line =~ /\/lib\/ruby\/[0-9.]+\/test\/unit\//}
149
- end
150
122
  end
151
123
  end
152
124
  end