Skip to main content

fallow_cli/health_types/
coverage.rs

1use std::path::PathBuf;
2
3/// Runtime code that no test dependency path reaches.
4#[derive(Debug, Clone, serde::Serialize)]
5pub struct UntestedFile {
6    /// Absolute file path.
7    pub path: PathBuf,
8    /// Number of value exports declared by the file.
9    pub value_export_count: usize,
10}
11
12/// Runtime export that no test-reachable module references.
13#[derive(Debug, Clone, serde::Serialize)]
14pub struct UntestedExport {
15    /// Absolute file path.
16    pub path: PathBuf,
17    /// Export name.
18    pub export_name: String,
19    /// 1-based source line.
20    pub line: u32,
21    /// 0-based source column.
22    pub col: u32,
23}
24
25/// Aggregate coverage-gap counters for the current analysis scope.
26#[derive(Debug, Clone, Default, serde::Serialize)]
27pub struct CoverageGapSummary {
28    /// Runtime-reachable files in scope.
29    pub runtime_files: usize,
30    /// Runtime-reachable files also reachable from tests.
31    pub covered_files: usize,
32    /// Percentage of runtime files that are test-reachable.
33    pub file_coverage_pct: f64,
34    /// Runtime files with no test dependency path.
35    pub untested_files: usize,
36    /// Runtime exports with no test-reachable reference chain.
37    pub untested_exports: usize,
38}
39
40/// Static test coverage gaps derived from the module graph.
41#[derive(Debug, Clone, Default, serde::Serialize)]
42pub struct CoverageGaps {
43    /// Summary metrics for the current analysis scope.
44    pub summary: CoverageGapSummary,
45    /// Runtime files with no test dependency path.
46    #[serde(skip_serializing_if = "Vec::is_empty")]
47    pub files: Vec<UntestedFile>,
48    /// Runtime exports with no test-reachable reference chain.
49    #[serde(skip_serializing_if = "Vec::is_empty")]
50    pub exports: Vec<UntestedExport>,
51}
52
53impl CoverageGaps {
54    #[must_use]
55    pub fn is_empty(&self) -> bool {
56        self.files.is_empty() && self.exports.is_empty()
57    }
58}