test-map 0.3.0 → 0.4.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/CHANGELOG.md +6 -0
- data/README.md +49 -0
- data/lib/test_map/cache.rb +13 -4
- data/lib/test_map/event.rb +48 -0
- data/lib/test_map/file_recorder.rb +3 -2
- data/lib/test_map/plugins/minitest/cache_reporter.rb +53 -0
- data/lib/test_map/plugins/minitest.rb +26 -8
- data/lib/test_map/plugins/rspec/cache_formatter.rb +62 -0
- data/lib/test_map/plugins/rspec.rb +40 -21
- data/lib/test_map/version.rb +1 -1
- data/lib/test_map.rb +1 -0
- metadata +5 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 502e7e183acdd6b0f2576ad014d920a1c00b4233f08cdfaf57243ed4814b1c1b
|
|
4
|
+
data.tar.gz: 4d50c652f8ffa46c485ab2da15c5ddd5da022cd856aac394375679f07ea083b8
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 60480addcb32f9528c65895488190f4a7c01623b437e9818ff81e85f081b4e884e8fc3afb5684b4105b2eb52010ae1f1e182e2fbae0574a690c2404b86af3314
|
|
7
|
+
data.tar.gz: 61ce5a7bb1bd602f018e6e64b141bdfddbf52bbd61c72794796823d04b8b0a225f1748a6d66afe1d0540bfd85e31d34ed3cc3dd9c368ad543a2ecacfe0f898a5
|
data/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,12 @@ All notable changes to this project will be documented in this file.
|
|
|
6
6
|
The format is based on [Keep a Changelog](http://keepachangelog.com/)
|
|
7
7
|
and this project adheres to [Semantic Versioning](http://semver.org/).
|
|
8
8
|
|
|
9
|
+
## 0.4.0 - 2026-03-07
|
|
10
|
+
|
|
11
|
+
Extend reporting and cache handling for minitest and rspec. Add caches at
|
|
12
|
+
processing and profiling events. Optimize execution by reducing excessive
|
|
13
|
+
calls and calculations.
|
|
14
|
+
|
|
9
15
|
## 0.3.0 - 2026-03-01
|
|
10
16
|
|
|
11
17
|
Introduce test cache and remove changes runner. Removed `test:changes` Rake
|
data/README.md
CHANGED
|
@@ -17,6 +17,55 @@ Add test-map to your Gemfile.
|
|
|
17
17
|
$ bundle add test-map
|
|
18
18
|
```
|
|
19
19
|
|
|
20
|
+
Require test-map in your test helper or spec helper.
|
|
21
|
+
|
|
22
|
+
```ruby
|
|
23
|
+
# filename: test/test_helper.rb
|
|
24
|
+
require 'test_map'
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Example Run
|
|
28
|
+
|
|
29
|
+
Running the testsuite, test-map creates a mapping of tests to their code files,
|
|
30
|
+
as well as a test-file result cache. Running the testsuite again, all
|
|
31
|
+
successfully run tests are cached and skipped. Chaning a file, **only tests
|
|
32
|
+
that need to be run are executed**.
|
|
33
|
+
|
|
34
|
+
```sh
|
|
35
|
+
# Running the testsuite for the first time, all tests are executed and mapped
|
|
36
|
+
> be rake
|
|
37
|
+
Run options: --seed 10112
|
|
38
|
+
|
|
39
|
+
# Running:
|
|
40
|
+
|
|
41
|
+
.......................................................
|
|
42
|
+
|
|
43
|
+
Finished in 0.042190s, 1303.6402 runs/s, 1730.2861 assertions/s.
|
|
44
|
+
55 runs, 73 assertions, 0 failures, 0 errors, 0 skips, 0 cached
|
|
45
|
+
|
|
46
|
+
# Running again without changes, all tests are cached and skipped
|
|
47
|
+
> be rake
|
|
48
|
+
Run options: --seed 40581
|
|
49
|
+
|
|
50
|
+
# Running:
|
|
51
|
+
|
|
52
|
+
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|
53
|
+
|
|
54
|
+
Finished in 0.007902s, 6960.1126 runs/s, 0.0000 assertions/s.
|
|
55
|
+
55 runs, 0 assertions, 0 failures, 0 errors, 0 skips, 55 cached
|
|
56
|
+
|
|
57
|
+
# Change a file and rerun the testsuite
|
|
58
|
+
> be rake
|
|
59
|
+
Run options: --seed 47682
|
|
60
|
+
|
|
61
|
+
# Running:
|
|
62
|
+
|
|
63
|
+
CCCCCCCCCC...CCCCCCCCCCCC.....CCCCCCCCCCCCCCCCCCCCCCCCC
|
|
64
|
+
|
|
65
|
+
Finished in 0.014029s, 3920.3764 runs/s, 570.2366 assertions/s.
|
|
66
|
+
55 runs, 8 assertions, 0 failures, 0 errors, 0 skips, 47 cached
|
|
67
|
+
```
|
|
68
|
+
|
|
20
69
|
### Minitest
|
|
21
70
|
|
|
22
71
|
Include test-map in your test helper.
|
data/lib/test_map/cache.rb
CHANGED
|
@@ -12,13 +12,16 @@ module TestMap
|
|
|
12
12
|
@cache_file = cache_file
|
|
13
13
|
@map_file = map_file
|
|
14
14
|
@root = root
|
|
15
|
+
@global_files_changed = nil
|
|
16
|
+
@current_checksums = {}
|
|
17
|
+
@file_exists_cache = {}
|
|
15
18
|
end
|
|
16
19
|
|
|
17
20
|
def fresh?(test_file)
|
|
18
21
|
return false unless cached_checksums
|
|
19
22
|
return false if global_files_changed?
|
|
20
23
|
|
|
21
|
-
files_to_check = [test_file]
|
|
24
|
+
files_to_check = [test_file].concat(source_files_for(test_file))
|
|
22
25
|
files_to_check.all? { |f| file_exist?(f) && current_checksum(f) == cached_checksums[f] }
|
|
23
26
|
end
|
|
24
27
|
|
|
@@ -37,7 +40,9 @@ module TestMap
|
|
|
37
40
|
end
|
|
38
41
|
|
|
39
42
|
def global_files_changed?
|
|
40
|
-
|
|
43
|
+
return @global_files_changed unless @global_files_changed.nil?
|
|
44
|
+
|
|
45
|
+
@global_files_changed = GLOBAL_FILES.any? do |f|
|
|
41
46
|
file_exist?(f) && current_checksum(f) != cached_checksums[f]
|
|
42
47
|
end
|
|
43
48
|
end
|
|
@@ -60,10 +65,14 @@ module TestMap
|
|
|
60
65
|
end
|
|
61
66
|
|
|
62
67
|
def current_checksum(file)
|
|
63
|
-
Digest::SHA256.file(File.join(@root, file)).hexdigest
|
|
68
|
+
@current_checksums[file] ||= Digest::SHA256.file(File.join(@root, file)).hexdigest
|
|
64
69
|
end
|
|
65
70
|
|
|
66
|
-
def file_exist?(file)
|
|
71
|
+
def file_exist?(file)
|
|
72
|
+
return @file_exists_cache[file] if @file_exists_cache.key?(file)
|
|
73
|
+
|
|
74
|
+
@file_exists_cache[file] = File.exist?(File.join(@root, file))
|
|
75
|
+
end
|
|
67
76
|
|
|
68
77
|
def collect_tracked_files(results)
|
|
69
78
|
sources = results.keys
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module TestMap
|
|
4
|
+
# Publish/subscribe event bus. No overhead when no subscribers.
|
|
5
|
+
#
|
|
6
|
+
# Topics use `type.action` format, e.g. `cache.create`, `map.create`.
|
|
7
|
+
#
|
|
8
|
+
# Block form measures elapsed time and passes it to subscribers:
|
|
9
|
+
# Event.publish('cache.create') { write_cache }
|
|
10
|
+
#
|
|
11
|
+
# Fire-and-forget form for simple notifications:
|
|
12
|
+
# Event.publish('cache.found', test_file:)
|
|
13
|
+
module Event
|
|
14
|
+
@subscribers = {}
|
|
15
|
+
|
|
16
|
+
class << self
|
|
17
|
+
def subscribe(topic, &block)
|
|
18
|
+
(@subscribers[topic] ||= []) << block
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def publish(topic, **payload, &block)
|
|
22
|
+
listeners = @subscribers[topic]
|
|
23
|
+
return notify(listeners, topic, **payload) unless block
|
|
24
|
+
return yield unless listeners
|
|
25
|
+
|
|
26
|
+
publish_with_timing(listeners, topic, **payload, &block)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def reset
|
|
30
|
+
@subscribers = {}
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
private
|
|
34
|
+
|
|
35
|
+
def notify(listeners, topic, **payload)
|
|
36
|
+
listeners&.each { |cb| cb.call(topic, **payload) }
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def publish_with_timing(listeners, topic, **payload)
|
|
40
|
+
start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
41
|
+
result = yield
|
|
42
|
+
elapsed = Process.clock_gettime(Process::CLOCK_MONOTONIC) - start
|
|
43
|
+
listeners.each { |cb| cb.call(topic, elapsed:, **payload) }
|
|
44
|
+
result
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -26,8 +26,9 @@ module TestMap
|
|
|
26
26
|
def results
|
|
27
27
|
raise NotTracedError.default unless @trace
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
cwd = "#{Dir.pwd}/"
|
|
30
|
+
@files.filter { _1.start_with? cwd }
|
|
31
|
+
.map { _1.sub(cwd, '') }
|
|
31
32
|
.then { Filter.call _1 }
|
|
32
33
|
end
|
|
33
34
|
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module TestMap
|
|
4
|
+
module Plugins
|
|
5
|
+
module Minitest
|
|
6
|
+
# Reporter that tracks cached test count and appends it to the summary.
|
|
7
|
+
class CacheReporter < ::Minitest::StatisticsReporter
|
|
8
|
+
attr_accessor :cached, :composite
|
|
9
|
+
|
|
10
|
+
def initialize(io = $stdout, options = {}, composite: nil)
|
|
11
|
+
super(io, options)
|
|
12
|
+
self.cached = 0
|
|
13
|
+
self.composite = composite
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def record(result)
|
|
17
|
+
super
|
|
18
|
+
self.cached += 1 if result.failure.is_a?(TestMap::CachedSkip)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def report
|
|
22
|
+
super
|
|
23
|
+
return unless composite
|
|
24
|
+
|
|
25
|
+
summary_reporter = composite.reporters.find { |r| r.is_a?(::Minitest::SummaryReporter) }
|
|
26
|
+
return unless summary_reporter
|
|
27
|
+
|
|
28
|
+
summary_reporter.results.reject! { |r| r.failure.is_a?(TestMap::CachedSkip) }
|
|
29
|
+
summary_reporter.skips -= cached if summary_reporter.skips
|
|
30
|
+
patch_summary(summary_reporter)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
private
|
|
34
|
+
|
|
35
|
+
def patch_summary(summary_reporter)
|
|
36
|
+
cached_count = cached
|
|
37
|
+
original_summary = summary_reporter.method(:summary)
|
|
38
|
+
|
|
39
|
+
summary_reporter.define_singleton_method(:summary) do
|
|
40
|
+
"#{original_summary.call}, #{cached_count} cached"
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
module Minitest # :nodoc:
|
|
49
|
+
def self.plugin_test_map_cache_init(options)
|
|
50
|
+
cache_reporter = TestMap::Plugins::Minitest::CacheReporter.new(options[:io], options, composite: reporter)
|
|
51
|
+
reporter.reporters.unshift(cache_reporter)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
module TestMap
|
|
4
|
+
# CachedSkip is raised to skip tests whose files haven't changed.
|
|
5
|
+
# Subclasses Minitest::Skip so Minitest treats it as a skip, but the
|
|
6
|
+
# custom reporter can distinguish it and show `C` instead of `S`.
|
|
7
|
+
class CachedSkip < Minitest::Skip
|
|
8
|
+
def initialize(msg = 'test-map: cached')
|
|
9
|
+
super
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def result_label
|
|
13
|
+
'Cached'
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
require_relative 'minitest/cache_reporter'
|
|
19
|
+
|
|
3
20
|
module TestMap
|
|
4
21
|
module Plugins
|
|
5
22
|
# Minitest plugin for TestMap.
|
|
@@ -9,6 +26,11 @@ module TestMap
|
|
|
9
26
|
TestMap.suite_passed = true
|
|
10
27
|
|
|
11
28
|
::Minitest.after_run { write_results }
|
|
29
|
+
install_cache_reporter
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def self.install_cache_reporter
|
|
33
|
+
::Minitest.extensions << 'test_map_cache'
|
|
12
34
|
end
|
|
13
35
|
|
|
14
36
|
def self.write_results
|
|
@@ -32,22 +54,18 @@ module TestMap
|
|
|
32
54
|
end
|
|
33
55
|
end
|
|
34
56
|
|
|
35
|
-
def
|
|
57
|
+
def before_setup
|
|
36
58
|
test_file = resolve_test_file
|
|
37
|
-
if test_file && TestMap.cache.fresh?(test_file)
|
|
38
|
-
@_test_map_skipped = true
|
|
39
|
-
skip 'test-map: cached'
|
|
40
|
-
else
|
|
41
|
-
@recorder = FileRecorder.new.tap(&:trace)
|
|
42
|
-
end
|
|
59
|
+
raise TestMap::CachedSkip if test_file && TestMap.cache.fresh?(test_file)
|
|
43
60
|
|
|
61
|
+
@recorder = FileRecorder.new.tap(&:trace)
|
|
44
62
|
super
|
|
45
63
|
end
|
|
46
64
|
|
|
47
65
|
def before_teardown
|
|
48
66
|
super
|
|
49
67
|
|
|
50
|
-
return
|
|
68
|
+
return unless @recorder
|
|
51
69
|
|
|
52
70
|
@recorder.stop
|
|
53
71
|
TestMap.reporter.add @recorder.results
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rspec/core/formatters/progress_formatter'
|
|
4
|
+
|
|
5
|
+
module TestMap
|
|
6
|
+
module Plugins
|
|
7
|
+
module RSpec
|
|
8
|
+
# Formatter that shows `C` for cached tests instead of `*` (pending).
|
|
9
|
+
# Extends ProgressFormatter so it can serve as the default formatter.
|
|
10
|
+
# Adjusts the summary to show cached count and filters cached tests
|
|
11
|
+
# from the pending output.
|
|
12
|
+
class CacheFormatter < ::RSpec::Core::Formatters::ProgressFormatter
|
|
13
|
+
CACHED_MESSAGE = 'test-map: cached'
|
|
14
|
+
|
|
15
|
+
::RSpec::Core::Formatters.register self,
|
|
16
|
+
:example_passed, :example_pending, :example_failed,
|
|
17
|
+
:start_dump, :dump_summary, :dump_pending
|
|
18
|
+
|
|
19
|
+
def initialize(output)
|
|
20
|
+
super
|
|
21
|
+
@cached_count = 0
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def example_pending(notification)
|
|
25
|
+
if cached?(notification.example)
|
|
26
|
+
@cached_count += 1
|
|
27
|
+
output.print ::RSpec::Core::Formatters::ConsoleCodes.wrap('c', :cyan)
|
|
28
|
+
else
|
|
29
|
+
super
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def dump_pending(notification)
|
|
34
|
+
examples = notification.pending_examples
|
|
35
|
+
cached = examples.select { |ex| cached?(ex) }
|
|
36
|
+
return if examples.size == cached.size
|
|
37
|
+
|
|
38
|
+
cached.each { |ex| examples.delete(ex) }
|
|
39
|
+
super
|
|
40
|
+
cached.each { |ex| examples.push(ex) }
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def dump_summary(summary)
|
|
44
|
+
if @cached_count.positive?
|
|
45
|
+
cached_count = @cached_count
|
|
46
|
+
original_totals_line = summary.method(:totals_line)
|
|
47
|
+
summary.define_singleton_method(:totals_line) do
|
|
48
|
+
"#{original_totals_line.call}, #{cached_count} cached"
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
super
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
private
|
|
55
|
+
|
|
56
|
+
def cached?(example)
|
|
57
|
+
example.execution_result.pending_message == CACHED_MESSAGE
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
@@ -1,14 +1,49 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative 'rspec/cache_formatter'
|
|
4
|
+
|
|
3
5
|
TestMap.logger.info 'Loading RSpec plugin'
|
|
4
6
|
TestMap.suite_passed = true
|
|
5
7
|
|
|
8
|
+
module TestMap
|
|
9
|
+
module Plugins
|
|
10
|
+
# RSpec integration for TestMap.
|
|
11
|
+
module RSpec
|
|
12
|
+
def self.write_results
|
|
13
|
+
out_file = "#{Dir.pwd}/#{Config.config[:out_file]}"
|
|
14
|
+
reporter_results = TestMap.reporter.results
|
|
15
|
+
|
|
16
|
+
# All tests were cache-skipped, existing files are still valid
|
|
17
|
+
return if reporter_results.empty?
|
|
18
|
+
|
|
19
|
+
full_results = merge_results(out_file, reporter_results)
|
|
20
|
+
File.write(out_file, full_results.to_yaml)
|
|
21
|
+
TestMap.cache.write(full_results) if TestMap.suite_passed
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Merge with existing map to preserve mappings for cache-skipped tests
|
|
25
|
+
def self.merge_results(out_file, reporter_results)
|
|
26
|
+
if File.exist?(out_file)
|
|
27
|
+
TestMap.reporter.merge(reporter_results, YAML.safe_load_file(out_file))
|
|
28
|
+
else
|
|
29
|
+
reporter_results
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
6
36
|
RSpec.configure do |config|
|
|
7
|
-
config.
|
|
8
|
-
test_file = example.metadata[:file_path].sub("#{Dir.pwd}/", '').sub(%r{^\./}, '')
|
|
37
|
+
config.default_formatter = TestMap::Plugins::RSpec::CacheFormatter
|
|
9
38
|
|
|
10
|
-
|
|
11
|
-
|
|
39
|
+
config.before(:context) do
|
|
40
|
+
test_file = self.class.metadata[:file_path].sub("#{Dir.pwd}/", '').sub(%r{^\./}, '')
|
|
41
|
+
skip TestMap::Plugins::RSpec::CacheFormatter::CACHED_MESSAGE if TestMap.cache.fresh?(test_file)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
config.around(:example) do |example|
|
|
45
|
+
if example.metadata[:skip]
|
|
46
|
+
example.run
|
|
12
47
|
else
|
|
13
48
|
recorder = TestMap::FileRecorder.new
|
|
14
49
|
recorder.trace { example.run }
|
|
@@ -18,21 +53,5 @@ RSpec.configure do |config|
|
|
|
18
53
|
end
|
|
19
54
|
end
|
|
20
55
|
|
|
21
|
-
config.after(:suite)
|
|
22
|
-
out_file = "#{Dir.pwd}/#{TestMap::Config.config[:out_file]}"
|
|
23
|
-
reporter_results = TestMap.reporter.results
|
|
24
|
-
|
|
25
|
-
# All tests were cache-skipped, existing files are still valid
|
|
26
|
-
next if reporter_results.empty?
|
|
27
|
-
|
|
28
|
-
# Merge with existing map to preserve mappings for cache-skipped tests
|
|
29
|
-
full_results = if File.exist?(out_file)
|
|
30
|
-
TestMap.reporter.merge(reporter_results, YAML.safe_load_file(out_file))
|
|
31
|
-
else
|
|
32
|
-
reporter_results
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
File.write(out_file, full_results.to_yaml)
|
|
36
|
-
TestMap.cache.write(full_results) if TestMap.suite_passed
|
|
37
|
-
end
|
|
56
|
+
config.after(:suite) { TestMap::Plugins::RSpec.write_results }
|
|
38
57
|
end
|
data/lib/test_map/version.rb
CHANGED
data/lib/test_map.rb
CHANGED
|
@@ -9,6 +9,7 @@ require_relative 'test_map/file_recorder'
|
|
|
9
9
|
require_relative 'test_map/natural_mapping'
|
|
10
10
|
require_relative 'test_map/mapping'
|
|
11
11
|
require_relative 'test_map/cache'
|
|
12
|
+
require_relative 'test_map/event'
|
|
12
13
|
|
|
13
14
|
# TestMap records associated files to test execution.
|
|
14
15
|
module TestMap
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: test-map
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Christoph Lipautz
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-03-
|
|
11
|
+
date: 2026-03-07 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description: |
|
|
14
14
|
Track files that are covered by test files to execute only the necessary
|
|
@@ -28,12 +28,15 @@ files:
|
|
|
28
28
|
- lib/test_map/cache.rb
|
|
29
29
|
- lib/test_map/config.rb
|
|
30
30
|
- lib/test_map/errors.rb
|
|
31
|
+
- lib/test_map/event.rb
|
|
31
32
|
- lib/test_map/file_recorder.rb
|
|
32
33
|
- lib/test_map/filter.rb
|
|
33
34
|
- lib/test_map/mapping.rb
|
|
34
35
|
- lib/test_map/natural_mapping.rb
|
|
35
36
|
- lib/test_map/plugins/minitest.rb
|
|
37
|
+
- lib/test_map/plugins/minitest/cache_reporter.rb
|
|
36
38
|
- lib/test_map/plugins/rspec.rb
|
|
39
|
+
- lib/test_map/plugins/rspec/cache_formatter.rb
|
|
37
40
|
- lib/test_map/report.rb
|
|
38
41
|
- lib/test_map/version.rb
|
|
39
42
|
homepage: https://github.com/unused/test-map
|