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.
source to share
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
source to share