module RSpactor # Maps the changed filenames to list of specs to run in the next go. # Assumes Rails-like directory structure class TestInspector EXTENSIONS = %w(rb erb builder haml rhtml rxml yml conf opts) def initialize(dir) @root = dir end def determine_test_files(file) candidates = translate(file) candidates.reject { |candidate| candidate.index('.') }.each do |dir| candidates.reject! { |candidate| candidate.index("#{dir}/") == 0 } end test_files = candidates.select { |candidate| File.exists? candidate } if test_files.empty? $stderr.puts "doesn't exist: #{candidates.inspect}" end test_files end # mappings for Rails are inspired by autotest mappings in rspec-rails def translate(file) file = file.sub(%r:^#{Regexp.escape(@root)}/:, '') candidates = [] if test_file?(file) candidates << file else test_file = append_test_file_extension(file) case file when %r:^app/: if file =~ %r:^app/controllers/application(_controller)?.rb$: candidates << 'controllers' elsif file == 'app/helpers/application_helper.rb' candidates << 'helpers' << 'views' else candidates << test_file.sub('app/', '') if file =~ %r:^app/(views/.+\.[a-z]+)\.[a-z]+$: candidates << append_test_file_extension($1) elsif file =~ %r:app/helpers/(\w+)_helper.rb: candidates << "views/#{$1}" elsif file =~ /_observer.rb$/ candidates << candidates.last.sub('_observer', '') end end when %r:^lib/: candidates << test_file # lib/foo/bar_test.rb -> lib/bar_test.rb candidates << candidates.last.sub($&, '') # lib/bar_test.rb -> bar_test.rb candidates << candidates.last.sub(%r:\w+/:, '') if candidates.last.index('/') when 'config/routes.rb' candidates << 'controllers' << 'helpers' << 'views' when 'config/database.yml', 'db/schema.rb' candidates << 'models' when %r:^(spec/(spec_helper|shared/.*)|config/(boot|environment(s/test)?))\.rb$: candidates << 'test' else candidates << test_file end end candidates.map do |candidate| if candidate.index('test') == 0 File.join(@root, candidate) else File.join(@root, 'test', candidate) end end end def append_test_file_extension(file) if File.extname(file) == ".rb" file.sub(/.rb$/, "_test.rb") else file + "_test.rb" end end def test_file?(file) file =~ /^test\/.+_test.rb$/ end end end