00
:
00
:
00
:
00
•Corso SEO AI - Usa SEOEMAIL al checkout per il 30% di sconto

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.