-
Notifications
You must be signed in to change notification settings - Fork 21.4k
/
rails_plugin.rb
137 lines (111 loc) · 4.12 KB
/
rails_plugin.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# frozen_string_literal: true
require "active_support/core_ext/module/attribute_accessors"
require "rails/test_unit/reporter"
require "rails/test_unit/runner"
module Minitest
class BacktraceFilterWithFallback
def initialize(preferred, fallback)
@preferred = preferred
@fallback = fallback
end
def filter(backtrace)
filtered = @preferred.filter(backtrace)
filtered = @fallback.filter(backtrace) if filtered.empty?
filtered
end
end
class SuppressedSummaryReporter < SummaryReporter
# Disable extra failure output after a run if output is inline.
def aggregated_results(*)
super unless options[:output_inline]
end
end
class ProfileReporter < StatisticsReporter
def initialize(io = $stdout, options = {})
super
@results = []
@count = options[:profile]
end
def record(result)
@results << result
end
def report
total_time = @results.sum(&:time)
@results.sort! { |a, b| b.time <=> a.time }
slow_results = @results.take(@count)
slow_tests_total_time = slow_results.sum(&:time)
ratio = (total_time == 0) ? 0.0 : (slow_tests_total_time / total_time) * 100
io.puts("\nTop %d slowest tests (%.2f seconds, %.1f%% of total time):\n" % [slow_results.size, slow_tests_total_time, ratio])
slow_results.each do |result|
io.puts(" %s\n %.4f seconds %s\n" % [result.location, result.time, source_location(result)])
end
io.puts("\n")
end
private
def source_location(result)
filename, line = result.source_location
return "" unless filename
pwd = Dir.pwd
if filename.start_with?(pwd)
filename = Pathname.new(filename).relative_path_from(pwd)
end
"#{filename}:#{line}"
end
end
def self.plugin_rails_options(opts, options)
::Rails::TestUnit::Runner.attach_before_load_options(opts)
opts.on("-b", "--backtrace", "Show the complete backtrace") do
options[:full_backtrace] = true
end
opts.on("-d", "--defer-output", "Output test failures and errors after the test run") do
options[:output_inline] = false
end
opts.on("-f", "--fail-fast", "Abort test run on first failure or error") do
options[:fail_fast] = true
end
opts.on("-c", "--[no-]color", "Enable color in the output") do |value|
options[:color] = value
end
opts.on("--profile [COUNT]", "Enable profiling of tests and list the slowest test cases (default: 10)") do |value|
default_count = 10
if value.nil?
count = default_count
else
count = Integer(value, exception: false)
if count.nil?
warn("Non integer specified as profile count, separate " \
"your path from options with -- e.g. " \
"`bin/test --profile -- #{value}`")
count = default_count
end
end
options[:profile] = count
end
options[:color] = true
options[:output_inline] = true
end
# Owes great inspiration to test runner trailblazers like RSpec,
# minitest-reporters, maxitest, and others.
def self.plugin_rails_init(options)
unless options[:full_backtrace] || ENV["BACKTRACE"]
# Plugin can run without Rails loaded, check before filtering.
if ::Rails.respond_to?(:backtrace_cleaner)
Minitest.backtrace_filter = BacktraceFilterWithFallback.new(::Rails.backtrace_cleaner, Minitest.backtrace_filter)
end
end
# Suppress summary reports when outputting inline rerun snippets.
if reporter.reporters.reject! { |reporter| reporter.kind_of?(SummaryReporter) }
reporter << SuppressedSummaryReporter.new(options[:io], options)
end
# Replace progress reporter for colors.
if reporter.reporters.reject! { |reporter| reporter.kind_of?(ProgressReporter) }
reporter << ::Rails::TestUnitReporter.new(options[:io], options)
end
# Add slowest tests reporter at the end.
if options[:profile]
reporter << ProfileReporter.new(options[:io], options)
end
end
# Backwards compatibility with Rails 5.0 generated plugin test scripts
mattr_reader :run_via, default: {}
end