Skip to content

Commit c3c566f

Browse files
authored
Merge pull request rails#49082 from fatkodima/profile-tests
Add ability to show slow tests to the test runner
2 parents 967b8d4 + 14d9b3e commit c3c566f

File tree

1 file changed

+63
-0
lines changed

1 file changed

+63
-0
lines changed

railties/lib/minitest/rails_plugin.rb

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,46 @@ def aggregated_results(*)
2525
end
2626
end
2727

28+
class ProfileReporter < StatisticsReporter
29+
def initialize(io = $stdout, options = {})
30+
super
31+
@results = []
32+
@count = options[:profile]
33+
end
34+
35+
def record(result)
36+
@results << result
37+
end
38+
39+
def report
40+
total_time = @results.sum(&:time)
41+
42+
@results.sort! { |a, b| b.time <=> a.time }
43+
slow_results = @results.take(@count)
44+
slow_tests_total_time = slow_results.sum(&:time)
45+
46+
ratio = (total_time == 0) ? 0.0 : (slow_tests_total_time / total_time) * 100
47+
48+
io.puts("\nTop %d slowest tests (%.2f seconds, %.1f%% of total time):\n" % [slow_results.size, slow_tests_total_time, ratio])
49+
slow_results.each do |result|
50+
io.puts(" %s\n %.4f seconds %s\n" % [result.location, result.time, source_location(result)])
51+
end
52+
io.puts("\n")
53+
end
54+
55+
private
56+
def source_location(result)
57+
filename, line = result.source_location
58+
return "" unless filename
59+
60+
pwd = Dir.pwd
61+
if filename.start_with?(pwd)
62+
filename = Pathname.new(filename).relative_path_from(pwd)
63+
end
64+
"#{filename}:#{line}"
65+
end
66+
end
67+
2868
def self.plugin_rails_options(opts, options)
2969
::Rails::TestUnit::Runner.attach_before_load_options(opts)
3070

@@ -44,6 +84,24 @@ def self.plugin_rails_options(opts, options)
4484
options[:color] = value
4585
end
4686

87+
opts.on("--profile [COUNT]", "Enable profiling of tests and list the slowest test cases (default: 10)") do |value|
88+
default_count = 10
89+
90+
if value.nil?
91+
count = default_count
92+
else
93+
count = Integer(value, exception: false)
94+
if count.nil?
95+
warn("Non integer specified as profile count, separate " \
96+
"your path from options with -- e.g. " \
97+
"`bin/test --profile -- #{value}`")
98+
count = default_count
99+
end
100+
end
101+
102+
options[:profile] = count
103+
end
104+
47105
options[:color] = true
48106
options[:output_inline] = true
49107
end
@@ -67,6 +125,11 @@ def self.plugin_rails_init(options)
67125
if reporter.reporters.reject! { |reporter| reporter.kind_of?(ProgressReporter) }
68126
reporter << ::Rails::TestUnitReporter.new(options[:io], options)
69127
end
128+
129+
# Add slowest tests reporter at the end.
130+
if options[:profile]
131+
reporter << ProfileReporter.new(options[:io], options)
132+
end
70133
end
71134

72135
# Backwards compatibility with Rails 5.0 generated plugin test scripts

0 commit comments

Comments
 (0)