Anuncios

Bienvenidos sean a este post, hoy veremos las distintas formas de correr un test.

Anuncios

Hasta ahora hemos visto como es la anatomia de un test, algunas macros y atributos para poder escribir nuestros test y ver si funcionan o no dependiendo de lo que vamos a verificar, en todos los casos usamos el siguiente comando:

$ cargo test
Anuncios

Pero podemos utilizar mas opciones y para ello debemos hacerlo de la siguiente forma:

$ cargo test -- opciones
Anuncios

Para entender este concepto y otros vamos a aplicar en un pequeño ejemplo, para ello tomaremos el codigo generado en el post anterior, en caso de no tenerlo simplemente generen una nueva libreria llamada invitados, y en este modificaremos el codigo del archivo lib.rs de la siguiente manera:

lib.rs

pub struct Invitado {
	valor: u32,
}

impl Invitado
{
	pub fn nuevo(valor: u32) -> Invitado {
		if valor < 20
		{
			panic!("El id debe ser mayor a 20, pasaste {}", valor);
		} else if valor > 70 {
			panic!("El id debe ser menor a 70, pasaste {}", valor);
		}		
                println!("El id es {}", valor);
		Invitado { valor }
	}
}

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

	#[test]
	fn crear_invitado()
	{
		Invitado::nuevo(40);
	}

	#[test]
	fn crear_mal_invitado()
	{
		Invitado::nuevo(10);
	}
}
Anuncios
Anuncios

Aqui tenemos un codigo que genera un id de invitado para una empresa X, en este caso tenemos un simple struct para el invitado, una implementacion que genera el nuevo invitado, en caso de que el id no este entre los valores 20 y 70 llamara a panic con dos mensajes distintos, uno para el caso de que sea menor a 20 y otro para mayor a 70, en este caso a diferencia del post anterior mostraremos el valor del id por medio de un println (ya veremos porque) y si paso los condicionales genera un objeto y lo devuelve, despues tendremos en el mod dos funciones para hacer testing, en la prmera se creara un invitado de manera correcta y en el segundo no, vamos a realizar el primer test pero con la siguiente variante:

$ cargo test -- --test-threads=1
Anuncios

Observen como utilizamos la sintaxis anteriormente descriptas, en este caso usamos una opcion para indicar que utilice un solo thread para hacer el test, esto hara que sea mas lento pero sera mas seguro, el resultado sera como cualquier otro test que hemos hecho hasta ahora:

tinchicus@dbn001vrt:~/lenguajes/rust/invitados$ cargo test -- --test-threads=1
warning: field is never read: `valor`
 --> src/lib.rs:2:2
  |
2 |     valor: u32,
  |     ^^^^^^^^^^
  |
  = note: `#[warn(dead_code)]` on by default

warning: `invitados` (lib) generated 1 warning
warning: `invitados` (lib test) generated 1 warning (1 duplicate)
    Finished test [unoptimized + debuginfo] target(s) in 0.02s
     Running unittests (target/debug/deps/invitados-06ae58bb5146574f)

running 2 tests
test tests::crear_invitado ... ok
test tests::crear_mal_invitado ... FAILED

failures:

---- tests::crear_mal_invitado stdout ----
thread 'main' panicked at 'El id debe ser mayor a 20, pasaste 10', src/lib.rs:10:13
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace


failures:
    tests::crear_mal_invitado

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/invitados$
Anuncios

Hasta aca nada del otro mundo, el aviso de que no usamos a la propiedad en ningun momento, la funcion que paso Ok y la falla de la funcion que no iba a funcionar, pero si observan no nos mostro la llamada al println, pero si nosotros necesitamos ver esto podemos usar una opcion para que no capture esto y lo muestre, para ello debemos correr el test con la siguiente opcion:

$ cargo test -- --nocapture
Anuncios

Tal como dijimos siempre usamos la misma sintaxis inicial y luego le agregamos el nocapture, con esto probemos de correr el test con esta nueva opcion y veamos que sucede:

    Finished test [unoptimized + debuginfo] target(s) in 0.02s
     Running unittests (target/debug/deps/invitados-06ae58bb5146574f)

running 2 tests
test tests::crear_invitado ... El id es 40
ok
test tests::crear_mal_invitado ... thread 'main' panicked at 'El id debe ser mayor a 20, pasaste 10', src/lib.rs:10:13
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
FAILED

failures:

failures:
    tests::crear_mal_invitado

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/invitados$ 
Anuncios

Observemos el primer detalle, el test que funciona correctamente llego a mostrar el valor que asignamos como id, en el segundo caso no porque entra en panico y sale del test pero tenganlo en cuenta que nos puede servir para hacer una depuracion, dado que si queremos saber que esta haciendo durante el test o ver los distintos valores que maneja podemos usar varios println mostrando lo que necesitemos y por medio de nocapture lo veremos en la salida del test.

Anuncios

Hasta ahora siempre que corrimos un test nos lo hacia en todas las funciones que agregamos el atributo test pero en algunas ocasiones no necesitaremos analizar todas las funciones sino simplemente la que falla o alguna en particular, para ello simplemente debemos pasar la funcion que deseamos chequear, veamos un ejemplo:

$ cargo test crear_invitado
Anuncios

Si lo corremos veremos la sigueinte salida:

    Finished test [unoptimized + debuginfo] target(s) in 0.02s

     Running unittests (target/debug/deps/invitados-06ae58bb5146574f)

running 1 test
test tests::crear_invitado ... ok

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

tinchicus@dbn001vrt:~/lenguajes/rust/invitados$
Anuncios

Como podemos ver el test corrio exitosamente dado que ahora no hicimos el test sobre la funcion que falla sino solamente sobre la unica que hace lo que debe hacer, observen que nos comenta que dejo uno filtrado (filtered out), si hubiera mas funciones figurarian ahi, pero tambien podemos filtrar por solo una porcion del nombre, por ejemplo:

$ cargo test mal
Anuncios

En este caso no tenemos una funcion que se llame mal pero si una que posee esta palabra, cargo entiende que debe procesar todas las funciones que posean esta palabra, por lo tanto tendremos una salida como la siguiente:

    Finished test [unoptimized + debuginfo] target(s) in 0.01s
     Running unittests (target/debug/deps/invitados-06ae58bb5146574f)

running 1 test
test tests::crear_mal_invitado ... FAILED

failures:

---- tests::crear_mal_invitado stdout ----
thread 'main' panicked at 'El id debe ser mayor a 20, pasaste 10', src/lib.rs:10:13
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace


failures:
    tests::crear_mal_invitado

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

error: test failed, to rerun pass '--lib'
tinchicus@dbn001vrt:~/lenguajes/rust/invitados$
Anuncios

En esta salida proceso a la funcion que falla y por lo tanto fallo el test y observen que volvio a filtrar una funcion, con esto ya casi tenemos todo pero nos falta un atributo mas.

Anuncios

Este atributo es ignore y como su nombre lo indica es para ignorar un test, esta pensado para cuando ya sabemos que determinados test pasan sin problemas y no necesitamos correrlo pero no queremos quitar la etiqueta porque mas adelante puede que necesitemos correrlo nuevamente, aqui entra este atributo en accion, vamos a modificar la funcion que falla de la siguiente forma:

        #[test]
        #[ignore]
        fn crear_mal_invitado()
        {
                Invitado::nuevo(10);
        }
Anuncios

Simplemente agregaremos el atributo despues del test, con esto solo ya el compilador se encargara de ignorarlo al momento de correr el test, corramos el test para ver como funciona:

    Finished test [unoptimized + debuginfo] target(s) in 1.20s
     Running unittests (target/debug/deps/invitados-06ae58bb5146574f)

running 2 tests
test tests::crear_invitado ... ok
test tests::crear_mal_invitado ... ignored

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

   Doc-tests invitados

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/invitados$
Anuncios
Nota:
Para correr este test simplemente corran a cargo test como siempre.
Anuncios

Observen que el primero paso Ok y el segundo fue … ignored, tal como esperabamos pero vemos que no tuvimos ninguna falla sino solamente el pasado y el ignorado, con esto y tenemos una buena base para poder correr nuestros test de manera mas especifica, ya sea para correrlos en uno o varios threads, asi como que nos muestre algun mensaje que hayamos agregado, tambien como filtrar una o varias funciones asi como la posibilidad de ignorarlo.

Anuncios

En resumen, hoy hemos visto como correr un test con varias opciones, hemos visto las distintas opciones que disponemos para poder moldear la salida a nuestra necesidad, hemos visto algunas opciones como tambien atributos para formatear la salida, 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.

Anuncios
pp258

Donación

Es para mantenimento del sitio, gracias!

$1.50