Created
February 27, 2026 16:48
-
-
Save KHCode/c77dacb2fa46d3e7d2f1d5d8b2487e3e to your computer and use it in GitHub Desktop.
Rspec file benchmark rake task
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # frozen_string_literal: true | |
| desc 'Run an RSpec file multiple times and report timing statistics. Usage: rake rspec_benchmark[spec/path/to/file,5]' | |
| task :rspec_benchmark, [:file, :runs] do |_t, args| | |
| file = args[:file] | |
| runs = args[:runs]&.to_i | |
| if file.nil? || file.empty? | |
| puts "Usage: rake rspec_benchmark[spec/path/to/file,number_of_runs]" | |
| exit 1 | |
| end | |
| unless File.exist?(file) | |
| puts "File not found: #{file}" | |
| exit 1 | |
| end | |
| if runs.nil? || runs < 1 | |
| puts "Number of runs must be at least 1." | |
| exit 1 | |
| end | |
| times = [] | |
| runs.times do |i| | |
| puts "\n#{'=' * 60}" | |
| puts "Run #{i + 1} of #{runs}" | |
| puts '=' * 60 | |
| output = `bundle exec rspec #{file} 2>&1` | |
| puts output | |
| if (match = output.match(/Finished in (\d+\.?\d*) seconds?/)) | |
| duration = match[1].to_f | |
| times << duration | |
| puts ">> Run #{i + 1} completed in #{duration}s" | |
| else | |
| puts ">> Run #{i + 1}: Could not parse timing from output." | |
| end | |
| end | |
| if times.empty? | |
| puts "\nNo timing data collected." | |
| exit 1 | |
| end | |
| sorted = times.sort | |
| sum = sorted.sum | |
| count = sorted.length | |
| mean = sum / count | |
| median = if count.odd? | |
| sorted[count / 2] | |
| else | |
| (sorted[(count / 2) - 1] + sorted[count / 2]) / 2.0 | |
| end | |
| range = sorted.last - sorted.first | |
| frequency = sorted.map { |t| t.round(1) }.tally | |
| max_freq = frequency.values.max | |
| modes = frequency.select { |_, v| v == max_freq }.keys | |
| puts "\n#{'=' * 60}" | |
| puts 'RESULTS' | |
| puts '=' * 60 | |
| times.each_with_index do |t, i| | |
| puts " Run #{i + 1}: #{t.round(4)}s" | |
| end | |
| puts '-' * 40 | |
| puts " Mean: #{mean.round(4)}s" | |
| puts " Median: #{median.round(4)}s" | |
| puts " Mode: #{modes.map { |m| "#{m}s" }.join(', ')} (rounded to 0.1s, appeared #{max_freq}x)" | |
| puts " Range: #{range.round(4)}s (#{sorted.first.round(4)}s – #{sorted.last.round(4)}s)" | |
| puts '=' * 60 | |
| end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment