Class: Henitai::CoverageBootstrapper
- Inherits:
-
Object
- Object
- Henitai::CoverageBootstrapper
- Defined in:
- lib/henitai/coverage_bootstrapper.rb,
sig/henitai.rbs
Overview
Ensures coverage data exists before the mutation pipeline starts.
Constant Summary collapse
- DEPENDENCY_MANIFEST_FILE =
Sidecar recording which dependency files existed when the coverage artifacts were produced. Deletions drop a path from the current set but leave every surviving file's mtime untouched, so freshness must compare the recorded path set, not just watch existing files.
"henitai_dependency_manifest.json"
Instance Attribute Summary collapse
-
#static_filter ⇒ StaticFilter
readonly
Returns the value of attribute static_filter.
Instance Method Summary collapse
- #bootstrap_coverage(integration, config, test_files = nil) ⇒ void
- #coverage_available?(source_files, config) ⇒ Boolean
-
#coverage_fresh?(source_files, config, test_files) ⇒ Boolean
Returns true when a coverage report already exists, is newer than every watched source and test file, and the dependency path set is unchanged since the report was produced.
- #coverage_report_path(config) ⇒ String
-
#ensure!(source_files:, config:, integration:, test_files: nil) ⇒ void
Runs the test suite to collect coverage, unless a fresh report already exists.
-
#initialize(static_filter: StaticFilter.new) ⇒ CoverageBootstrapper
constructor
A new instance of CoverageBootstrapper.
-
#record_dependency_manifest(config) ⇒ Object
Writes the current dependency path set next to the coverage artifacts.
- #source_file_paths(source_files) ⇒ Array[String]
Constructor Details
#initialize(static_filter: StaticFilter.new) ⇒ CoverageBootstrapper
Returns a new instance of CoverageBootstrapper.
17 18 19 |
# File 'lib/henitai/coverage_bootstrapper.rb', line 17 def initialize(static_filter: StaticFilter.new) @static_filter = static_filter end |
Instance Attribute Details
#static_filter ⇒ StaticFilter (readonly)
Returns the value of attribute static_filter.
58 59 60 |
# File 'lib/henitai/coverage_bootstrapper.rb', line 58 def static_filter @static_filter end |
Instance Method Details
#bootstrap_coverage(integration, config, test_files = nil) ⇒ void
This method returns an undefined value.
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 |
# File 'lib/henitai/coverage_bootstrapper.rb', line 125 def bootstrap_coverage(integration, config, test_files = nil) test_files ||= integration.test_files with_reports_dir(config) do with_coverage_dir(config) do result = integration.run_suite(test_files) if result == :survived record_dependency_manifest(config) return end raise CoverageError, build_bootstrap_error(result) end end end |
#coverage_available?(source_files, config) ⇒ Boolean
60 61 62 63 64 65 |
# File 'lib/henitai/coverage_bootstrapper.rb', line 60 def coverage_available?(source_files, config) coverage_lines = static_filter.coverage_lines_for(config) covered_sources = covered_source_files(source_files, coverage_lines) covered_sources.any? end |
#coverage_fresh?(source_files, config, test_files) ⇒ Boolean
Returns true when a coverage report already exists, is newer than every watched source and test file, and the dependency path set is unchanged since the report was produced. Stale or absent reports return false.
86 87 88 89 90 91 92 |
# File 'lib/henitai/coverage_bootstrapper.rb', line 86 def coverage_fresh?(source_files, config, test_files) watched_files_fresh?( coverage_report_path(config), source_files, test_files ) && dependency_manifest_current?(config) end |
#coverage_report_path(config) ⇒ String
117 118 119 |
# File 'lib/henitai/coverage_bootstrapper.rb', line 117 def coverage_report_path(config) File.join(coverage_dir(config), ".resultset.json") end |
#ensure!(source_files:, config:, integration:, test_files: nil) ⇒ void
This method returns an undefined value.
Runs the test suite to collect coverage, unless a fresh report already exists.
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
# File 'lib/henitai/coverage_bootstrapper.rb', line 36 def ensure!(source_files:, config:, integration:, test_files: nil) return if source_files.empty? resolved_test_files = resolve_test_files(integration, test_files) # Skip the bootstrap only when the coverage artifacts are both newer than # all watched files and actually cover the configured sources. A fresh # but irrelevant report (e.g. from a different working directory) must # still trigger a re-bootstrap rather than silently proceeding with no # usable coverage. unless coverage_ready?(source_files, config, integration, resolved_test_files) bootstrap_coverage(integration, config, resolved_test_files) end return if coverage_available?(source_files, config) raise CoverageError, "Coverage data is unavailable for the configured source files" end |
#record_dependency_manifest(config) ⇒ Object
Writes the current dependency path set next to the coverage artifacts. Called after every bootstrap; exposed so tests can seed a manifest.
23 24 25 26 |
# File 'lib/henitai/coverage_bootstrapper.rb', line 23 def record_dependency_manifest(config) FileUtils.mkdir_p(reports_dir(config)) File.write(dependency_manifest_path(config), JSON.generate(current_dependency_paths)) end |
#source_file_paths(source_files) ⇒ Array[String]
79 80 81 |
# File 'lib/henitai/coverage_bootstrapper.rb', line 79 def source_file_paths(source_files) Array(source_files).map { |path| File.(path) } end |