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,224 +1,224 @@
1
- require 'builder'
2
- require 'fileutils'
3
- require 'erb'
4
-
5
- module Minitest
6
- module Reporters
7
- # A reporter for generating HTML test reports
8
- # This is recommended to be used with a CI server, where the report is kept as an artifact and is accessible via
9
- # a shared link
10
- #
11
- # The reporter sorts the results alphabetically and then by results
12
- # so that failing and skipped tests are at the top.
13
- #
14
- # When using Minitest Specs, the number prefix is dropped from the name of the test so that it reads well
15
- #
16
- # On each test run all files in the reports directory are deleted, this prevents a build up of old reports
17
- #
18
- # The report is generated using ERB. A custom ERB template can be provided but it is not required
19
- # The default ERB template uses JQuery and Bootstrap, both of these are included by referencing the CDN sites
20
- class HtmlReporter < BaseReporter
21
- # The title of the report
22
- attr_reader :title
23
-
24
- # The number of tests that passed
25
- def passes
26
- count - failures - errors - skips
27
- end
28
-
29
- # The percentage of tests that passed, calculated in a way that avoids rounding errors
30
- def percent_passes
31
- 100 - percent_skipps - percent_errors_failures
32
- end
33
-
34
- # The percentage of tests that were skipped
35
- def percent_skipps
36
- (skips / count.to_f * 100).to_i
37
- end
38
-
39
- # The percentage of tests that failed
40
- def percent_errors_failures
41
- ((errors + failures) / count.to_f * 100).to_i
42
- end
43
-
44
- # Trims off the number prefix on test names when using Minitest Specs
45
- def friendly_name(test)
46
- groups = test.name.scan(/(test_\d+_)(.*)/i)
47
- return test.name if groups.empty?
48
- "it #{groups[0][1]}"
49
- end
50
-
51
- # The constructor takes a hash, and uses the following keys:
52
- # :title - the title that will be used in the report, defaults to 'Test Results'
53
- # :reports_dir - the directory the reports should be written to, defaults to 'test/html_reports'
54
- # :erb_template - the path to a custom ERB template, defaults to the supplied ERB template
55
- # :mode - Useful for debugging, :terse suppresses errors and is the default, :verbose lets errors bubble up
56
- # :output_filename - the report's filename, defaults to 'index.html'
57
- def initialize(args = {})
58
- super({})
59
-
60
- defaults = {
61
- :title => 'Test Results',
62
- :erb_template => "#{File.dirname(__FILE__)}/../templates/index.html.erb",
63
- :reports_dir => 'test/html_reports',
64
- :mode => :safe,
65
- :output_filename => 'index.html',
66
- }
67
-
68
- settings = defaults.merge(args)
69
-
70
- @mode = settings[:mode]
71
- @title = settings[:title]
72
- @erb_template = settings[:erb_template]
73
- @output_filename = settings[:output_filename]
74
- reports_dir = settings[:reports_dir]
75
-
76
- @reports_path = File.absolute_path(reports_dir)
77
- end
78
-
79
- def start
80
- super
81
-
82
- puts "Emptying #{@reports_path}"
83
- FileUtils.mkdir_p(@reports_path)
84
- File.delete(html_file) if File.exist?(html_file)
85
- end
86
-
87
- # Called by the framework to generate the report
88
- def report
89
- super
90
-
91
- begin
92
- puts "Writing HTML reports to #{@reports_path}"
93
- erb_str = File.read(@erb_template)
94
- renderer = ERB.new(erb_str)
95
-
96
- tests_by_suites = tests.group_by { |test| test_class(test) } # taken from the JUnit reporter
97
-
98
- suites = tests_by_suites.map do |suite, tests|
99
- suite_summary = summarize_suite(suite, tests)
100
- suite_summary[:tests] = tests.sort { |a, b| compare_tests(a, b) }
101
- suite_summary
102
- end
103
-
104
- suites.sort! { |a, b| compare_suites(a, b) }
105
-
106
- result = renderer.result(binding)
107
- File.open(html_file, 'w') do |f|
108
- f.write(result)
109
- end
110
-
111
- # rubocop:disable Lint/RescueException
112
- rescue Exception => e
113
- puts 'There was an error writing the HTML report'
114
- puts 'This may have been caused by cancelling the test run'
115
- puts 'Use mode => :verbose in the HTML reporters constructor to see more detail' if @mode == :terse
116
- puts 'Use mode => :terse in the HTML reporters constructor to see less detail' if @mode != :terse
117
- raise e if @mode != :terse
118
- end
119
- # rubocop:enable Lint/RescueException
120
- end
121
-
122
- private
123
-
124
- def html_file
125
- "#{@reports_path}/#{@output_filename}"
126
- end
127
-
128
- def compare_suites_by_name(suite_a, suite_b)
129
- suite_a[:name] <=> suite_b[:name]
130
- end
131
-
132
- def compare_tests_by_name(test_a, test_b)
133
- friendly_name(test_a) <=> friendly_name(test_b)
134
- end
135
-
136
- # Test suites are first ordered by evaluating the results of the tests, then by test suite name
137
- # Test suites which have failing tests are given highest order
138
- # Tests suites which have skipped tests are given second highest priority
139
- def compare_suites(suite_a, suite_b)
140
- return compare_suites_by_name(suite_a, suite_b) if suite_a[:has_errors_or_failures] && suite_b[:has_errors_or_failures]
141
- return -1 if suite_a[:has_errors_or_failures] && !suite_b[:has_errors_or_failures]
142
- return 1 if !suite_a[:has_errors_or_failures] && suite_b[:has_errors_or_failures]
143
-
144
- return compare_suites_by_name(suite_a, suite_b) if suite_a[:has_skipps] && suite_b[:has_skipps]
145
- return -1 if suite_a[:has_skipps] && !suite_b[:has_skipps]
146
- return 1 if !suite_a[:has_skipps] && suite_b[:has_skipps]
147
-
148
- compare_suites_by_name(suite_a, suite_b)
149
- end
150
-
151
- # Tests are first ordered by evaluating the results of the tests, then by tests names
152
- # Tess which fail are given highest order
153
- # Tests which are skipped are given second highest priority
154
- def compare_tests(test_a, test_b)
155
- return compare_tests_by_name(test_a, test_b) if test_fail_or_error?(test_a) && test_fail_or_error?(test_b)
156
-
157
- return -1 if test_fail_or_error?(test_a) && !test_fail_or_error?(test_b)
158
- return 1 if !test_fail_or_error?(test_a) && test_fail_or_error?(test_b)
159
-
160
- return compare_tests_by_name(test_a, test_b) if test_a.skipped? && test_b.skipped?
161
- return -1 if test_a.skipped? && !test_b.skipped?
162
- return 1 if !test_a.skipped? && test_b.skipped?
163
-
164
- compare_tests_by_name(test_a, test_b)
165
- end
166
-
167
- def test_fail_or_error?(test)
168
- test.error? || test.failure
169
- end
170
-
171
- # based on analyze_suite from the JUnit reporter
172
- def summarize_suite(suite, tests)
173
- summary = Hash.new(0)
174
- summary[:name] = suite.to_s
175
- tests.each do |test|
176
- summary[:"#{result(test)}_count"] += 1
177
- summary[:assertion_count] += test.assertions
178
- summary[:test_count] += 1
179
- summary[:time] += test.time
180
- end
181
- summary[:has_errors_or_failures] = (summary[:fail_count] + summary[:error_count]) > 0
182
- summary[:has_skipps] = summary[:skip_count] > 0
183
- summary
184
- end
185
-
186
- # based on message_for(test) from the JUnit reporter
187
- def message_for(test)
188
- suite = test.class
189
- name = test.name
190
- e = test.failure
191
-
192
- if test.passed?
193
- nil
194
- elsif test.skipped?
195
- "Skipped:\n#{name}(#{suite}) [#{location(e)}]:\n#{e.message}\n"
196
- elsif test.failure
197
- "Failure:\n#{name}(#{suite}) [#{location(e)}]:\n#{e.message}\n"
198
- elsif test.error?
199
- "Error:\n#{name}(#{suite}):\n#{e.message}"
200
- end
201
- end
202
-
203
- # taken from the JUnit reporter
204
- def location(exception)
205
- last_before_assertion = ''
206
- exception.backtrace.reverse_each do |s|
207
- break if s =~ /in .(assert|refute|flunk|pass|fail|raise|must|wont)/
208
- last_before_assertion = s
209
- end
210
- last_before_assertion.sub(/:in .*$/, '')
211
- end
212
-
213
- def total_time_to_hms
214
- return ('%.2fs' % total_time) if total_time < 1
215
-
216
- hours = (total_time / (60 * 60)).round
217
- minutes = ((total_time / 60) % 60).round.to_s.rjust(2, '0')
218
- seconds = (total_time % 60).round.to_s.rjust(2, '0')
219
-
220
- "#{hours}h#{minutes}m#{seconds}s"
221
- end
222
- end
223
- end
224
- end
1
+ require 'builder'
2
+ require 'fileutils'
3
+ require 'erb'
4
+
5
+ module Minitest
6
+ module Reporters
7
+ # A reporter for generating HTML test reports
8
+ # This is recommended to be used with a CI server, where the report is kept as an artifact and is accessible via
9
+ # a shared link
10
+ #
11
+ # The reporter sorts the results alphabetically and then by results
12
+ # so that failing and skipped tests are at the top.
13
+ #
14
+ # When using Minitest Specs, the number prefix is dropped from the name of the test so that it reads well
15
+ #
16
+ # On each test run all files in the reports directory are deleted, this prevents a build up of old reports
17
+ #
18
+ # The report is generated using ERB. A custom ERB template can be provided but it is not required
19
+ # The default ERB template uses JQuery and Bootstrap, both of these are included by referencing the CDN sites
20
+ class HtmlReporter < BaseReporter
21
+ # The title of the report
22
+ attr_reader :title
23
+
24
+ # The number of tests that passed
25
+ def passes
26
+ count - failures - errors - skips
27
+ end
28
+
29
+ # The percentage of tests that passed, calculated in a way that avoids rounding errors
30
+ def percent_passes
31
+ 100 - percent_skipps - percent_errors_failures
32
+ end
33
+
34
+ # The percentage of tests that were skipped
35
+ def percent_skipps
36
+ (skips / count.to_f * 100).to_i
37
+ end
38
+
39
+ # The percentage of tests that failed
40
+ def percent_errors_failures
41
+ ((errors + failures) / count.to_f * 100).to_i
42
+ end
43
+
44
+ # Trims off the number prefix on test names when using Minitest Specs
45
+ def friendly_name(test)
46
+ groups = test.name.scan(/(test_\d+_)(.*)/i)
47
+ return test.name if groups.empty?
48
+ "it #{groups[0][1]}"
49
+ end
50
+
51
+ # The constructor takes a hash, and uses the following keys:
52
+ # :title - the title that will be used in the report, defaults to 'Test Results'
53
+ # :reports_dir - the directory the reports should be written to, defaults to 'test/html_reports'
54
+ # :erb_template - the path to a custom ERB template, defaults to the supplied ERB template
55
+ # :mode - Useful for debugging, :terse suppresses errors and is the default, :verbose lets errors bubble up
56
+ # :output_filename - the report's filename, defaults to 'index.html'
57
+ def initialize(args = {})
58
+ super({})
59
+
60
+ defaults = {
61
+ :title => 'Test Results',
62
+ :erb_template => "#{File.dirname(__FILE__)}/../templates/index.html.erb",
63
+ :reports_dir => 'test/html_reports',
64
+ :mode => :safe,
65
+ :output_filename => 'index.html',
66
+ }
67
+
68
+ settings = defaults.merge(args)
69
+
70
+ @mode = settings[:mode]
71
+ @title = settings[:title]
72
+ @erb_template = settings[:erb_template]
73
+ @output_filename = settings[:output_filename]
74
+ reports_dir = settings[:reports_dir]
75
+
76
+ @reports_path = File.absolute_path(reports_dir)
77
+ end
78
+
79
+ def start
80
+ super
81
+
82
+ puts "Emptying #{@reports_path}"
83
+ FileUtils.mkdir_p(@reports_path)
84
+ File.delete(html_file) if File.exist?(html_file)
85
+ end
86
+
87
+ # Called by the framework to generate the report
88
+ def report
89
+ super
90
+
91
+ begin
92
+ puts "Writing HTML reports to #{@reports_path}"
93
+ erb_str = File.read(@erb_template)
94
+ renderer = ERB.new(erb_str)
95
+
96
+ tests_by_suites = tests.group_by { |test| test_class(test) } # taken from the JUnit reporter
97
+
98
+ suites = tests_by_suites.map do |suite, tests|
99
+ suite_summary = summarize_suite(suite, tests)
100
+ suite_summary[:tests] = tests.sort { |a, b| compare_tests(a, b) }
101
+ suite_summary
102
+ end
103
+
104
+ suites.sort! { |a, b| compare_suites(a, b) }
105
+
106
+ result = renderer.result(binding)
107
+ File.open(html_file, 'w') do |f|
108
+ f.write(result)
109
+ end
110
+
111
+ # rubocop:disable Lint/RescueException
112
+ rescue Exception => e
113
+ puts 'There was an error writing the HTML report'
114
+ puts 'This may have been caused by cancelling the test run'
115
+ puts 'Use mode => :verbose in the HTML reporters constructor to see more detail' if @mode == :terse
116
+ puts 'Use mode => :terse in the HTML reporters constructor to see less detail' if @mode != :terse
117
+ raise e if @mode != :terse
118
+ end
119
+ # rubocop:enable Lint/RescueException
120
+ end
121
+
122
+ private
123
+
124
+ def html_file
125
+ "#{@reports_path}/#{@output_filename}"
126
+ end
127
+
128
+ def compare_suites_by_name(suite_a, suite_b)
129
+ suite_a[:name] <=> suite_b[:name]
130
+ end
131
+
132
+ def compare_tests_by_name(test_a, test_b)
133
+ friendly_name(test_a) <=> friendly_name(test_b)
134
+ end
135
+
136
+ # Test suites are first ordered by evaluating the results of the tests, then by test suite name
137
+ # Test suites which have failing tests are given highest order
138
+ # Tests suites which have skipped tests are given second highest priority
139
+ def compare_suites(suite_a, suite_b)
140
+ return compare_suites_by_name(suite_a, suite_b) if suite_a[:has_errors_or_failures] && suite_b[:has_errors_or_failures]
141
+ return -1 if suite_a[:has_errors_or_failures] && !suite_b[:has_errors_or_failures]
142
+ return 1 if !suite_a[:has_errors_or_failures] && suite_b[:has_errors_or_failures]
143
+
144
+ return compare_suites_by_name(suite_a, suite_b) if suite_a[:has_skipps] && suite_b[:has_skipps]
145
+ return -1 if suite_a[:has_skipps] && !suite_b[:has_skipps]
146
+ return 1 if !suite_a[:has_skipps] && suite_b[:has_skipps]
147
+
148
+ compare_suites_by_name(suite_a, suite_b)
149
+ end
150
+
151
+ # Tests are first ordered by evaluating the results of the tests, then by tests names
152
+ # Tess which fail are given highest order
153
+ # Tests which are skipped are given second highest priority
154
+ def compare_tests(test_a, test_b)
155
+ return compare_tests_by_name(test_a, test_b) if test_fail_or_error?(test_a) && test_fail_or_error?(test_b)
156
+
157
+ return -1 if test_fail_or_error?(test_a) && !test_fail_or_error?(test_b)
158
+ return 1 if !test_fail_or_error?(test_a) && test_fail_or_error?(test_b)
159
+
160
+ return compare_tests_by_name(test_a, test_b) if test_a.skipped? && test_b.skipped?
161
+ return -1 if test_a.skipped? && !test_b.skipped?
162
+ return 1 if !test_a.skipped? && test_b.skipped?
163
+
164
+ compare_tests_by_name(test_a, test_b)
165
+ end
166
+
167
+ def test_fail_or_error?(test)
168
+ test.error? || test.failure
169
+ end
170
+
171
+ # based on analyze_suite from the JUnit reporter
172
+ def summarize_suite(suite, tests)
173
+ summary = Hash.new(0)
174
+ summary[:name] = suite.to_s
175
+ tests.each do |test|
176
+ summary[:"#{result(test)}_count"] += 1
177
+ summary[:assertion_count] += test.assertions
178
+ summary[:test_count] += 1
179
+ summary[:time] += test.time
180
+ end
181
+ summary[:has_errors_or_failures] = (summary[:fail_count] + summary[:error_count]) > 0
182
+ summary[:has_skipps] = summary[:skip_count] > 0
183
+ summary
184
+ end
185
+
186
+ # based on message_for(test) from the JUnit reporter
187
+ def message_for(test)
188
+ suite = test.class
189
+ name = test.name
190
+ e = test.failure
191
+
192
+ if test.passed?
193
+ nil
194
+ elsif test.skipped?
195
+ "Skipped:\n#{name}(#{suite}) [#{location(e)}]:\n#{e.message}\n"
196
+ elsif test.failure
197
+ "Failure:\n#{name}(#{suite}) [#{location(e)}]:\n#{e.message}\n"
198
+ elsif test.error?
199
+ "Error:\n#{name}(#{suite}):\n#{e.message}"
200
+ end
201
+ end
202
+
203
+ # taken from the JUnit reporter
204
+ def location(exception)
205
+ last_before_assertion = ''
206
+ exception.backtrace.reverse_each do |s|
207
+ break if s =~ /in .(assert|refute|flunk|pass|fail|raise|must|wont)/
208
+ last_before_assertion = s
209
+ end
210
+ last_before_assertion.sub(/:in .*$/, '')
211
+ end
212
+
213
+ def total_time_to_hms
214
+ return ('%.2fs' % total_time) if total_time < 1
215
+
216
+ hours = (total_time / (60 * 60)).round
217
+ minutes = ((total_time / 60) % 60).round.to_s.rjust(2, '0')
218
+ seconds = (total_time % 60).round.to_s.rjust(2, '0')
219
+
220
+ "#{hours}h#{minutes}m#{seconds}s"
221
+ end
222
+ end
223
+ end
224
+ end