test_file_finder 0.0.1 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: