Search code examples
rubyrspecrakeglobrake-task

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


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

  2. According to the documentation the default pattern for RSpec is **/*_spec.rb. Why is this different than the default spec/**{,/*/**}/*_spec.rb for RSpec::Core::RakeTask (specifically ** versus **{,/*/**}; I assume this is related to the first question)?


Solution

  • 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.