minitest-reporters 1.3.6 → 1.3.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +28 -27
  3. data/.rubocop.yml +77 -77
  4. data/.ruby-gemset +1 -1
  5. data/.travis.yml +14 -14
  6. data/.yardopts +5 -5
  7. data/CHANGELOG.md +102 -93
  8. data/Gemfile +2 -2
  9. data/LICENSE +20 -20
  10. data/README.md +135 -135
  11. data/Rakefile +70 -70
  12. data/appveyor.yml +22 -22
  13. data/lib/minitest/extensible_backtrace_filter.rb +67 -67
  14. data/lib/minitest/minitest_reporter_plugin.rb +76 -76
  15. data/lib/minitest/old_activesupport_fix.rb +24 -24
  16. data/lib/minitest/relative_position.rb +26 -26
  17. data/lib/minitest/reporters/ansi.rb +30 -30
  18. data/lib/minitest/reporters/base_reporter.rb +136 -136
  19. data/lib/minitest/reporters/default_reporter.rb +228 -228
  20. data/lib/minitest/reporters/html_reporter.rb +224 -224
  21. data/lib/minitest/reporters/junit_reporter.rb +168 -164
  22. data/lib/minitest/reporters/mean_time_reporter.rb +388 -388
  23. data/lib/minitest/reporters/progress_reporter.rb +104 -96
  24. data/lib/minitest/reporters/ruby_mate_reporter.rb +54 -54
  25. data/lib/minitest/reporters/rubymine_reporter.rb +116 -116
  26. data/lib/minitest/reporters/spec_reporter.rb +61 -61
  27. data/lib/minitest/reporters/version.rb +5 -5
  28. data/lib/minitest/reporters.rb +91 -91
  29. data/lib/minitest/templates/index.html.erb +82 -82
  30. data/minitest-reporters.gemspec +31 -32
  31. data/test/fixtures/junit_filename_bug_example_test.rb +41 -41
  32. data/test/fixtures/mean_time_test.rb +36 -36
  33. data/test/fixtures/progress_detailed_skip_test.rb +8 -8
  34. data/test/fixtures/progress_test.rb +8 -8
  35. data/test/fixtures/sample_test.rb +15 -15
  36. data/test/fixtures/spec_test.rb +18 -18
  37. data/test/gallery/bad_test.rb +25 -25
  38. data/test/gallery/good_test.rb +14 -14
  39. data/test/integration/reporters/junit_reporter_test.rb +12 -12
  40. data/test/integration/reporters/mean_time_reporter_test.rb +7 -7
  41. data/test/integration/reporters/progress_reporter_test.rb +40 -40
  42. data/test/test_helper.rb +22 -22
  43. data/test/unit/minitest/extensible_backtrace_filter_test.rb +42 -42
  44. data/test/unit/minitest/junit_reporter_test.rb +46 -23
  45. data/test/unit/minitest/mean_time_reporter_unit_test.rb +149 -149
  46. data/test/unit/minitest/minitest_reporter_plugin_test.rb +14 -14
  47. data/test/unit/minitest/reporters_test.rb +65 -65
  48. data/test/unit/minitest/spec_reporter_test.rb +62 -62
  49. metadata +22 -5
@@ -1,164 +1,168 @@
1
- require 'builder'
2
- require 'fileutils'
3
- require 'pathname'
4
- module Minitest
5
- module Reporters
6
- # A reporter for writing JUnit test reports
7
- # Intended for easy integration with CI servers - tested on JetBrains TeamCity
8
- #
9
- # Inspired by ci_reporter (see https://github.com/nicksieger/ci_reporter)
10
- # Also inspired by Marc Seeger's attempt at producing a JUnitReporter (see https://github.com/rb2k/minitest-reporters/commit/e13d95b5f884453a9c77f62bc5cba3fa1df30ef5)
11
- # Also inspired by minitest-ci (see https://github.com/bhenderson/minitest-ci)
12
- class JUnitReporter < BaseReporter
13
- def initialize(reports_dir = "test/reports", empty = true, options = {})
14
- super({})
15
- @reports_path = File.absolute_path(reports_dir)
16
- @single_file = options[:single_file]
17
- @base_path = options[:base_path] || Dir.pwd
18
-
19
- if empty
20
- puts "Emptying #{@reports_path}"
21
- FileUtils.mkdir_p(@reports_path)
22
- File.delete(*Dir.glob("#{@reports_path}/TEST-*.xml"))
23
- end
24
- end
25
-
26
- def report
27
- super
28
-
29
- puts "Writing XML reports to #{@reports_path}"
30
- suites = tests.group_by { |test|
31
- test_class(test)
32
- }
33
-
34
- if @single_file
35
- xml = Builder::XmlMarkup.new(:indent => 2)
36
- xml.instruct!
37
- xml.testsuites do
38
- suites.each do |suite, tests|
39
- parse_xml_for(xml, suite, tests)
40
- end
41
- end
42
- File.open(filename_for('minitest'), "w") { |file| file << xml.target! }
43
- else
44
- suites.each do |suite, tests|
45
- xml = Builder::XmlMarkup.new(:indent => 2)
46
- xml.instruct!
47
- xml.testsuites do
48
- parse_xml_for(xml, suite, tests)
49
- end
50
- File.open(filename_for(suite), "w") { |file| file << xml.target! }
51
- end
52
- end
53
- end
54
-
55
- def get_relative_path(result)
56
- file_path = Pathname.new(get_source_location(result).first)
57
- base_path = Pathname.new(@base_path)
58
- file_path.relative_path_from(base_path) if file_path.absolute?
59
- file_path
60
- end
61
-
62
- private
63
-
64
- def get_source_location(result)
65
- if result.respond_to? :klass
66
- result.source_location
67
- else
68
- result.method(result.name).source_location
69
- end
70
- end
71
-
72
- def parse_xml_for(xml, suite, tests)
73
- suite_result = analyze_suite(tests)
74
- file_path = get_relative_path(tests.first)
75
-
76
- xml.testsuite(:name => suite, :filepath => file_path,
77
- :skipped => suite_result[:skip_count], :failures => suite_result[:fail_count],
78
- :errors => suite_result[:error_count], :tests => suite_result[:test_count],
79
- :assertions => suite_result[:assertion_count], :time => suite_result[:time]) do
80
- tests.each do |test|
81
- lineno = get_source_location(test).last
82
- xml.testcase(:name => test.name, :lineno => lineno, :classname => suite, :assertions => test.assertions,
83
- :time => test.time) do
84
- xml << xml_message_for(test) unless test.passed?
85
- end
86
- end
87
- end
88
- end
89
-
90
- def xml_message_for(test)
91
- # This is a trick lifted from ci_reporter
92
- xml = Builder::XmlMarkup.new(:indent => 2, :margin => 2)
93
-
94
- def xml.trunc!(txt)
95
- txt.sub(/\n.*/m, '...')
96
- end
97
-
98
- e = test.failure
99
-
100
- if test.skipped?
101
- xml.skipped(:type => test.name)
102
- elsif test.error?
103
- xml.error(:type => test.name, :message => xml.trunc!(e.message)) do
104
- xml.text!(message_for(test))
105
- end
106
- elsif test.failure
107
- xml.failure(:type => test.name, :message => xml.trunc!(e.message)) do
108
- xml.text!(message_for(test))
109
- end
110
- end
111
- end
112
-
113
- def message_for(test)
114
- suite = test.class
115
- name = test.name
116
- e = test.failure
117
-
118
- if test.passed?
119
- nil
120
- elsif test.skipped?
121
- "Skipped:\n#{name}(#{suite}) [#{location(e)}]:\n#{e.message}\n"
122
- elsif test.failure
123
- "Failure:\n#{name}(#{suite}) [#{location(e)}]:\n#{e.message}\n"
124
- elsif test.error?
125
- "Error:\n#{name}(#{suite}):\n#{e.message}"
126
- end
127
- end
128
-
129
- def location(exception)
130
- last_before_assertion = ''
131
- exception.backtrace.reverse_each do |s|
132
- break if s =~ /in .(assert|refute|flunk|pass|fail|raise|must|wont)/
133
- last_before_assertion = s
134
- end
135
- last_before_assertion.sub(/:in .*$/, '')
136
- end
137
-
138
- def analyze_suite(tests)
139
- result = Hash.new(0)
140
- result[:time] = 0
141
- tests.each do |test|
142
- result[:"#{result(test)}_count"] += 1
143
- result[:assertion_count] += test.assertions
144
- result[:test_count] += 1
145
- result[:time] += test.time
146
- end
147
- result
148
- end
149
-
150
- def filename_for(suite)
151
- file_counter = 0
152
- # restrict max filename length, to be kind to filesystems
153
- suite_name = suite.to_s[0..240].gsub(/[^a-zA-Z0-9]+/, '-')
154
- filename = "TEST-#{suite_name}.xml"
155
- while File.exist?(File.join(@reports_path, filename)) # restrict number of tries, to avoid infinite loops
156
- file_counter += 1
157
- filename = "TEST-#{suite_name}-#{file_counter}.xml"
158
- puts "Too many duplicate files, overwriting earlier report #{filename}" and break if file_counter >= 99
159
- end
160
- File.join(@reports_path, filename)
161
- end
162
- end
163
- end
164
- end
1
+ require 'builder'
2
+ require 'fileutils'
3
+ require 'pathname'
4
+ module Minitest
5
+ module Reporters
6
+ # A reporter for writing JUnit test reports
7
+ # Intended for easy integration with CI servers - tested on JetBrains TeamCity
8
+ #
9
+ # Inspired by ci_reporter (see https://github.com/nicksieger/ci_reporter)
10
+ # Also inspired by Marc Seeger's attempt at producing a JUnitReporter (see https://github.com/rb2k/minitest-reporters/commit/e13d95b5f884453a9c77f62bc5cba3fa1df30ef5)
11
+ # Also inspired by minitest-ci (see https://github.com/bhenderson/minitest-ci)
12
+ class JUnitReporter < BaseReporter
13
+ DEFAULT_REPORTS_DIR = "test/reports".freeze
14
+
15
+ attr_reader :reports_path
16
+
17
+ def initialize(reports_dir = DEFAULT_REPORTS_DIR, empty = true, options = {})
18
+ super({})
19
+ @reports_path = File.absolute_path(ENV.fetch("MINITEST_REPORTERS_REPORTS_DIR", reports_dir))
20
+ @single_file = options[:single_file]
21
+ @base_path = options[:base_path] || Dir.pwd
22
+
23
+ if empty
24
+ puts "Emptying #{@reports_path}"
25
+ FileUtils.mkdir_p(@reports_path)
26
+ File.delete(*Dir.glob("#{@reports_path}/TEST-*.xml"))
27
+ end
28
+ end
29
+
30
+ def report
31
+ super
32
+
33
+ puts "Writing XML reports to #{@reports_path}"
34
+ suites = tests.group_by { |test|
35
+ test_class(test)
36
+ }
37
+
38
+ if @single_file
39
+ xml = Builder::XmlMarkup.new(:indent => 2)
40
+ xml.instruct!
41
+ xml.testsuites do
42
+ suites.each do |suite, tests|
43
+ parse_xml_for(xml, suite, tests)
44
+ end
45
+ end
46
+ File.open(filename_for('minitest'), "w") { |file| file << xml.target! }
47
+ else
48
+ suites.each do |suite, tests|
49
+ xml = Builder::XmlMarkup.new(:indent => 2)
50
+ xml.instruct!
51
+ xml.testsuites do
52
+ parse_xml_for(xml, suite, tests)
53
+ end
54
+ File.open(filename_for(suite), "w") { |file| file << xml.target! }
55
+ end
56
+ end
57
+ end
58
+
59
+ def get_relative_path(result)
60
+ file_path = Pathname.new(get_source_location(result).first)
61
+ base_path = Pathname.new(@base_path)
62
+ file_path.relative_path_from(base_path) if file_path.absolute?
63
+ file_path
64
+ end
65
+
66
+ private
67
+
68
+ def get_source_location(result)
69
+ if result.respond_to? :klass
70
+ result.source_location
71
+ else
72
+ result.method(result.name).source_location
73
+ end
74
+ end
75
+
76
+ def parse_xml_for(xml, suite, tests)
77
+ suite_result = analyze_suite(tests)
78
+ file_path = get_relative_path(tests.first)
79
+
80
+ xml.testsuite(:name => suite, :filepath => file_path,
81
+ :skipped => suite_result[:skip_count], :failures => suite_result[:fail_count],
82
+ :errors => suite_result[:error_count], :tests => suite_result[:test_count],
83
+ :assertions => suite_result[:assertion_count], :time => suite_result[:time]) do
84
+ tests.each do |test|
85
+ lineno = get_source_location(test).last
86
+ xml.testcase(:name => test.name, :lineno => lineno, :classname => suite, :assertions => test.assertions,
87
+ :time => test.time) do
88
+ xml << xml_message_for(test) unless test.passed?
89
+ end
90
+ end
91
+ end
92
+ end
93
+
94
+ def xml_message_for(test)
95
+ # This is a trick lifted from ci_reporter
96
+ xml = Builder::XmlMarkup.new(:indent => 2, :margin => 2)
97
+
98
+ def xml.trunc!(txt)
99
+ txt.sub(/\n.*/m, '...')
100
+ end
101
+
102
+ e = test.failure
103
+
104
+ if test.skipped?
105
+ xml.skipped(:type => test.name)
106
+ elsif test.error?
107
+ xml.error(:type => test.name, :message => xml.trunc!(e.message)) do
108
+ xml.text!(message_for(test))
109
+ end
110
+ elsif test.failure
111
+ xml.failure(:type => test.name, :message => xml.trunc!(e.message)) do
112
+ xml.text!(message_for(test))
113
+ end
114
+ end
115
+ end
116
+
117
+ def message_for(test)
118
+ suite = test.class
119
+ name = test.name
120
+ e = test.failure
121
+
122
+ if test.passed?
123
+ nil
124
+ elsif test.skipped?
125
+ "Skipped:\n#{name}(#{suite}) [#{location(e)}]:\n#{e.message}\n"
126
+ elsif test.failure
127
+ "Failure:\n#{name}(#{suite}) [#{location(e)}]:\n#{e.message}\n"
128
+ elsif test.error?
129
+ "Error:\n#{name}(#{suite}):\n#{e.message}"
130
+ end
131
+ end
132
+
133
+ def location(exception)
134
+ last_before_assertion = ''
135
+ exception.backtrace.reverse_each do |s|
136
+ break if s =~ /in .(assert|refute|flunk|pass|fail|raise|must|wont)/
137
+ last_before_assertion = s
138
+ end
139
+ last_before_assertion.sub(/:in .*$/, '')
140
+ end
141
+
142
+ def analyze_suite(tests)
143
+ result = Hash.new(0)
144
+ result[:time] = 0
145
+ tests.each do |test|
146
+ result[:"#{result(test)}_count"] += 1
147
+ result[:assertion_count] += test.assertions
148
+ result[:test_count] += 1
149
+ result[:time] += test.time
150
+ end
151
+ result
152
+ end
153
+
154
+ def filename_for(suite)
155
+ file_counter = 0
156
+ # restrict max filename length, to be kind to filesystems
157
+ suite_name = suite.to_s[0..240].gsub(/[^a-zA-Z0-9]+/, '-')
158
+ filename = "TEST-#{suite_name}.xml"
159
+ while File.exist?(File.join(@reports_path, filename)) # restrict number of tries, to avoid infinite loops
160
+ file_counter += 1
161
+ filename = "TEST-#{suite_name}-#{file_counter}.xml"
162
+ puts "Too many duplicate files, overwriting earlier report #{filename}" and break if file_counter >= 99
163
+ end
164
+ File.join(@reports_path, filename)
165
+ end
166
+ end
167
+ end
168
+ end