Matt Schuchard Matt Schuchard - 1 year ago 66
Ruby Question

Difference between pattern syntax in RSpec::Core::RakeTask and Pathname/Dir.glob

  1. If I do a
    then the recursive part guarantees that a directory named
    in the current directory will be captured. If I do a
    task.pattern = '**/spec/**/*_spec.rb'
    then tests inside spec in the current directory are not executed. They will be if the pattern is
    . What is the difference with patterns in
    and why?

  2. According to the documentation the default pattern for RSpec is
    . Why is this different than the default
    ; I assume this is related to the first question)?

Answer Source

How glob patterns are used in RSpec::Core::RakeTask

RSpec::Core::RakeTask just runs the rspec executable. Setting a task's pattern just passes the pattern with the --pattern flag.

RSpec first constructs a list of paths in which to look for specs. If no files or directories are given on the command line, a single default path is used, 'spec'. RSpec looks for the pattern in each path. If the pattern begins with the path, RSpec just globs the pattern. If the pattern doesn't begin with the path, RSpec prepends the path to the pattern. So:

  • The pattern **/spec/**/*_spec.rb begins with a wildcard, so RSpec prepends the path, and spec/**/spec/**/*_spec.rb doesn't match anything.
  • The pattern spec/**/*_spec.rb begins with the path, so RSpec just uses it and it works.

The pattern **/*_spec.rb would also work; RSpec would prepend spec/.

RSpec::Core::RakeTask's default pattern

This part of the pattern **{,/*/**} allows it to follow symlinks. I don't know why RSpec::Core::RakeTask follows symlinks by default and command-line rspec doesn't.

I believe the the rake task's default pattern only works because RSpec recognizes that it begins with the path and doesn't prepend the path. I think if it were **{,/*/**}/*_spec.rb it would be clearer and would work in more situations.