Accept JSON mapping for test_file_finder
Proposal:
Add feature to accept json
based mapping in test_file_finder
alongside existing yaml
mapping.
Problem to solve
For very large projects mapping individual test files to source files can result in a VERY large yaml file which is difficult to maintain and read. Developers want an easier to way to maintain a map test and source files so they can benefit from tff
and get feedback for failures faster.
Rationale
In gitlab-org/gitlab
project, we are generating test mapping dynamically based on test coverage. A proof-of-concept MR can be found in gitlab-org/gitlab!44968 (merged). We intend to use this JSON mapping with tff
to determine the tests that need to be run for a given MR change.
A contrived example of such mapping:
{
"app/models/user.rb": [
"spec/models/user_spec.rb",
"spec/models/project_spec.rb",
"spec/controllers/users_controller_spec.rb"
],
"app/controllers/users_controller_spec.rb": [
"spec/controllers/users_controller_spec.rb"
]
}
The format of tff
's existing yaml mapping is suitable for specifying mapping based on known patterns. This format is less ideal for a very granular mapping that matches exact files to exact test files, where the list of test files can be very lengthy. For example, in gitlab-org/gitlab
, the file app/models/user.rb
is used in 5038 test files.
To convert a dynamically generated mapping into the yaml format, we'd need to specify a pair of file for each test file. With the size of the GitLab code base, this would make the yaml file significantly large.
Using json
to store the mapping data is more appropriate as it removes the keywords used in the yaml
mapping and reduces verbosity. In the case of json
, we are matching files and tests one-to-many, so readability of the file is less of a concern.
Example use case:
Given a json
mapping of a file to its tests:
{
"app/models/user.rb": [
"spec/models/user_spec.rb",
"spec/models/project_spec.rb",
"spec/controllers/users_controller_spec.rb"
],
"app/controllers/users_controller_spec.rb": [
"spec/controllers/users_controller_spec.rb"
]
}
When tff
is called with the json mapping and a list of source files
$ tff --json mapping.json app/models/user.rb app/controllers/users_controller_spec.rb
Then tff
prints the test files corresponding to the source files
spec/models/user_spec.rb spec/models/project_spec.rb spec/controllers/users_controller_spec.rb
Acceptance criteria
json
mapping
Given only a Given a json
mapping of a file to its tests:
{
"app/models/user.rb": [
"spec/models/user_spec.rb",
"spec/models/project_spec.rb",
"spec/controllers/users_controller_spec.rb"
],
"app/controllers/users_controller_spec.rb": [
"spec/controllers/users_controller_spec.rb"
]
}
When tff
is called with the json mapping and a list of source files
$ tff --json mapping.json app/models/user.rb app/controllers/users_controller_spec.rb
Then tff
prints the test files corresponding to the source files
spec/models/user_spec.rb spec/models/project_spec.rb spec/controllers/users_controller_spec.rb
json
and a yaml
mapping
Given both a Given a json
mapping of a file to its tests:
{
"app/models/user.rb": [
"spec/models/user_spec.rb",
"spec/models/project_spec.rb",
"spec/controllers/users_controller_spec.rb"
],
"app/controllers/users_controller_spec.rb": [
"spec/controllers/users_controller_spec.rb"
]
}
And a yaml
mapping:
mapping:
- source: app/models/(.+)\.rb
test: spec/models/%s_spec.rb
When tff
is called with both mappings and a list of source files
$ tff -f mapping.yaml --json mapping.json app/models/user.rb app/models/project.rb
Then tff
prints the test files corresponding to the source files based on both mappings
spec/models/user_spec.rb spec/models/project_spec.rb spec/controllers/users_controller_spec.rb spec/models/project_spec.rb