use std::process::Command;
fn cargo_command() -> Command {
Command::new("cargo")
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum TestRunner {
CargoTest,
Nextest,
}
impl TestRunner {
pub fn name(&self) -> &str {
match self {
Self::CargoTest => "cargo test",
Self::Nextest => "cargo nextest",
}
}
pub fn is_available(&self) -> bool {
match self {
Self::CargoTest => true, Self::Nextest => cargo_command()
.arg("nextest")
.arg("--version")
.output()
.map(|o| o.status.success())
.unwrap_or(false),
}
}
pub fn build_command(&self, packages: &[String], args: &[String]) -> Command {
let mut cmd = cargo_command();
match self {
Self::CargoTest => {
cmd.arg("test");
for pkg in packages {
cmd.arg("-p").arg(pkg);
}
if !args.is_empty() {
cmd.arg("--");
cmd.args(args);
}
}
Self::Nextest => {
cmd.arg("nextest").arg("run");
for pkg in packages {
cmd.arg("-p").arg(pkg);
}
cmd.args(args);
}
}
cmd
}
}
pub fn select_runner(prefer_nextest: bool) -> TestRunner {
if prefer_nextest && TestRunner::Nextest.is_available() {
TestRunner::Nextest
} else {
TestRunner::CargoTest
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_cargo_test_runner_always_available() {
let runner = TestRunner::CargoTest;
assert!(runner.is_available());
assert_eq!(runner.name(), "cargo test");
}
#[test]
fn test_cargo_test_command_building() {
let runner = TestRunner::CargoTest;
let packages = vec!["crate-a".to_string(), "crate-b".to_string()];
let args = vec!["--nocapture".to_string()];
let cmd = runner.build_command(&packages, &args);
let cmd_str = format!("{:?}", cmd);
assert!(cmd_str.contains("cargo"));
assert!(cmd_str.contains("test"));
}
#[test]
fn test_nextest_runner_name() {
let runner = TestRunner::Nextest;
assert_eq!(runner.name(), "cargo nextest");
}
#[test]
fn test_select_runner_fallback() {
let runner = select_runner(false);
assert_eq!(runner, TestRunner::CargoTest);
}
#[test]
fn test_select_runner_with_nextest_preference() {
let runner = select_runner(true);
assert!(
runner == TestRunner::Nextest || runner == TestRunner::CargoTest,
"Runner should be either nextest or cargo test"
);
}
}