Have you ever written a spec and forgotten to give its file name the
required _spec.rb
suffix? That spec will rarely (if ever) be run and you may never find out…
Perhaps surprisingly, a default-configured, bare rspec
command only
runs spec files ending with _spec.rb
inside the spec/
directory:
For example, a spec file at spec/models/foo.rb
will not be run
by a typical, plain rspec
command.
What can make this slip-up hard to detect is when you
give the full file path as an argument to rspec
(e.g.
rspec spec/models/foo.rb
) then the spec will be run
and you won’t get a heads-up about the file name.
# Only runs specs withs paths like spec/**/*_spec.rb
# spec/models/foo.rb would _not_ be run:
rspec
# Explicit path argument will run foo.rb:
rspec spec/models/foo.rb
The good news is you can protect yourself against these spec file name oversights by adding an enforcer to your projects:
# Suggested steps:
# 1. Create file: `spec/support/spec_file_name_enforcer.rb`
# 2. Include the below config in spec_file_name_enforcer.rb
# 3. Ensure test env requires `spec/support/*` files
RSpec.configure do |config|
config.before(:suite) do
files_without_spec_suffix = Dir.glob('spec/**/*').select do |filename|
# Customize regular expression patterns below as needed. Common
# non-spec file paths under spec/ will not raise an error.
File.file?(filename) &&
!filename.match(/_spec\.rb\z/) &&
!filename.match(%r{\Aspec/(support|factories|mailers/previews)/}) &&
!filename.match(%r{\Aspec/(spec_helper\.rb|rails_helper\.rb|examples\.txt)\z})
end
if files_without_spec_suffix.any?
raise 'Spec files need _spec.rb suffix: ' + files_without_spec_suffix.join(', ')
end
end
end
Running rspec
on a project using the above configuration will raise an error
any time a suspect file in spec/
is detected without the _spec.rb
suffix.
You can check the spec file names are being enforced in your own project by
creating an empty file with touch spec/models/foo.rb
. Run rspec
and
check it reports a “Spec files need _spec.rb suffix: spec/models/foo.rb
” error.