È uscito il Corso Java Completo — usa il coupon JAVA2026 (fino al 30 giugno)

Testing in Rust

Rust ha un framework di testing integrato nel linguaggio. Non servono librerie esterne per scrivere ed eseguire test.

Test Unitari

I test unitari si scrivono nello stesso file del codice, in un modulo tests:

pub fn somma(a: i32, b: i32) -> i32 {
    a + b
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_somma() {
        assert_eq!(somma(2, 3), 5);
    }

    #[test]
    fn test_somma_negativi() {
        assert_eq!(somma(-1, -1), -2);
    }
}

Macro di Asserzione

#[test]
fn test_asserzioni() {
    assert!(true);                                    // Verifica booleano
    assert_eq!(2 + 2, 4);                             // Verifica uguaglianza
    assert_ne!(2 + 2, 5);                             // Verifica disuguaglianza
    assert_eq!(2 + 2, 4, "La somma dovrebbe essere 4"); // Con messaggio
}

Test che Devono Causare Panic

#[test]
#[should_panic]
fn test_divisione_per_zero() {
    dividi(10, 0);
}

#[test]
#[should_panic(expected = "divisione per zero")]
fn test_messaggio_panic() {
    dividi(10, 0); // Verifica anche il messaggio del panic
}

Test con Result

#[test]
fn test_con_result() -> Result<(), String> {
    let risultato = "42".parse::<i32>().map_err(|e| e.to_string())?;
    if risultato == 42 {
        Ok(())
    } else {
        Err(format!("Atteso 42, ottenuto {}", risultato))
    }
}

Eseguire i Test

cargo test                    # Tutti i test
cargo test nome_test          # Test specifico
cargo test test_somma         # Test che contengono "test_somma"
cargo test -- --nocapture     # Mostra println! durante i test
cargo test -- --test-threads=1 # Esegui test in sequenza
cargo test --doc              # Solo doc-test

Ignorare Test

#[test]
#[ignore]
fn test_lento() {
    // Test che richiede molto tempo
    thread::sleep(Duration::from_secs(60));
}
cargo test -- --ignored        # Esegue solo i test ignorati
cargo test -- --include-ignored # Esegue tutti, inclusi gli ignorati

Subtest con Naming

#[test]
fn test_validazione() {
    let casi = vec![
        ("valido@email.com", true),
        ("invalido", false),
        ("", false),
    ];

    for (email, atteso) in casi {
        assert_eq!(
            valida_email(email), atteso,
            "Fallito per email: '{}'", email
        );
    }
}

Test di Integrazione

I test di integrazione vanno nella directory tests/:

progetto/
├── src/
│   └── lib.rs
└── tests/
    └── integrazione.rs
// tests/integrazione.rs
use mio_progetto::somma;

#[test]
fn test_integrazione_somma() {
    assert_eq!(somma(10, 20), 30);
}

Test Coverage

# Con cargo-tarpaulin
cargo install cargo-tarpaulin
cargo tarpaulin

Conclusione

Il framework di testing integrato in Rust rende semplice scrivere test affidabili senza dipendenze esterne. I test unitari vivono accanto al codice che testano grazie a #[cfg(test)], i test di integrazione nella directory tests/, e i doc-test garantiscono che la documentazione rimanga corretta. Esegui cargo test regolarmente per mantenere il codice solido.