Beat Spec File Name Blunders

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:

# 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)/}) &&

    if files_without_spec_suffix.any?
      raise 'Spec files need _spec.rb suffix: ' +
        files_without_spec_suffix.join(', ')

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.