¡Bienvenidos de nuevo a Rustaceo.es! Hoy nos enfocaremos en una parte fundamental para garantizar la calidad y fiabilidad de nuestros programas: las pruebas (tests) en Rust. Aprenderemos a escribir pruebas unitarias y de integración, y a usar herramientas para asegurar que nuestro código es robusto y libre de errores.
📁 Introducción a las pruebas en Rust #
Rust tiene soporte nativo para pruebas mediante su herramienta de construcción cargo
. Al ejecutar cargo test
, Rust buscará y ejecutará todas las pruebas definidas en el proyecto.
⚒ Creando pruebas unitarias #
Las pruebas unitarias se centran en comprobar el correcto funcionamiento de funciones y módulos individuales.
Ejemplo: prueba unitaria de una función de daño #
// src/lib.rs
pub fn calcular_dano(ataque: u16, defensa: u16, poder: u16) -> u16 {
((ataque as f32 / defensa as f32) * poder as f32 / 50.0 + 2.0) as u16
}
#[Cfg(test)]
mod tests {
use super::*;
#[test]
fn test_calcular_dano() {
let resultado = calcular_dano(100, 50, 60);
assert_eq!(resultado, 24, "El cálculo de daño es incorrecto.");
}
}
#[cfg(test)]
: Indica que este módulo solo se compila durante las pruebas.#[test]
: Marca la función como una prueba.assert_eq!
: Comprueba que el resultado es el esperado.
⚖️ Aserciones (assertions) comunes #
assert!
: Verifica que una condición sea verdadera.assert_eq!
: Comprueba la igualdad entre valores.assert_ne!
: Comprueba que los valores no sean iguales.assert_matches!
: Verifica que un valor coincida con un patrón.
Ejemplo de varias aserciones: #
#[Test]
fn test_varias_aserciones() {
let nivel = 42;
assert!(nivel > 40, "El nivel es demasiado bajo.");
assert_eq!(nivel, 42, "El nivel no coincide.");
assert_ne!(nivel, 50, "El nivel es incorrecto.");
}
🔧 Pruebas con resultados #
Si una prueba devuelve Result<(), String>
, podemos usar ?
para propagar errores:
#[Test]
fn test_con_resultado() -> Result<(), String> {
let valor = 10;
if valor == 10 {
Ok(())
} else {
Err(String::from("El valor no es 10"))
}
}
⚔️ Pruebas de integración #
Las pruebas de integración validan que módulos o componentes funcionan correctamente juntos. Estas pruebas se colocan en la carpeta tests/
.
Ejemplo: prueba de integración #
// tests/integration_test.rs
use mi_crate::calcular_dano;
#[Test]
fn test_dano_en_batalla() {
let resultado = calcular_dano(120, 60, 80);
assert_eq!(resultado, 34, "Daño inesperado en la batalla.");
}
tests/
: Carpeta especial para pruebas de integración.use mi_crate::
: Importa el crate para probarlo desde fuera.
⌚ Ejecutando pruebas #
- Ejecutar todas las pruebas:
cargo test
- Ejecutar pruebas con nombre específico:
cargo test nombre_prueba
- Ejecutar pruebas con resultados completos:
cargo test -- --nocapture
- Ignorar pruebas temporalmente: Agrega
#[ignore]
.
Ejemplo de prueba ignorada #
#[Test]
#[Ignore]
fn test_lenta() {
std::thread::sleep(std::time::Duration::from_secs(5));
assert_eq!(2 + 2, 4);
}
Ejecuta solo las pruebas no ignoradas:
cargo test
Ejecuta también las pruebas ignoradas:
cargo test -- --ignored
⚛ Cobertura de pruebas #
Para medir la cobertura de pruebas, se puede usar cargo-tarpaulin
:
cargo install cargo-tarpaulin
cargo tarpaulin --out Html
Esto generará un reporte detallado.
📊 Conclusión #
Escribir pruebas es fundamental para garantizar que nuestro código sea confiable. Rust facilita la creación de pruebas unitarias e integración, y proporciona herramientas para cubrir todos los aspectos del desarrollo seguro. Con estas prácticas, tu código será más resistente a errores y más fácil de mantener.
¡Atrapa todos los bugs antes de que aparezcan en producción!