@@ -25,6 +25,46 @@ def aggregated_results(*)
25
25
end
26
26
end
27
27
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 ( "\n Top %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
+
28
68
def self . plugin_rails_options ( opts , options )
29
69
::Rails ::TestUnit ::Runner . attach_before_load_options ( opts )
30
70
@@ -44,6 +84,24 @@ def self.plugin_rails_options(opts, options)
44
84
options [ :color ] = value
45
85
end
46
86
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
+
47
105
options [ :color ] = true
48
106
options [ :output_inline ] = true
49
107
end
@@ -67,6 +125,11 @@ def self.plugin_rails_init(options)
67
125
if reporter . reporters . reject! { |reporter | reporter . kind_of? ( ProgressReporter ) }
68
126
reporter << ::Rails ::TestUnitReporter . new ( options [ :io ] , options )
69
127
end
128
+
129
+ # Add slowest tests reporter at the end.
130
+ if options [ :profile ]
131
+ reporter << ProfileReporter . new ( options [ :io ] , options )
132
+ end
70
133
end
71
134
72
135
# Backwards compatibility with Rails 5.0 generated plugin test scripts
0 commit comments