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 +4 -4
- data/README.md +35 -0
- data/exe/tff +3 -1
- data/lib/test_file_finder.rb +5 -1
- data/lib/test_file_finder/file_finder.rb +19 -36
- data/lib/test_file_finder/mapping.rb +63 -0
- data/lib/test_file_finder/option_parser.rb +19 -0
- data/lib/test_file_finder/version.rb +1 -1
- data/test_file_finder.gemspec +5 -6
- data/tests.yml +5 -0
- data/tff_test.sh +15 -1
- metadata +11 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6a5db49df6fa89ead1681625678682bc15b2f430c80c029fc12c3b1edd3e302b
|
4
|
+
data.tar.gz: 7bf00383d07d235ec18bb745cd9847cbd23ef1af258f0ee38549369e8dba486c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
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
|
data/lib/test_file_finder.rb
CHANGED
@@ -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
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
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
|
-
|
16
|
-
|
17
|
-
|
8
|
+
def test_files
|
9
|
+
search
|
10
|
+
end
|
18
11
|
|
19
|
-
|
20
|
-
paths.map do |path|
|
21
|
-
guess_test_files_for(path)
|
22
|
-
end.compact.uniq
|
23
|
-
end
|
12
|
+
private
|
24
13
|
|
25
|
-
|
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
|
-
|
35
|
-
|
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
|
-
|
40
|
-
|
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
|
-
|
44
|
-
|
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
|
data/test_file_finder.gemspec
CHANGED
@@ -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 = ['
|
10
|
-
spec.email = ['
|
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/
|
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/
|
23
|
-
spec.metadata['changelog_uri'] = 'https://gitlab.com/gitlab-org/ci-cd/
|
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
|
data/tests.yml
ADDED
data/tff_test.sh
CHANGED
@@ -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
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
-
|
7
|
+
- GitLab
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
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
|
-
-
|
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/
|
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/
|
98
|
-
source_code_uri: https://gitlab.com/gitlab-org/ci-cd/
|
99
|
-
changelog_uri: https://gitlab.com/gitlab-org/ci-cd/
|
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:
|