rvtest 0.2.0

A Next Level Testing Library for Rust — BDD specs, property-based testing, parametrized tests, rich reporting, and code coverage
Documentation
//! Integration tests for the `cargo rvtest` CLI.
//!
//! These tests run `cargo rvtest` as a subprocess and verify that the
//! CLI pipeline (argument parsing → test execution → rendering) works
//! end-to-end.
//!
//! Note: `cargo rvtest --coverage` is NOT tested here because it
//! recompiles the entire project with instrumentation (too slow).

use std::process::Command;

/// Run `cargo rvtest` with the given args, return (exit_status, stdout, stderr).
fn rvtest(args: &[&str]) -> (bool, String, String) {
    let output = Command::new("cargo")
        .arg("rvtest")
        .args(args)
        .output()
        .expect("failed to run cargo rvtest");
    let ok = output.status.success();
    let stdout = String::from_utf8_lossy(&output.stdout).into_owned();
    let stderr = String::from_utf8_lossy(&output.stderr).into_owned();
    (ok, stdout, stderr)
}

#[test]
fn cli_help_succeeds() {
    let (ok, stdout, _) = rvtest(&["--help"]);
    assert!(ok, "cargo rvtest --help should exit 0");
    assert!(stdout.contains("rvtest"));
    assert!(stdout.contains("--filter"));
    assert!(stdout.contains("--format"));
}

#[test]
fn cli_filter_nonexistent_is_fast() {
    // Filtering by a name that doesn't exist is fast because cargo
    // finds zero matching tests and exits quickly.
    let (ok, stdout, _) = rvtest(&["-F", "compact", "-f", "NONEXISTENT_TEST_XYZ"]);
    assert!(ok, "filtering nonexistent test should succeed");
    assert!(stdout.contains("0/0"));
}

#[test]
fn cli_format_compact() {
    let (ok, stdout, _) = rvtest(&["-F", "compact"]);
    assert!(ok, "compact format should succeed");
    assert!(
        stdout.contains("passed") || stdout.contains("Results:"),
        "compact output should contain Results line"
    );
}

#[test]
fn cli_format_json() {
    let (ok, stdout, _) = rvtest(&["-F", "json"]);
    assert!(ok, "json format should succeed");
    assert!(stdout.contains(r#""success""#));
}

#[test]
fn cli_format_tap() {
    let (ok, stdout, _) = rvtest(&["-F", "tap"]);
    assert!(ok, "tap format should succeed");
    assert!(stdout.starts_with("1.."), "TAP output should start with 1..N");
}

#[test]
fn cli_format_junit() {
    let (ok, stdout, _) = rvtest(&["-F", "junit"]);
    assert!(ok, "junit format should succeed");
    assert!(stdout.contains("<?xml"));
    assert!(stdout.contains("<testsuites"));
}

#[test]
fn cli_verbose_flag() {
    let (ok, stdout, _) = rvtest(&["-v", "-F", "compact"]);
    assert!(ok, "verbose mode should succeed");
}

#[test]
fn cli_tag_filter() {
    let (ok, stdout, _) = rvtest(&["-F", "compact", "--tag", "spec"]);
    assert!(ok, "tag filter should succeed");
    assert!(stdout.contains("passed") || stdout.contains("Results:"));
}

#[test]
fn cli_exclude_tag() {
    let (ok, stdout, _) = rvtest(&["-F", "compact", "-E", "NONEXISTENT_TAG"]);
    assert!(ok, "exclude tag should succeed");
}

#[test]
fn cli_retries_flag() {
    let (ok, stdout, _) = rvtest(&["-F", "compact", "--retries", "1"]);
    assert!(ok, "retries flag should succeed");
}