Bienvenidos sean a este post, hoy hablaremos sobre los tests para nuestro codigo.
Cuando necesitamos hacer un test sobre un codigo este es un simple atributo que se pone para indicar que esto sera un test, un atributo es un porcion de metadata para nuestro codigo por ejemplo:
#[test]
fn sarasa...
Despues simplemente al momento de ejecutarlo en lugar de usar cargo run usaremos a cargo test, el compilador se encargara de crear todo la parte binaria para correr los test, si recuerdan al momento de crear un crate propio vimos como hacer un test sobre el mismo en este post, pero hoy nos centraremos en como trabaja y como nos genera uno por defecto, para ello crearemos una nueva libreria llamada prueba, para ello ejecutaremos el siguiente comando:
$ cargo new prueba --lib
Con nuestra nueva libreria generada pasemos a ver cual es el codigo que se genero automaticamente en nuestro archivo lib.rs ubicado en el directorio src:
lib.rs
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
let result = 2 + 2;
assert_eq!(result, 4);
}
}
Las primeras dos lineas seran para configurar el test, mas adelante hablaremos sobre esto, y la otra es para indicar que este es un modulo, ahora viene lo que nos interesa como es el atributo con el test seguido de una funcion, en esta sumaremos dos valores y lo siguiente sera utilizar a assert_eq para verificar que ambos valores son iguales y del mismo tipo, con esto podemos hacer una prueba basica con cargo test, hagamos esto y veamos como es su salida:
tinchicus@dbn001vrt:~/lenguajes/rust/prueba$ cargo test
Compiling prueba v0.1.0 (/home/tinchicus/lenguajes/rust/prueba)
Finished test [unoptimized + debuginfo] target(s) in 2.75s
Running unittests (target/debug/deps/prueba-e23faeddfadd8fad)
running 1 test
test tests::it_works ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
Doc-tests prueba
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
tinchicus@dbn001vrt:~/lenguajes/rust/prueba$
En este caso observen que primero nos corre el test de la funcion que se encuentra del modulo tests, nos dice que esta ok, lo siguiente es informarnos los siguientes resultados del test:
- pasaron, es decir los exitosos
- fallaron, los que no pasaron
- ignorados, los que fueron marcados para ser ignorados
- medidos, los cuales se usaron para medir el tiempo
- filtrados del test, los cuales fueron omitidos mediante un filtro
Para finalmente decirnos cuanto demoro en realizarse, los siguientes test son los correspondientes a la documentacion pero como no tenemos ninguna documentacion nos informa que no hubo nada, esto es el codigo creado de manera predeterminada y un test basico pero que sucede cuando falla? Bueno, vamos a ver eso mediante la siguiente modificacion:
lib.rs
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
let result = 2 + 2;
assert_eq!(result, 4);
}
#[test]
fn no_funca() {
panic!("Es para que falle!");
}
}
En esta oportunidad agregamos otra funcion que llamara a un panic para que salga del programa y se finalice, observen que volvimos a poner el atributo test sobre esta nueva funcion para que al momento de correr el test sepa que tambien debe verificarla, es decir que por cada funcion que deseemos probar o verificar debemos agregarle el atributo, vamos a correr el test igual que lo hicimos antes para ver su salida:
tinchicus@dbn001vrt:~/lenguajes/rust/prueba$ cargo test
Compiling prueba v0.1.0 (/home/tinchicus/lenguajes/rust/prueba)
Finished test [unoptimized + debuginfo] target(s) in 1.21s
Running unittests (target/debug/deps/prueba-e23faeddfadd8fad)
running 2 tests
test tests::it_works ... ok
test tests::no_funca ... FAILED
failures:
---- tests::no_funca stdout ----
thread 'main' panicked at 'Es para que falle!', src/lib.rs:11:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
failures:
tests::no_funca
test result: FAILED. 1 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
error: test failed, to rerun pass '--lib'
tinchicus@dbn001vrt:~/lenguajes/rust/prueba$
Ahora si fallo y no solo nos notifico cual fue la funcion que fallo sino que nos devuelve cual fue la salida que produjo la falla, nos contabiliza cuantos pasaron, cuantos fallaron y el resto, y como obtuvimos una falla omitio el chequeo de la documentacion, ya con esto tenemos la vista de cuando todo esta bien y corre sin ningun problema y la otra cuando tenemos una falla en nuestro codigo, pero que sucede con las funciones que no tienen el atributo? En ese caso no les correra el test, para verificarlo vamos a eliminar el atributo de la nueva funcion (#[test]) y dejen la funcion, si vuelven a correr el test deberia suceder lo siguiente:
tinchicus@dbn001vrt:~/lenguajes/rust/prueba$ cargo test
warning: function is never used: `no_funca`
--> src/lib.rs:9:5
|
9 | fn no_funca() {
| ^^^^^^^^
|
= note: `#[warn(dead_code)]` on by default
warning: `prueba` (lib test) generated 1 warning
Finished test [unoptimized + debuginfo] target(s) in 0.02s
Running unittests (target/debug/deps/prueba-e23faeddfadd8fad)
running 1 test
test tests::it_works ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
Doc-tests prueba
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
tinchicus@dbn001vrt:~/lenguajes/rust/prueba$
Como pueden ver nos notifica que la funcion no_funca no es utilizada pero si observan solo nos hizo el test sobre la unica funcion, la otra fue ignorada y como dijimos anteriormente solamente deben agregar el atributo para realizar los tests sobre la misma, en los proximos posts nos adentraremos mas en los tests.
En resumen, hoy hemos visto una forma muy basica de un test, la anatomia del mismo, como se configura, como se le asigna el atributo para que el «testeador» sepa cual debe verificar, hemos hecho un par de pruebas para ver tanto como funciona como la falla, espero les haya sido de utilidad sigueme en tumblr, Twitter o Facebook para recibir una notificacion cada vez que subo un nuevo post en este blog, nos vemos en el proximo post.


Donación
Es para mantenimento del sitio, gracias!
$1.50
