Tutorial Symfony - Jobeet dia 9 - Pruebas funcionales
Functional Tests
Las pruebas funcionales permiten testear en conjunto una aplicación, desde los request hasta el response pasando por routing y las distintas capas de MVC. Es como testear personalmente cada link cuando añades un cambio a la aplicación.
La diferencia es la misma que en las pruebas unitarias, si lo haces tu pierdes tiempo y con esto garantizas que siempre se hagan las mismas pruebas, tanto en número como variables. Así siempre tendrás el código estable :)
Existe una aplicación llamada Selenium que hace un macro con los tus movimientos por el navegador, no está de más verla en su página oficial.
The sfBrowser class
Para comenzar estas pruebas utilizaremos la clase sfBrowser, que es algo así como un emulador de un navegador en consola, simulando la navegación con los métodos más habituales:
get() Coge una URL
post() Envía una URL
call() Llama a una URL con PUT y DELETE
back() Página anterior en historial
forward() Página siguiente en historial
reload() Recarga la página
click() Pulsa un enlace o botón
select() Seleciona un radiobutton o checkbox
deselect() Deseleciona un radiobutton o checkbox
restart() Reinicia el navegador
Existen otros muchos que puedes consultar en la documentación.
The sfTestFunctional class
Con esto ya podríamos empezar a crear test, entre la clase sfBrowser y lime. pero existe la clase sfTestFunctional que crea una instancia de sfBrowser y tiene muchos test predefinidos.
Por el momento creamos la ruta para los test de la aplicación /test/functional/frontend/ y creamos una prueba para cada uno de nuestros dos módulos... Sorpresa!!! ya están creados, FEEL LIKE A HACKER
La sintaxis es algo extraña porque han usado fluent interface, que es algo así como sobrecargar un objeto con métodos para que sea más legible.
Cada prueba empieza con un with(nombrePrueba)->begin() y termina con end();
The Request Tester
Tiene un conjunto de métodos para probar un sfWebRequest, son bastante básicos por lo que no voy a volver a enumerarlos.
The Response Tester
Igual que el anterior contra un sfWebRespose.
Running Functional Tests
Tenemos el fichero de pruebas con los primeros test, para ver si el routing funciona correctamente, así que lo ejecutamos con:
$ php symfony test:functional frontend categoryActions
Es sencillo, invocas la aplicación y el test (borrando la palabra "test" del final) y ya deberías tener salida, recuerda que la mayoría de los errores que encontrarás con tanto código copypaste serán:
Porque la ruta/fichero no está bien escrito
Porque no has cargado los items en la bd de pruebas
Al menos es lo que me ha pasado a mi :D
Test Data
Cargamos los ficheros, esta vez es más sencillo, creamos nuestra propia clase en /lib/test/JobeetTestFunctional.class.php que hereda de sfTestFunctional.
Aquí me quedé colgado un rato ya que no había puesto el "class".
Writing Functional Tests
Vamos a crear distintos escenarios para la página principal de Jobs, nuestro primero test será comprobar que no lista trabajos expired.
Expired jobs are not listed
Esto es posible mirando si el selector de CSS encuentra la cadena expired en algún contenedor, todo ello con el método checkElement().
Only n jobs are listed for a category
checkElement() es bastante potente, si añadimos un segundo parámetro (integer) permite devolver TRUE si el número de nodos del contenedor CSS coincide.
A category has a link to the category page only if too many jobs
Comprobamos que la categoría Design no tiene botón more jobs y que Programming si que lo tiene.
Jobs are sorted by date
Vamos a hacer una función para comprobar sólo si el primero elemento que recibimos es el que realmente es el primero. Como es una consulta SQL debería ir en el modelo, pero al formar parte de los test lo añadiremos a la clase nueva que hemos hecho en /lib/test, refactorizamos para poder utlizar la función más adelante y pasamos a la siguiente.
Each job on the homepage is clickable
Comprobamos que el primer elemento de Web Developer genera correctamente la URL para que el routing no la cague cuando coja esta información.
Learn by the Example
Aquí nos dejan todo el código anterior para evitar cualquier error al juntar las pruebas, los cambios en resumen son:
CategoryActionsTest: Añadimos 4 test funcionales
JobActionsTest: Pruebas enumeradas y otras nuevas
JobeetTestFunctional.class: Cargamos datos y factorizamos dos querys.
Debugging Functional Tests
Como esto del navegador de texto suena muy bien pero para depurar no muestra suficiente información, podemos usar
$browser->with('response')->debug();
Puedes añadirlo en cualquier bloque respose para que pare la ejecución y nos dé más información sobre lo que está pasando.
Functional Tests Harness
Ejecutamos las pruebas de forma conjunta
./symfony test:functional frontend
A mi me dan error un par de ellas, pero creo que es porque he modificado los elementos de la base de datos así que hago la vista gorda.
Tests Harness
Para rizar el rizo vamos a ejecutar las pruebas unitarias y funcionales juntas, sólo hay que hacer un
$ php symfony test:all
Si estás depurando un programa porque varios test hayan fallado, no hace falta que ejecutes todos desde el principio, tienes un parámetro que se acuerda de los que han fallado y sólo ejecuta esos.
$ php symfony test:all --only-failed
Final Thoughts
Lime para pruebas unitarias y el framework NONAME de pruebas funcionales te ayudan a mantener estables las aplicaciones a lo largo del tiempo, es bueno diseñar una batería de pruebas para cada desarrollo nuevo, terminas ahorrando bastante tiempo.















