Render test revisions separately

This commit is contained in:
Jakub Beránek 2025-04-17 17:14:26 +02:00
parent 4b310338f8
commit 1a6e0d52e5
No known key found for this signature in database
GPG key ID: 909CD0D26483516B
2 changed files with 46 additions and 10 deletions

View file

@ -60,19 +60,27 @@ fn gather_test_suites(job_metrics: &HashMap<JobName, JobMetrics>) -> TestSuites
for test in &suite.tests {
let test_name = normalize_test_name(&test.name, &suite_name);
let test_entry = suite_entry
.tests
.entry(test_name.clone())
.or_insert_with(|| Test { name: test_name, passed: vec![], ignored: vec![] });
let (test_name, variant_name) = match test_name.rsplit_once('#') {
Some((name, variant)) => (name.to_string(), variant.to_string()),
None => (test_name, "".to_string()),
};
let test_entry = suite_entry.tests.entry(test_name.clone()).or_insert_with(|| {
Test { name: test_name.clone(), revisions: Default::default() }
});
let variant_entry = test_entry
.revisions
.entry(variant_name)
.or_insert_with(|| TestResults { passed: vec![], ignored: vec![] });
match test.outcome {
TestOutcome::Passed => {
test_entry.passed.push(test_metadata);
variant_entry.passed.push(test_metadata);
}
TestOutcome::Ignored { ignore_reason: _ } => {
test_entry.ignored.push(test_metadata);
variant_entry.ignored.push(test_metadata);
}
TestOutcome::Failed => {
eprintln!("Warning: failed test");
eprintln!("Warning: failed test {test_name}");
}
}
}
@ -158,12 +166,29 @@ struct TestSuite<'a> {
}
#[derive(Debug, serde::Serialize)]
struct Test<'a> {
name: String,
struct TestResults<'a> {
passed: Vec<TestMetadata<'a>>,
ignored: Vec<TestMetadata<'a>>,
}
#[derive(Debug, serde::Serialize)]
struct Test<'a> {
name: String,
revisions: BTreeMap<String, TestResults<'a>>,
}
impl<'a> Test<'a> {
/// If this is a test without revisions, it will have a single entry in `revisions` with
/// an empty string as the revision name.
fn single_test(&self) -> Option<&TestResults<'a>> {
if self.revisions.len() == 1 {
self.revisions.iter().next().take_if(|e| e.0.is_empty()).map(|e| e.1)
} else {
None
}
}
}
#[derive(Clone, Copy, Debug, serde::Serialize)]
struct TestMetadata<'a> {
job: &'a str,

View file

@ -13,7 +13,18 @@
{% if !root_tests.is_empty() %}
<ul>
{% for test in root_tests %}
<li><b>{{ test.name }}</b> ({{ test.passed.len() }} passed, {{ test.ignored.len() }} ignored)</li>
<li>
{% if let Some(result) = test.single_test() %}
<b>{{ test.name }}</b> ({{ result.passed.len() }} passed, {{ result.ignored.len() }} ignored)
{% else %}
<b>{{ test.name }}</b> ({{ test.revisions.len() }} revision{{ test.revisions.len() | pluralize }})
<ul>
{% for (revision, result) in test.revisions %}
<li>#<i>{{ revision }}</i> ({{ result.passed.len() }} passed, {{ result.ignored.len() }} ignored)</li>
{% endfor %}
</ul>
{% endif %}
</li>
{% endfor %}
</ul>
{% endif %}