test_file_finder 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b01e368369d161afd0766f1ea95a296b16dc8cb5e3f20d5c8e7abf7910e8da0b
4
- data.tar.gz: 442c058ea7d0ad184d5fe31d697cb9f0f3058b1fe09e03717cf8d12bbadaa5cc
3
+ metadata.gz: 6a5db49df6fa89ead1681625678682bc15b2f430c80c029fc12c3b1edd3e302b
4
+ data.tar.gz: 7bf00383d07d235ec18bb745cd9847cbd23ef1af258f0ee38549369e8dba486c
5
5
  SHA512:
6
- metadata.gz: 70f2284e0d24b68b4a426acd9d42c02a4886c64e258282339459ae4df8ae5da73484916f78b3ca774b8619d88666dc40041f6820f306def6fc5f10d70a143033
7
- data.tar.gz: ccfc5613ed9250411a4e2623ddcf650d2a982e7631d0d3bdb12b820278bfa07c7c0f3595424f925bfc78324c54ba1106dd2180e9bf802756c2dc0037172672dc
6
+ metadata.gz: c18f06159878ea39337c9364a1eff56a94f22ff747d9da569a6fa5816fc7a51bc15e0990c00eb7844da9baf29d5f00154ea6b2ce9b5223ba1d96057496ca6f50
7
+ data.tar.gz: 7431cb14b42c17e8d82a96c9a7fd47cf7ad88b26047c9ea5620bbe38b2c5db2c1d9458f2f655ef91f8ae41e64fee69e74ff4e84ba9903785142d9f0351972f7f
data/README.md CHANGED
@@ -42,6 +42,41 @@ You can use it in a script, for example:
42
42
  $ rspec $(tff $(git diff --name-only master..head))
43
43
  ```
44
44
 
45
+ #### Options
46
+
47
+ `TestFileFinder` can be used with an optional mapping file to specify the mapping from a source file to a test file.
48
+
49
+ The mapping file is a yaml file containing to entries to match file patterns to its test files. The patterns may include capturing groups to be used to identify the test file. To refer to a captured value in the test file, use the `%s` placeholder. For example:
50
+
51
+ ```yaml
52
+ mapping:
53
+ # maps `app/file.rb` to `spec/file_spec.rb`
54
+ - source: app/(.+)\.rb
55
+ test: spec/%s_spec.rb
56
+ # maps `db/schema.rb` to `spec/db/schema_spec.rb`
57
+ - source: db/schema.rb
58
+ test: spec/db/schema_spec.rb
59
+ # maps `ee/app/models/ee/user.rb` to `ee/spec/models/user_spec.rb`
60
+ - source: ee/app/(.*/)ee/(.+)\.rb
61
+ test: ee/spec/%s%s_spec.rb
62
+ ```
63
+
64
+ Command line example:
65
+
66
+ ```bash
67
+ $ file_paths="app/models/widget.rb"
68
+ $ tff -f mapping.yml $file_paths
69
+ spec/models/widget_spec.rb
70
+ ```
71
+
72
+ Ruby example:
73
+
74
+ ```ruby
75
+ TestFileFinder::FileFinder.new(paths: file_paths, mapping_file: 'mapping.yml').test_files
76
+ ```
77
+
78
+ An example mapping file is available in `spec/fixtures/mapping.yml`.
79
+
45
80
  ## Development
46
81
 
47
82
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
data/exe/tff CHANGED
@@ -1,4 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
  require 'test_file_finder'
3
3
 
4
- puts TestFileFinder::FileFinder.new(paths: ARGV).test_files
4
+ options = TestFileFinder::OptionParser.parse!(ARGV)
5
+ mapping = TestFileFinder::Mapping.load(options.mapping_file)
6
+ puts TestFileFinder::FileFinder.new(paths: ARGV, mapping: mapping).test_files
@@ -1,6 +1,10 @@
1
- require 'test_file_finder/version'
2
1
  require 'test_file_finder/file_finder'
2
+ require 'test_file_finder/mapping'
3
+ require 'test_file_finder/option_parser'
4
+ require 'test_file_finder/version'
3
5
 
4
6
  module TestFileFinder
5
7
  class Error < StandardError; end
8
+
9
+ InvalidMappingFileError = Class.new(Error)
6
10
  end
@@ -1,47 +1,30 @@
1
- class TestFileFinder::FileFinder
2
-
3
- def initialize(paths: [])
4
- @paths = [paths].flatten
5
- end
6
-
7
- def test_files
8
- search
9
- end
10
-
11
- private
12
-
13
- attr_reader :paths
1
+ module TestFileFinder
2
+ class FileFinder
3
+ def initialize(paths: [], mapping: nil)
4
+ @paths = [paths].flatten
5
+ @mapping = mapping
6
+ end
14
7
 
15
- def search
16
- file_path_guesses.select { |path| File.exist?(path) }
17
- end
8
+ def test_files
9
+ search
10
+ end
18
11
 
19
- def file_path_guesses
20
- paths.map do |path|
21
- guess_test_files_for(path)
22
- end.compact.uniq
23
- end
12
+ private
24
13
 
25
- def context
26
- {
27
- app: %r{^app/(.+)\.rb$},
28
- lib: %r{^lib/(.+)\.rb$},
29
- spec: %r{^spec/(.+)_spec.rb$},
30
- spec_dir: 'spec',
31
- }
32
- end
14
+ attr_reader :paths
33
15
 
34
- def guess_test_files_for(path)
35
- if (match = context[:app]&.match(path))
36
- return "#{context[:spec_dir]}/#{match[1]}_spec.rb"
16
+ def search
17
+ file_path_guesses.select { |path| File.exist?(path) }
37
18
  end
38
19
 
39
- if (match = context[:lib]&.match(path))
40
- return "#{context[:spec_dir]}/lib/#{match[1]}_spec.rb"
20
+ def file_path_guesses
21
+ paths.flat_map do |path|
22
+ guess_test_files_for(path)
23
+ end.compact.uniq
41
24
  end
42
25
 
43
- if context[:spec]&.match(path)
44
- return path
26
+ def guess_test_files_for(path)
27
+ @mapping.match(path)
45
28
  end
46
29
  end
47
30
  end
@@ -0,0 +1,63 @@
1
+ require 'set'
2
+ require 'yaml'
3
+
4
+ module TestFileFinder
5
+ class Mapping
6
+ attr_reader :pattern_matchers
7
+
8
+ def self.load(mapping_file = nil)
9
+ return default_rails_mapping unless mapping_file
10
+
11
+ content = File.read(mapping_file)
12
+ maps = YAML.load(content)['mapping']
13
+
14
+ validate(maps)
15
+
16
+ new do |mapping|
17
+ maps.each do |map|
18
+ source = map['source']
19
+ test = map['test']
20
+ mapping.relate(source, test)
21
+ end
22
+ end
23
+ end
24
+
25
+ def self.validate(maps)
26
+ raise InvalidMappingFileError, 'missing `mapping` in test mapping file' if maps.nil?
27
+ raise InvalidMappingFileError, 'missing `source` or `test` in test mapping file' if maps.any? { |map| incomplete?(map) }
28
+ end
29
+
30
+ def self.incomplete?(map)
31
+ map['source'].nil? || map['test'].nil?
32
+ end
33
+
34
+ def self.default_rails_mapping
35
+ new do |mapping|
36
+ mapping.relate(%r{^app/(.+)\.rb$}, 'spec/%s_spec.rb')
37
+ mapping.relate(%r{^lib/(.+)\.rb$}, 'spec/lib/%s_spec.rb')
38
+ mapping.relate(%r{^spec/(.+)_spec.rb$}, 'spec/%s_spec.rb')
39
+ end
40
+ end
41
+
42
+ def initialize
43
+ @pattern_matchers = Hash.new { |h, k| h[k] = [] }
44
+
45
+ yield self if block_given?
46
+ end
47
+
48
+ def relate(source, test)
49
+ @pattern_matchers[source] << test
50
+ end
51
+
52
+ def match(file)
53
+ @pattern_matchers.each_with_object(Set.new) do |(source, tests), result|
54
+ regexp = %r{^#{source}$}
55
+
56
+ if (match = regexp.match(file))
57
+ test_files = tests.flat_map { |test| test % match.captures }
58
+ result.merge(Array(test_files))
59
+ end
60
+ end.to_a
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,19 @@
1
+ require 'optparse'
2
+
3
+ module TestFileFinder
4
+ Options = Struct.new(:mapping_file)
5
+
6
+ class OptionParser
7
+ def self.parse!(argv)
8
+ Options.new.tap do |options|
9
+ ::OptionParser.new do |opts|
10
+ opts.banner = "Usage: tff [options] [...file_paths]"
11
+
12
+ opts.on('-f', '--mapping-file FILE', String, 'Use a custom test mapping file') do |mapping_file|
13
+ options.mapping_file = mapping_file
14
+ end
15
+ end.parse!(argv)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -1,3 +1,3 @@
1
1
  module TestFileFinder
2
- VERSION = '0.0.1'
2
+ VERSION = '0.1.0'
3
3
  end
@@ -1,4 +1,3 @@
1
-
2
1
  lib = File.expand_path('../lib', __FILE__)
3
2
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
3
  require 'test_file_finder/version'
@@ -6,12 +5,12 @@ require 'test_file_finder/version'
6
5
  Gem::Specification.new do |spec|
7
6
  spec.name = 'test_file_finder'
8
7
  spec.version = TestFileFinder::VERSION
9
- spec.authors = ['drew cimino']
10
- spec.email = ['dscimino@gmail.com']
8
+ spec.authors = ['GitLab']
9
+ spec.email = ['gitlab_rubygems@gitlab.com']
11
10
 
12
11
  spec.summary = %q{Guesses spec file paths given input file paths.}
13
12
  spec.description = %q{A command-line tool for guessing which spec files are relavant to a passed-in set of file paths.}
14
- spec.homepage = 'https://gitlab.com/gitlab-org/ci-cd/test-file-finder'
13
+ spec.homepage = 'https://gitlab.com/gitlab-org/ci-cd/test_file_finder'
15
14
 
16
15
  # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
17
16
  # to allow pushing to a single host or delete this section to allow pushing to any host.
@@ -19,8 +18,8 @@ Gem::Specification.new do |spec|
19
18
  spec.metadata['allowed_push_host'] = 'https://rubygems.org'
20
19
 
21
20
  spec.metadata['homepage_uri'] = spec.homepage
22
- spec.metadata['source_code_uri'] = 'https://gitlab.com/gitlab-org/ci-cd/test-file-finder/-/tree/master'
23
- spec.metadata['changelog_uri'] = 'https://gitlab.com/gitlab-org/ci-cd/test-file-finder/-/blob/master/CHANGELOG.md'
21
+ spec.metadata['source_code_uri'] = 'https://gitlab.com/gitlab-org/ci-cd/test_file_finder'
22
+ spec.metadata['changelog_uri'] = 'https://gitlab.com/gitlab-org/ci-cd/test_file_finder/-/blob/master/CHANGELOG.md'
24
23
  else
25
24
  raise 'RubyGems 2.0 or newer is required to protect against public gem pushes.'
26
25
  end
@@ -0,0 +1,5 @@
1
+ mapping:
2
+ - source: lib/(.+).rb
3
+ test: spec/lib/%s_spec.rb
4
+ - source: spec/spec_helper.rb
5
+ test: spec
@@ -9,8 +9,22 @@ rm $expected
9
9
  if [[ -n $actual && $expected = $actual ]]
10
10
  then
11
11
  echo "Executable verified"
12
- exit 0
13
12
  else
14
13
  echo "Could not verify executable"
15
14
  exit 1
16
15
  fi
16
+
17
+ expected="spec/db/schema_spec.rb"
18
+ mkdir -p "spec/db"
19
+ echo "existing schema specs" >> $expected
20
+
21
+ actual=$( ruby -Ilib exe/tff -f spec/fixtures/mapping.yml db/schema.rb)
22
+ rm $expected
23
+
24
+ if [[ -n $actual && $expected = $actual ]]
25
+ then
26
+ echo "Executable using mapping verified"
27
+ else
28
+ echo "Could not verify executable using mapping"
29
+ exit 1
30
+ fi
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: test_file_finder
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
- - drew cimino
7
+ - GitLab
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-06-11 00:00:00.000000000 Z
11
+ date: 2020-08-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -69,7 +69,7 @@ dependencies:
69
69
  description: A command-line tool for guessing which spec files are relavant to a passed-in
70
70
  set of file paths.
71
71
  email:
72
- - dscimino@gmail.com
72
+ - gitlab_rubygems@gitlab.com
73
73
  executables:
74
74
  - tff
75
75
  extensions: []
@@ -87,16 +87,19 @@ files:
87
87
  - exe/tff
88
88
  - lib/test_file_finder.rb
89
89
  - lib/test_file_finder/file_finder.rb
90
+ - lib/test_file_finder/mapping.rb
91
+ - lib/test_file_finder/option_parser.rb
90
92
  - lib/test_file_finder/version.rb
91
93
  - test_file_finder.gemspec
94
+ - tests.yml
92
95
  - tff_test.sh
93
- homepage: https://gitlab.com/gitlab-org/ci-cd/test-file-finder
96
+ homepage: https://gitlab.com/gitlab-org/ci-cd/test_file_finder
94
97
  licenses: []
95
98
  metadata:
96
99
  allowed_push_host: https://rubygems.org
97
- homepage_uri: https://gitlab.com/gitlab-org/ci-cd/test-file-finder
98
- source_code_uri: https://gitlab.com/gitlab-org/ci-cd/test-file-finder/-/tree/master
99
- changelog_uri: https://gitlab.com/gitlab-org/ci-cd/test-file-finder/-/blob/master/CHANGELOG.md
100
+ homepage_uri: https://gitlab.com/gitlab-org/ci-cd/test_file_finder
101
+ source_code_uri: https://gitlab.com/gitlab-org/ci-cd/test_file_finder
102
+ changelog_uri: https://gitlab.com/gitlab-org/ci-cd/test_file_finder/-/blob/master/CHANGELOG.md
100
103
  post_install_message:
101
104
  rdoc_options: []
102
105
  require_paths: