minitest-reporters 0.14.24 → 1.0.0.beta1

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.
@@ -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