How do I get the current test file name from RSpec?
I am trying to speed up large RSpec projects. In addition to using the RSpec option, --profile
I wanted to get the longest test files [1].
In mine, spec_helper.rb
I am dumping the tested classes and the total time per file, however, since we have directories spec/model
and spec/request
, I would really like to be able to print the current test file name, not just the class name ( described_class
), so that the user can eliminate the double deviation between model/foo_spec.rb
and request/foo_spec.rb
when optimizing.
In block before
c spec/spec_helper.rb
, how can I get the current filename of the test file?
Mine (heavily cropped) spec_helper
looks like this:
config.before :all do
@start_time = Time.now
end
config.after :all do |test|
timings.push({ :name => test.described_class,
:file => 'I do not know how to get this',
:duration_in_seconds => (Time.now - @start_time) })
end
config.after :suite do
timing_logfile_name = 'log/rspec_file_times.log'
timing_logfile = "#{File.dirname(__FILE__)}/../#{timing_logfile_name}"
file = File.open(timing_logfile, 'w')
timings.sort_by{ |timing| timing[:duration_in_seconds].to_f }.reverse!.each do |timing|
file.write( sprintf("%-25.25s % 9.3f seconds\n",
timing[:name], timing[:duration_in_seconds]) )
end
file.close
tell_if_verbose("Overall test times are logged in '#{timing_logfile_name}'")
end
This doesn't sound like curpecn RSpec metadata, but I hope someone more familiar with internals can think of a way to expose it. Thanks, Dave
[1] Often a file with, say, 100 examples in it gives a higher speed than one example from -profile, when this large file before :each
/ before :all
blocks is targeted, obviously even the saved ms is multiplied by the number of tests in the file. Using this technique in addition to --profile
me helped a lot.
As long as you're just using this to profile your tests to determine which files need to be improved, you should be able to add this to your file spec_helper.rb
(and remove it afterwards). I totally understand that this is not pretty / clean / elegant / acceptable in production environments, and I disavow that I ever wrote this :)
config.before(:each) do |example|
path = example.metadata[:example_group][:file_path]
curr_path = config.instance_variable_get(:@curr_file_path)
if (curr_path.nil? || path != curr_path)
config.instance_variable_set(:@curr_file_path, path)
puts path
end
end