← Índice

1.11 La primera prueba

Esta traducción fue asistida por IA y revisada superficialmente. Si encuentras errores o algo no suena natural, escríbeme — lo agradezco.

Hacer y verificar no son lo mismo. Un artesano que acaba de terminar una pieza sabe una cosa: parece terminada. Si realmente lo está es otra pregunta, y la respuesta no se ve a simple vista. La tarea puede crearse, completarse y responder una pregunta sobre su estado. La fe es cómoda: no requiere herramientas y funciona al instante. El coste de la comodidad aparece exactamente cuando todo empieza a salir mal.

Lo que necesitas

make ci comprueba la forma: formato sin quejas, clippy sin advertencias. No pregunta por el comportamiento. El código que parece correcto puede comportarse incorrectamente - la puerta no lo notará.

Se necesita una forma de hacer preguntas sobre el comportamiento y exigir respuestas en cada ejecución.

La construcción

Los tests viven en un bloque especial al final del archivo:

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

#[cfg(test)] es un atributo de configuración: este bloque se compila solo al ejecutar cargo test. No acaba en una compilación normal. use super::* trae los tipos del archivo padre al ámbito - sin él, Task y Status son desconocidos dentro del bloque.

Un test es una función ordinaria con el atributo #[test]. El nombre describe el comportamiento que se comprueba, no el método:

#[test]
fn new_task_starts_as_todo() {
    let task = Task::new(1, "Buy coffee");
    assert!(!task.is_done());
}

assert! comprueba una condición: si es falsa, el test falla. Añade un segundo test:

#[test]
fn complete_marks_task_done() {
    let mut task = Task::new(1, "Buy coffee");
    task.complete();
    assert!(task.is_done());
}

Cuando hay que comparar dos valores, assert_eq! mostrará ambos si falla:

#[test]
fn task_id_is_preserved() {
    let task = Task::new(42, "Buy coffee");
    assert_eq!(task.id, 42);
}

assert_eq!(left, right) - si left != right, el test falla e imprime ambos valores. assert! no hace esto: solo sabe “falso.”

El resultado

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

    #[test]
    fn new_task_starts_as_todo() {
        let task = Task::new(1, "Buy coffee");
        assert!(!task.is_done());
    }

    #[test]
    fn complete_marks_task_done() {
        let mut task = Task::new(1, "Buy coffee");
        task.complete();
        assert!(task.is_done());
    }

    #[test]
    fn task_id_is_preserved() {
        let task = Task::new(42, "Buy coffee");
        assert_eq!(task.id, 42);
    }
}
running 3 tests
test tests::complete_marks_task_done ... ok
test tests::new_task_starts_as_todo ... ok
test tests::task_id_is_preserved ... ok

test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

make ci pasa. La puerta ahora pregunta por el comportamiento, no solo por la forma.

El código completo de tq para este capítulo está en 1-a-task/11-the-first-proof/.


Lore: Lo que no se prueba

Los tests comprueban el comportamiento a través de valores de retorno y estado. list devuelve () y solo imprime - para verificar su salida habría que capturar stdout. Es posible, pero las herramientas para ello aparecen más adelante.