CI: one test binary per crate, nextest, line tables only (#3855)

* CI: line tables only for workspace crates, no debug info for dependencies

* CI: one integration-test binary per crate

Each crate's tests/*.rs files become modules of tests/it/main.rs. Files that change
process-wide state (Color Settings, the font database, installed plug-ins, the working
directory), the fuzz sweeps and the test targets the Affinity corpus workflow names stay
their own binaries.

* Docs: name the integration tests' new paths

* CI: xtask test with nextest and doctests, one wasm check, clippy --keep-going

cargo xtask ci runs the tests with cargo nextest (cargo test when it is not installed),
builds them with --lib --bins --tests, runs the doctests as their own step, and checks
the wasm crates in one cargo check --keep-going call.
This commit is contained in:
aiongg
2026-10-23 21:36:10 -04:00
committed by GitHub
parent 5037a1ac4b
commit 8cc69ed45c
94 changed files with 235 additions and 197 deletions
+39 -21
View File
@@ -32,7 +32,8 @@ commands:
pdf-deps verify immutable shared PDF writer and patched Krilla sources
layers enforce the crate dependency layering (plan/architecture.md §3)
wasm cargo check --target wasm32-unknown-unknown for the wasm-safe crates and the web app
ci fmt --check, clippy -D warnings, test, no-bundled-fonts, pdf-deps, assets, brands, cursors (warnings only), layers, wasm (stops at first failure)
test the workspace tests (cargo nextest when installed, else cargo test), then the doctests
ci fmt --check, clippy -D warnings, test, doctests, no-bundled-fonts, pdf-deps, assets, brands, cursors (warnings only), layers, wasm (stops at first failure)
corpus [--download] [--affinity]
show where test corpora live; --download fetches PngSuite into corpus/pngsuite,
--affinity the pinned public Affinity documents into corpus/affinity
@@ -55,6 +56,7 @@ fn main() -> ExitCode {
Some("layers") => cmd_layers(),
Some("pdf-deps") => pdf_deps::run(&root()),
Some("wasm") => cmd_wasm(),
Some("test") => cmd_test().and_then(|()| cmd_doctests()),
Some("ci") => cmd_ci(),
Some("corpus") if rest.contains(&"--affinity") => affinity_corpus::fetch(),
Some("corpus") => cmd_corpus(rest.contains(&"--download")),
@@ -204,21 +206,43 @@ fn wasm_set() -> Result<Vec<String>, String> {
.collect())
}
/// One `cargo check` over the whole wasm set: the crates share one build, and `--keep-going`
/// reports every crate that fails rather than only the first.
fn cmd_wasm() -> Result<(), String> {
let set = wasm_set()?;
let mut results = Vec::new();
let mut c = cargo();
c.args(["check", "--target", "wasm32-unknown-unknown", "--keep-going"]);
for pkg in &set {
let mut c = cargo();
c.args(["check", "--target", "wasm32-unknown-unknown", "-p", pkg]);
let ok = run(c, &format!("cargo check --target wasm32-unknown-unknown -p {pkg}")).is_ok();
results.push((pkg.clone(), ok));
c.args(["-p", pkg]);
}
println!("\nwasm32-unknown-unknown check:");
for (p, ok) in &results {
println!(" {:<6} {p}", if *ok { "ok" } else { "FAIL" });
run(c, &format!("cargo check --target wasm32-unknown-unknown --keep-going ({} crates: {})", set.len(), set.join(", ")))
}
/// Whether `cargo nextest` is installed.
fn has_nextest() -> bool {
cargo().args(["nextest", "--version"]).output().is_ok_and(|o| o.status.success())
}
/// The workspace's unit and integration tests, without examples (clippy still checks those).
/// nextest runs each test in its own process, in parallel across all test binaries.
fn cmd_test() -> Result<(), String> {
const TARGETS: [&str; 3] = ["--lib", "--bins", "--tests"];
let mut c = cargo();
if has_nextest() {
c.args(["nextest", "run", "--workspace"]).args(TARGETS);
run(c, "cargo nextest run --workspace --lib --bins --tests")
} else {
eprintln!("note: cargo-nextest is not installed; running cargo test (cargo install cargo-nextest for faster runs)");
c.args(["test", "--workspace"]).args(TARGETS);
run(c, "cargo test --workspace --lib --bins --tests")
}
let failed = results.iter().filter(|r| !r.1).count();
if failed == 0 { Ok(()) } else { Err(format!("{failed} crate(s) failed the wasm check")) }
}
/// The doctests, which nextest doesn't run.
fn cmd_doctests() -> Result<(), String> {
let mut c = cargo();
c.args(["test", "--workspace", "--doc"]);
run(c, "cargo test --workspace --doc")
}
/// `cargo xtask ci`: each step in turn, stopping at the first that fails; the summary names the
@@ -238,18 +262,12 @@ fn cmd_ci() -> Result<(), String> {
"clippy",
Box::new(|| {
let mut c = cargo();
c.args(["clippy", "--workspace", "--all-targets", "--", "-D", "warnings"]);
run(c, "cargo clippy --workspace --all-targets -- -D warnings")
}),
),
(
"test",
Box::new(|| {
let mut c = cargo();
c.args(["test", "--workspace"]);
run(c, "cargo test --workspace")
c.args(["clippy", "--workspace", "--all-targets", "--keep-going", "--", "-D", "warnings"]);
run(c, "cargo clippy --workspace --all-targets --keep-going -- -D warnings")
}),
),
("test", Box::new(cmd_test)),
("doctests", Box::new(cmd_doctests)),
(
"no-bundled-fonts",
Box::new(|| {