Class: FastCov::TestMap
- Inherits:
-
Object
- Object
- FastCov::TestMap
- Defined in:
- lib/fast_cov/test_map.rb,
lib/fast_cov/test_map/reader.rb,
lib/fast_cov/test_map/aggregator.rb
Overview
In-memory test mapping that records which files each test depends on. Can be dumped to a gzipped TSV fragment file for later aggregation.
Usage:
# Accumulate mappings (e.g., in an RSpec formatter)
test_map = FastCov::TestMap.new
test_map.add("spec/models/user_spec.rb" => coverage_result)
test_map.dump("tmp/test_mapping.node_0.gz")
# Query mappings
test_map.dependencies("app/models/user.rb")
# => ["spec/models/user_spec.rb"]
# Aggregate fragments from multiple nodes
aggregator = FastCov::TestMap.aggregate(Dir["tmp/test_mapping.*.gz"])
aggregator.on(:sorted) { |elapsed| puts "Sorted in #{elapsed.round(2)}s" }
aggregator.on(:merged) { |files, elapsed| puts "Merged #{files} files in #{elapsed.round(2)}s" }
aggregator.each(10_000) { |batch| database.bulk_write(batch) }
Defined Under Namespace
Classes: Aggregator, Reader
Constant Summary collapse
- DEFAULT_MAX_READERS =
[100, Process.getrlimit(Process::RLIMIT_NOFILE).first / 2].min
Class Method Summary collapse
-
.aggregate(*patterns, readers: DEFAULT_MAX_READERS) ⇒ Object
Create an Aggregator for merging fragment files.
Instance Method Summary collapse
-
#add(mappings) ⇒ Object
Record test -> dependency mappings.
-
#dependencies(file) ⇒ Object
Returns the test paths that depend on the given file.
-
#dump(path) ⇒ Object
Write the accumulated mappings as a gzipped TSV fragment.
-
#initialize ⇒ TestMap
constructor
A new instance of TestMap.
-
#size ⇒ Object
Number of unique source files mapped.
Constructor Details
#initialize ⇒ TestMap
Returns a new instance of TestMap.
31 32 33 |
# File 'lib/fast_cov/test_map.rb', line 31 def initialize @mapping = {} end |
Class Method Details
.aggregate(*patterns, readers: DEFAULT_MAX_READERS) ⇒ Object
Create an Aggregator for merging fragment files. Accepts file paths or glob patterns.
67 68 69 70 |
# File 'lib/fast_cov/test_map.rb', line 67 def self.aggregate(*patterns, readers: DEFAULT_MAX_READERS) fragment_paths = patterns.flatten.flat_map { |p| p.include?("*") ? Dir.glob(p).sort : p } Aggregator.new(fragment_paths, readers) end |
Instance Method Details
#add(mappings) ⇒ Object
Record test -> dependency mappings. Accepts a Hash of { test_path => dependencies }.
37 38 39 40 41 42 43 44 45 |
# File 'lib/fast_cov/test_map.rb', line 37 def add(mappings) mappings.each do |test_path, deps| deps.each do |dep| next if dep == test_path (@mapping[dep] ||= Set.new) << test_path end end end |
#dependencies(file) ⇒ Object
Returns the test paths that depend on the given file.
48 49 50 |
# File 'lib/fast_cov/test_map.rb', line 48 def dependencies(file) @mapping[file]&.to_a end |
#dump(path) ⇒ Object
Write the accumulated mappings as a gzipped TSV fragment.
53 54 55 56 57 58 |
# File 'lib/fast_cov/test_map.rb', line 53 def dump(path) FileUtils.mkdir_p(File.dirname(path)) lines = @mapping.map { |file, deps| "#{file}\t#{deps.to_a.join("\t")}\n" } Zlib::GzipWriter.open(path) { |gz| gz.write(lines.join) } end |
#size ⇒ Object
Number of unique source files mapped.
61 62 63 |
# File 'lib/fast_cov/test_map.rb', line 61 def size @mapping.size end |