[Parte 6] Pruebas: Unitarias y funcionales con PHPUnit

Symfony, Tutoriales

Este post es la parte 6 de 6 del artículo: Creando un Blog con Symfony2

Debido a que la web de udelabs lleva varías semanas sin funcionar a petición de un par de usuarios me tomo la libertad de subir el tutorial traducido por ellos, quizás con alguna modificación que iba haciendo pero todos los méritos son de ellos.Tutorial en inglés 

Descripción

Hasta el momento hemos explorado una buena cantidad de la superficie, hemos visto una serie de conceptos básicos en cuanto al desarrollo con Symfony2. Antes de continuar agregando características es tiempo de presentarte las pruebas. Vamos a ver cómo comprobar distintas funciones con pruebas unitarias y cómo asegurarte de que múltiples componentes están funcionando correctamente, junto con las pruebas funcionales. Cubriremos la manera en que la biblioteca de pruebas PHPUnit de PHPestá en el centro de las pruebas de Symfony2. Debido a que el tema de las pruebas es un muy extenso, también lo trataremos en capítulos posteriores. Al final de este capítulo habrás escrito una serie de pruebas que abarcan tanto pruebas unitarias como funcionales. Tendrás que simular peticiones del navegador, poblar formularios con datos, y evaluar respuestas para verificar que las páginas del sitio se imprimen correctamente. También comprobaremos la cantidad del código base de tu aplicación que está cubierto por las pruebas.

Probando en Symfony2

PHPUnit Se ha convertido en el “estándar de facto” para escribir pruebas en PHP, por lo tanto su aprendizaje te beneficiará en todos tus proyectos PHP. Tampoco olvides que la mayoría de los temas tratados en este capítulo son independientes del lenguaje y por lo tanto los puedes transferir a otros lenguajes

Si estás pensando en escribir tus propios paquetes de código abierto para Symfony2, y si has probado (y documentado) tus paquetes; estos son mucho más propensos a recibir atención e interés por parte de otros programadores. Echa un vistazo a los paquetes de Symfony2 disponibles actualmente enSymfony2Bundles.

Pruebas unitarias

Las pruebas unitarias se encargan de garantizar que unidades individuales de código funcionan correctamente cuando se utilizan de manera aislada. En un código base orientado a objetos tal como lo es Symfony2, una unidad sería una clase y sus métodos. Por ejemplo, podemos escribir pruebas para las clases de las entidades Blog yComentario. Al escribir las pruebas unitarias, los casos de prueba se deben escribir de forma independiente de otros casos de prueba, es decir, el resultado del caso de prueba B no debe depender del resultado del caso de prueba A. Cuando pruebas unidades, es útil poder crear objetos simulados que te permitan probar fácilmente las funciones de unidades que tienen dependencias externas. La imitación te permite simular una llamada a función en lugar de ejecutarla realmente. Un ejemplo de esto serían las pruebas unitarias de una clase que envuelve una API externa. La clase de la API puede utilizar una capa de transporte para comunicarse con la API externa. Podríamos imitar el método de la petición de la capa de transporte para devolver el resultado que especifiquemos, en vez de realmente tocar la API externa. Las pruebas unitarias no prueban que los componentes de una aplicación funcionan correctamente en conjunto, esto lo cubriremos en el siguiente tema, cuando probemos la funcionalidad.

Pruebas funcionales

Las pruebas funcionales verifican la integración de los diferentes componentes dentro de la aplicación, tales como enrutado, controladores y vistas. Las pruebas funcionales son similares a las pruebas manuales que ejecutas en el navegador tal como solicitar una página, hacer clic en un enlace del blog y comprobar que el blog se muestre correctamente. Las pruebas funcionales te ofrecen la posibilidad de automatizar ese proceso. Symfony2 viene con una serie completa de útiles clases que te ayudan en las pruebas funcionales, incluyendo un cliente que es capaz de solicitar páginas, presentar formularios y un rastreador del DOM que podemos utilizar para recorrer la Respuesta desde el cliente.

Hay una serie de procesos para el desarrollo de software que son impulsados ​​por pruebas. Esto incluye procesos tales como Test Driven Development (TDD— “Desarrollo conducido por pruebas”) y Behavioral Driven Development (BDD — “Desarrollo conducido por comportamiento”). Si bien estos están fuera del alcance de esta guía, debes estar consciente de la biblioteca escrita por everzet que facilita el BDD llamada Béhat. También disponemos de un BehatBundlepara Symfony2 que se integra fácilmente en tu proyecto Béhat de Symfony2.

PHPUnit

Como mencionamos anteriormente, las pruebas en Symfony2 se escriben utilizando PHPUnit. Tendrás que instalar PHPUnit y las pruebas de este capítulo, a fin de realizar pruebas. Para ver detalladas instrucciones de instalación ve la documentación oficial en el sitio web de PHPUnit. Para ejecutar las pruebas en Symfony2 es necesario instalar PHPUnit 3.5.11 o posterior. PHPUnit es una biblioteca de pruebas muy grande, por lo tanto haremos referencia a la documentación oficial donde puedas encontrar lectura adicional. Véase el post Instalar PHPUnit en xampp y windows

Aserciones

La escritura de pruebas concierne a la comprobación de que el resultado de la prueba real es igual al resultado esperado de la prueba. Hay disponible una serie de métodos de aserciones para ayudar a PHPUnit en esta tarea. Algunos de los métodos de aserciones comunes que vamos a utilizar son los siguientes:

[codesyntax lang=”php”]

[/codesyntax]

Disponemos de una lista completa de aserciones en la documentación de PHPUnit .

Corriendo las pruebas de Symfony2

Antes de comenzar a escribir algunas pruebas, vamos a ver cómo ejecutar pruebas en Symfony2. Puedes adaptar a PHPUnit para que ejecute las pruebas con un archivo de configuración. En nuestro proyecto de Symfony2 este archivo se encuentra en app/phpunit.xml.dist. Puesto que este archivo tiene el sufijo .dist, tienes que copiar su contenido a un archivo llamado app/phpunit.xml.

Si estás utilizando un VCS como Git, debes añadir el nuevo archivo app/phpunit.xml a la lista de ignorados por el VCS.

Si echas un vistazo al contenido del archivo de configuración de PHPUnit verás lo siguiente:

[codesyntax lang=”xml” title=” app/phpunit.xml”]

[/codesyntax]

Los siguientes ajustes configuran algunos directorios que forman parte de nuestro banco de pruebas. Cuando ejecutas PHPUnit este buscará en los directorios anteriores las pruebas a ejecutar. También puedes pasar argumentos adicionales en la línea de ordenes a PHPUnit para ejecutar pruebas en un directorio específico, en lugar del banco de pruebas. Verás cómo lograr esto más adelante.

También notarás que la configuración se especifica en el archivo de arranque situado en app/bootstrap.php.cachePHPUnit utiliza este archivo para obtener la configuración del entorno de pruebas.

[codesyntax lang=”php”]

[/codesyntax]

Para más información sobre cómo configurar PHPUnit con un archivo XML consulta la documentación de PHPUnit.

Ejecutando las pruebas actuales

Debido a que —en el capítulo 1— utilizamos una de las tareas del generador de Symfony2 para crear el BloggerBlogBundle, esta tarea también creó una prueba para la clase defaultController. Podemos ejecutar esta prueba, ejecuta la siguiente orden desde el directorio raíz del proyecto. La opción -c especifica que PHPUnit debe cargar su configuración desde el directorio app.

$ phpunit -c app

Una vez completada la prueba, serás notificado de que las pruebas fallaron. Si nos fijamos en la clase DefaultControllerTest ubicada ensrc/Blogger/BlogBundle/Tests/Controller/DefaultControllerTest.php verás el siguiente contenido:

[codesyntax lang=”php” title=”src/Blogger/BlogBundle/Tests/Controller/DefaultControllerTest.php”]

[/codesyntax]

Esta es una prueba funcional para la clase defaultController que Symfony2 generó. Si recuerdas, del capítulo 1, el controlador tenía una acción que maneja las peticiones para /hello/{name}. El hecho de que hemos eliminado ese controlador es la razón por la cual está fallando la prueba anterior. Trata de ir a la URLhttp://symblog.dev/app_dev.php/hello/Fabien en tu navegador. Se te debería informar que no se pudo encontrar la ruta. Debido a que la prueba anterior, hace una petición a la misma URL, esta también recibirá la misma respuesta, por lo tanto, esa es la razón por qué falla la prueba. Las pruebas funcionales son una gran parte de este capítulo y se tratarán en detalle más adelante.

Puesto que eliminamos la clase DefaultController, también puedes eliminar esta clase de prueba. Elimina la clase DefaultControllerTest situada ensrc/Blogger/BlogBundle/Tests/Controller/DefaultControllerTest.php.

Pruebas unitarias

Como explicamos anteriormente, las pruebas unitarias se refieren a las pruebas aisladas de unidades individuales de tu aplicación. Al escribir las pruebas unitarias es recomendable replicar la estructura del paquete en el directorio de pruebas. Por ejemplo, si quieres probar la clase de la entidad Blog situada ensrc/Blogger/BlogBundle/Entity/Blog.php el archivo de pruebas debería residir en src/Blogger/BlogBundle/Tests/Entity/BlogTest.php. Un ejemplo de la estructura de directorios sería el siguiente:

[codesyntax lang=”php”]

[/codesyntax]

Ten en cuenta que cada uno de los archivos de prueba tienen el sufijo Test.

Probando la entidad Blog — el método slugify

Comencemos probando el método slugify en la entidad blog. Escribamos algunas pruebas para asegurarnos de que este método funciona correctamente. Crea un nuevo archivo situado en src/Blogger/BlogBundle/Tests/Entity/BlogTest.php y añade lo siguiente:

[codesyntax lang=”php” title=”src/Blogger/BlogBundle/Tests/Entity/BlogTest.php”]

[/codesyntax]

Hemos creado una clase de prueba para la entidad Blog. Observa que la ubicación del archivo cumple con la estructura de directorios mencionada anteriormente. La clase BlogTest extiende a la clase base PHPUnit_Framework_TestCase de PHPUnit. Todas las pruebas que escribas para PHPUnit serán herederas de esta clase. Recordarás de los capítulos anteriores que la  se debe colocar enfrente del nombre de la clase PHPUnit_Framework_TestCase debido a que la clase se declara en el espacio de nombres público de PHP.

Ahora que ya tenemos el esqueleto de la clase de pruebas para nuestra entidad Blog, escribamos un caso de prueba. Los casos de prueba en PHPUnit son los métodos de la clase prefijados con Test, tal como testSlugify(). Actualiza el BlogTest situado en src/Blogger/BlogBundle/Tests/Entity/BlogTest.php con lo siguiente:

[codesyntax lang=”php” title=”src/Blogger/BlogBundle/Tests/Entity/BlogTest.php”]

[/codesyntax]

Esta es una prueba muy simple. Crea una instancia de una nueva entidad Blog y ejecuta un assertEquals() en el resultado del método slugify. El método assertEquals()toma dos argumentos obligatorios, el resultado esperado y el resultado real. Puedes pasar un tercer argumento opcional para especificar un mensaje a mostrar cuando el caso de prueba falle.

Ejecutemos nuestra nueva prueba unitaria. Ejecuta lo siguiente en la línea de ordenes.

$ phpunit -c app

Deberías ver la siguiente salida.

 

La salida de PHPUnit es muy simple, comienza mostrando información acerca de PHPUnit y produce un '.' por cada prueba que se ejecuta, en nuestro caso solamente está ejecutando una prueba, de modo que produce un '.' solamente. La última aserción nos informa el resultado de las pruebas. Para nuestra BlogTest sólo corrió una prueba con una aserción. Si tienes salida a color en tu línea de ordenes también podrás ver que toda la última línea aparece en verde mostrando que toda la ejecución fue exitosa. Actualiza el método testSlugify() para ver qué pasa cuando las pruebas fallan.

[codesyntax lang=”php” title=”src/Blogger/BlogBundle/Tests/Entity/BlogTest.php”]

[/codesyntax]

Vuelve a ejecutar las pruebas unitarias como antes. La salida mostrará lo siguiente:

Esta vez, la salida es un poco más complicada. Podemos ver que el . de las pruebas ejecutadas se sustituye por una F. Esto nos dice que la prueba ha fallado. También podrás ver el carácter E producido, si tu prueba contiene errores. A continuación, PHPUnit nos informa detalladamente las fallas, en este caso, 1 falla. Podemos ver que el método BloggerBlogBundleTestsEntityBlogTest::testSlugify ha fallado porque los valores esperado y real eran diferentes. Si tienes salida a color en la línea de ordenes también podrás ver que la última línea mostrada aparece en color rojo cuando se presentan fallas en tus pruebas. Corrige el método testSlugify() para ejecutar las pruebas con éxito.

[codesyntax lang=”php” title=”src/Blogger/BlogBundle/Tests/Entity/BlogTest.php”]

[/codesyntax]

Antes de continuar añade algunas pruebas más al método slugify().

[codesyntax lang=”php” title=”src/Blogger/BlogBundle/Tests/Entity/BlogTest.php”]

[/codesyntax]

Ahora que hemos probado el método slugify de la entidad Blog, necesitamos garantizar que la propiedad $slug del Blog esté correctamente ajustada cuando se actualiza la propiedad $title del Blog. Añade los siguientes métodos al archivo BlogTest situado en src/Blogger/BlogBundle/Tests/Entity/BlogTest.php:

[codesyntax lang=”php” title=”src/Blogger/BlogBundle/Tests/Entity/BlogTest.php”]

[/codesyntax]

Comenzamos probando el método setSlug para asegurarnos de que la propiedad $slug esté correctamente slugificada cuando se actualiza. A continuación comprobamos que la propiedad $slug se actualiza correctamente cuando se invoca al método setTitle en la entidad Blog.

Ejecuta las pruebas para verificar que la entidad Blog está funcionando correctamente.

Probando la extensión de Twig

En el capítulo anterior creamos una extensión de Twig para convertir una instancia de DateTime en una cadena que detalla el lapso de un período de tiempo. Crea un nuevo archivo de prueba situado en src/Blogger/BlogBundle/Tests/Twig/Extensions/BloggerBlogExtensionTest.php y actualízalo con el siguiente contenido:

[codesyntax lang=”php” title=”src/Blogger/BlogBundle/Tests/Twig/Extensions/BloggerBlogExtensionTest.php”]

[/codesyntax]

La clase se configura igual que antes, creando un método testCreatedAgo() para probar la extensión de Twig. En este caso de prueba, te presentaremos otro método dePHPUnit, el método setExpectedException(). Este método se debe invocar antes de ejecutar un método que esperas lance una excepción. Sabemos que el métodocreatedAgo de la extensión de Twig no puede manejar fechas futuras y lanzará un Exception. El método getDateTime() simplemente es un método ayudante para crear una instancia de DateTime. Ten en cuenta que no tiene el prefijo test por lo tanto PHPUnit no tratará de ejecutarlo como un caso de prueba. Abre la línea de ordenes y ejecuta las pruebas de este archivo. Podríamos simplemente ejecutar la prueba como antes, pero también podemos decir a PHPUnit que ejecute las pruebas de un directorio (y subdirectorios) específico o un archivo. Ejecuta la siguiente orden:

$ phpunit -c app src/Blogger/BlogBundle/Tests/Twig/Extensions/BloggerBlogExtensionTest.php

Esto ejecutará las pruebas solamente para el archivo BloggerBlogExtensionTestPHPUnit nos informará que las pruebas fallaron. El resultado se muestra a continuación:

Estábamos esperando que la primera aserción regresara O seconds ago, pero no lo hizo, la segunda palabra no era plural. Actualicemos la extensión de Twig ubicada ensrc/Blogger/BlogBundle/Twig/Extensions/BloggerBlogBundle.php para corregir esta situación:

[codesyntax lang=”php” title=”src/Blogger/BlogBundle/Twig/Extensions/BloggerBlogBundle.php”]

[/codesyntax]

Vuelve a ejecutar las pruebas de PHPUnit. Deberías ver que la primer aserción pasa correctamente, pero nuestro caso de prueba sigue fallando. Examinemos el siguiente resultado:

[codesyntax lang=”php”]

[/codesyntax]

Ahora podemos ver que la quinta aserción está fallando (observa el 18 al final de la salida, esto nos da el número de línea en el archivo de la aserción que está fallando). Viendo los casos de prueba, podemos ver que la extensión de Twig ha funcionado incorrectamente. Debería haber devuelto Hace 1 hora, pero en su lugar fue hace 60minutos. Si examinamos el código en la extensión BloggerBlogExtension de Twig, podemos ver la razón. Comparamos el tiempo como si fuera incluyente, es decir, utilizamos <= en lugar de <. También podemos ver que este es el caso en la comprobación de las horas. Actualiza la extensión de Twig situada ensrc/Blogger/BlogBundle/Twig/Extensions/BloggerBlogBundle.php para corregir esta situación:

[codesyntax lang=”php” title=”src/Blogger/BlogBundle/Twig/Extensions/BloggerBlogBundle.php”]

[/codesyntax]

Ahora vuelve a ejecutar todas nuestras pruebas con la siguiente orden:

$ phpunit -c app

Esto ejecutará todas nuestras pruebas, y mostrará que todas las pruebas pasan satisfactoriamente. Aunque sólo hemos escrito un pequeño número de pruebas unitarias, deberías estar captando la idea de qué tan potentes e importantes son las pruebas a la hora de escribir código. Y aunque los errores anteriores fueron menores, ¡siguen siendo errores! Las pruebas también ayudan a garantizar que ninguna funcionalidad agregada en el futuro al proyecto rompa las características anteriores. Esto concluye las pruebas unitarias por el momento. Vamos a ver más pruebas unitarias en los siguientes capítulos. Intenta añadir tus propias pruebas unitarias para comprobar la funcionalidad que se ha perdido.

Probando la funcionalidad

Ahora que hemos escrito algunas pruebas unitarias, vamos a pasar a las pruebas de múltiples componentes juntos. La primera sección de la prueba de funcionamiento implicará la simulación de las peticiones del navegador hasta las pruebas de las respuestas generadas.

Probando la página Sobre

Comencemos probando la página Sobre de la clase PageController. Dado que la página Sobre es muy sencilla, este es un buen lugar para empezar. Crea un nuevo archivo situado en src/Blogger/BlogBundle/Tests/Controller/PageControllerTest.php y agrégale el siguiente contenido:

[codesyntax lang=”php” title=”src/Blogger/BlogBundle/Tests/Controller/PageControllerTest.php”]

[/codesyntax]

Ya hemos visto una prueba de controlador muy similar a esta cuando hablamos brevemente de la clase DefaultControllerTest. Esta es la prueba de la página sobre desymblog, comprobando que la cadena About symblog está presente en el código HTML generado, en concreto dentro de la etiqueta H1. La clase PageControllerTest no extiende a PHPUnit_Framework_TestCase como hemos visto con los ejemplos de las pruebas unitarias, en su lugar extiende a la clase WebTestCase. Esta clase forma parte del FrameworkBundle de Symfony2.

Como hemos explicado antes las clases de prueba de PHPUnit deben extender la clase PHPUnit_Framework_TestCase, pero cuando se requiere funcionalidad adicional o común a través de múltiples casos de prueba es útil encapsularla en su propia clase y que sus clases de prueba extiendan esta. La clase WebTestCase hace exactamente eso, esta ofrece una serie de métodos útiles para realizar pruebas funcionales en Symfony2. Echa un vistazo al archivo WebTestCase situado envendor/symfony/src/Symfony/Bundle/FrameworkBundle/Test/WebTestCase.php, verás que esta clase está, de hecho, extendiendo la clase PHPUnit_Framework_TestCase.

[codesyntax lang=”php” title=”vendor/symfony/src/Symfony/Bundle/FrameworkBundle/Test/WebTestCase.php”]

[/codesyntax]

Si nos fijamos en el método createClient() de la clase WebTestCase puedes ver que esta crea una instancia del Kernel de Symfony2. Siguiendo sus métodos, también te darás cuenta de que el entorno se fija en test (a menos que sustituyas uno de los argumentos de createClient()). Este es el entorno test del que hablamos en el capítulo anterior.

Mirando hacia atrás en nuestra clase de prueba podemos ver que el método createClient() invoca a la prueba y la ejecuta. Luego llamamos al método request() en el cliente para simular una petición GET del navegador HTTP a la URL /sobre (esto sería igual que visitar http://symblog.dev/about en tu navegador). La petición nos da un nuevo objeto Crawler, que contiene la Respuesta. La clase Crawler es muy útil ya que nos permite recorrer el HTML devuelto. Usamos la instancia del Crawler para verificar que la etiqueta H1 en el HTML de la respuesta contiene las palabras About symblog. Notarás que a pesar de que estamos extendiendo la clase WebTestCasetodavía usamos el método assert como antes (recordemos que la clase PageControllerTest todavía es heredera de la clase PHPUnit_Framework_TestCase).

Ejecutemos la PageControllerTest con la siguiente orden. Al escribir las pruebas es útil ejecutar solamente las pruebas para el archivo en que estás trabajando actualmente. A medida que crezca el conjunto de pruebas, las pruebas funcionales pueden ser una tarea que consume demasiado tiempo:

$ phpunit -c app/ src/Blogger/BlogBundle/Tests/Controller/PageControllerTest.php

Serás recibido con el mensaje OK (1 prueba, 1 aserción) informando que se ejecutó una prueba (la testAboutIndex()), con una aserción (assertEquals()).

Intenta cambiar la cadena About symblog a Contacto y vuelve a ejecutar la prueba. La prueba ahora fallará puesto que no se encontrará Contacto, provocando queasertEquals equivalga a false:

Revierte de nuevo la cadena a About symblog antes de continuar.

La instancia del Crawler utilizada te permite recorrer tanto documentos HTML como XML (lo cual significa que el Crawler sólo funcionará con respuestas que devuelvenHTML o XML). Podemos usar el Crawler para recorrer la respuesta generada usando métodos como filter()first()last() y parent(). Si has utilizado jQuery antes te debes sentir como en casa con la clase Crawler. Puedes encontrar una lista completa de los métodos de recorrido apoyados por el Crawler en el capítulo Probando del libro de Symfony2. Vamos a explorar más características del Crawler conforme avancemos.

Página inicial

 

Si bien probar la página Sobre fue sencillo, esta delineó los principios básicos de las pruebas funcionales de las páginas web.

  1. Crear el cliente
  2. Solicitar una página
  3. Comprobar la respuesta

Esta es una descripción simple del proceso, de hecho, hay una serie de otras medidas que también podrías seguir tal como hacer clic en enlaces y rellenar y enviar formularios.

Vamos a crear un método para probar la página inicial. Sabemos que la página inicial está disponible a través de la URL / y que esta debe mostrar los últimos mensajes. Añade un nuevo método testIndex() a la clase PageControllerTest ubicada en src/Blogger/BlogBundle/Tests/Controller/PageControllerTest.php como mostramos a continuación:

[codesyntax lang=”php” title=”src/Blogger/BlogBundle/Tests/Controller/PageControllerTest.php”]

[/codesyntax]

Puedes ver que se toman los mismos pasos como con las pruebas para la página Sobre. Ejecuta la prueba para asegurarte de que todo funciona como se espera.

$ phpunit -c app/ src/Blogger/BlogBundle/Tests/Controller/PageControllerTest.php

Ahora tomemos la prueba y escalémosla un poco más. Parte de las pruebas funcionales implica el poder replicar lo que haría un usuario en el sitio. A fin de que los usuarios se muevan entre las páginas de tu sitio web, ellos hacen clic en los enlaces. Ahora simulemos esta acción para probar los vínculos de la página del blog para mostrar que funciona correctamente cuando se hace clic en el título del blog. Actualiza el método testIndex() en la clase PageControllerTest con el siguiente código:

[codesyntax lang=”php” title=”src/Blogger/BlogBundle/Tests/Controller/PageControllerTest.php”]

[/codesyntax]

Lo primero que hacemos es utilizar el Crawler para extraer el texto contenido en el primer enlace del título del blog. Esto se hace usando el filtro article.blog h2 a. Este filtro se utiliza para devolver la etiqueta a dentro de la etiqueta H2 del artículo article.blog. Para comprender esto mejor, tienes que ver el formato utilizado en la página web para visualizar los blogs.

[codesyntax lang=”html4strict”]

[/codesyntax]

Puedes ver la estructura con el filtro article.blog h2 a en lugar de en el marcado de la página inicial. También notarás que hay más de un <article class="blog"> en el marcado, es decir, el filtro Crawler devuelve una colección. Puesto que sólo queremos el primer enlace, utilizamos el método first() en la colección. Finalmente, utilizamos el método text() para extraer el texto del enlace, que en este caso será el texto Un día con Symfony2. A continuación, hacemos clic en el enlace del título delblog para ir a la página que muestra el blog. El método click() del cliente toma un objeto link y devuelve la Respuesta en una instancia del Crawler. Ahora deberás notar que el objeto Crawler es una parte clave de las pruebas funcionales.

El objeto Crawler ahora contiene la Respuesta de la página que muestra el blog (show en este caso). Tenemos que probar que el enlace nos llevó a navegar por la página apropiada. Podemos utilizar el valor $blogTitle que recuperamos antes de comprobar esto contra el título en la Respuesta.

Ejecuta las pruebas para asegurarte que la navegación entre la página inicial y las páginas que muestran los blogs están funcionando correctamente.

$ phpunit -c app/ src/Blogger/BlogBundle/Tests/Controller/PageControllerTest.php

Ahora que has comprendido cómo navegar a través de las páginas web cuando realizas pruebas funcionales, pasemos a las pruebas de formularios.

Probando la página Contacto

Los usuarios de symblog pueden enviar consultas para ponerse en contacto completando el formulario en la página de contacto http://symblog.dev/contact. Comprobemos que los envíos de ese formulario funcionan correctamente. Lo primero que necesitamos para delinear lo que debe ocurrir cuando el formulario se ha enviado correctamente (presentado satisfactoriamente en este caso, significa que no hay presencia de errores en el formulario).

  1. Navega a la página de Contacto
  2. Rellena el formulario de contacto con valores aceptables
  3. Envía el formulario
  4. Comprueba que el correo electrónico se envía a symblog
  5. Comprueba que la respuesta al cliente contiene la notificación exitosa del contacto

Hasta el momento hemos explorado lo suficiente como para poder completar únicamente los pasos 1 y 5. Ahora vamos a buscar la forma de comprobar los 3 pasos intermedios.

Añade un nuevo método testContact() a la clase PageControllerTest ubicada en src/Blogger/BlogBundle/Tests/Controller/PageControllerTest.php:

[codesyntax lang=”php” title=”src/Blogger/BlogBundle/Tests/Controller/PageControllerTest.php”]

[/codesyntax]

Comenzamos en la forma habitual, haciendo una petición a la URL /Contact y comprobando que la página contiene el título correcto en H1. A continuación, utilizamos elCrawler para seleccionar el botón para enviar el formulario. La razón por la que seleccionamos el botón y no el formulario, es que un formulario puede contener varios botones en los cuales posiblemente desees hacer clic de forma independiente. A partir del botón seleccionado podemos recuperar el formulario. Podemos configurar los valores del formulario usando la notación de subíndice []. Por último, el formulario se pasa al cliente con el método submit() el cual efectivamente presenta el formulario. Como siempre, recibimos una nueva instancia del Crawler. Usando la respuesta del Crawler nos aseguramos de que el mensaje flash está presente en la respuesta devuelta. Ejecuta la prueba para comprobar que todo funciona correctamente.

$ phpunit -c app/ src/Blogger/BlogBundle/Tests/Controller/PageControllerTest.php

La prueba ha fallado. Por lo tanto PHPUnit nos proporciona la siguiente información:

La salida nos informa que el mensaje flash no se puede encontrar en la respuesta del formulario enviado. Esto se debe a que en el entorno test, no se siguen las redirecciones. Cuando el formulario es validado satisfactoriamente en la clase PageController ocurre una redirección. Esta redirección no se está siguiendo; Tenemos que decirle explícitamente que se debe seguir la redirección. La razón de que no se siguen las redirecciones es simple, posiblemente primero desees comprobar la respuesta actual. Esto lo vamos a demostrar en breve para comprobar si el correo electrónico fue enviado. Actualiza la clase PageControllerTest para establecer que el cliente siga la redirección.

[codesyntax lang=”php” title=”src/Blogger/BlogBundle/Tests/Controller/PageControllerTest.php”]

[/codesyntax]

Ahora al ejecutar PHPUnit esta prueba en particular debe pasar. Veamos el último paso del proceso de comprobación para el envío del formulario de contacto, el paso 4, debemos comprobar que un correo electrónico fue enviado a symblog. Ya sabemos que los mensajes de correo electrónico no serán entregados en el entorno test debido a la siguiente configuración:

[codesyntax lang=”php”]

[/codesyntax]

Podemos probar si los correos electrónicos fueron enviados utilizando la información proporcionada por el perfilador web. Aquí es donde entra en juego la importancia de que el cliente no siga las redirecciones. La comprobación en el perfilador se necesita hacer antes de que suceda la redirección, ya que la información en el perfilador se perderá. Actualiza el método testContact() con el siguiente mensaje:

[codesyntax lang=”php” title=”src/Blogger/BlogBundle/Tests/Controller/PageControllerTest.php”]

[/codesyntax]

Después de presentar el formulario comprobamos si está disponible el analizador, ya que se pudo haber desactivado con un valor de configuración para el entorno actual

Recuerda que las pruebas no se tienen que ejecutar en el entorno test, estas se podrían ejecutar en el entorno de producción en el cual ciertas cosas —como el generador de perfiles— no estarán disponibles.

Si podemos obtener el perfilador, haremos una petición para recuperar el colector SwiftMailer. El colector SwiftMailer trabaja entre bastidores para obtener información acerca de cómo se utiliza el servicio de correo electrónico. Podemos usar esto para obtener información respecto a los correos electrónicos que se han enviado.

A continuación, utilizamos el método getMessageCount() para comprobar que un correo electrónico fue enviado. Esto puede ser suficiente para garantizar que por lo menos un correo electrónico será enviado, pero no verifica que el correo electrónico será enviado a la ubicación correcta. Puede ser muy embarazoso e incluso perjudicial enviar mensajes de correo electrónico a la dirección de correo electrónico incorrecta. Para comprobar que este no es el caso, verifica que la dirección de correo electrónico es la correcta.

Ahora, vuelve a ejecutar las pruebas para comprobar que todo funciona correctamente:

$ phpunit -c app/ src/Blogger/BlogBundle/Tests/Controller/PageControllerTest.php

Probando la adición de comentarios al blog

Ahora vamos a utilizar el conocimiento que hemos adquirido de las pruebas anteriores en la página de contacto para comprobar el proceso de enviar un comentario alblog. Una vez más destacamos lo que debe ocurrir cuando el formulario se ha enviado correctamente:

  1. Navega a la página del blog
  2. Rellena el formulario de comentarios con valores adecuados
  3. Envía el formulario
  4. Comprueba que el nuevo comentario se agrega al final de la lista de comentarios del blog
  5. También puedes comprobar los comentarios más recientes en la barra lateral para asegurarte de que el comentario está en la parte superior de la lista.

Crea un nuevo archivo situado en src/Blogger/BlogBundle/Tests/Controller/BlogControllerTest.php y agrégale lo siguiente:

[codesyntax lang=”php” title=”src/Blogger/BlogBundle/Tests/Controller/BlogControllerTest.php”]

[/codesyntax]

Esta vez saltaremos directamente a la prueba. Antes de comenzar la disección del código, ejecuta las pruebas de este archivo para asegurarte de que todo funciona correctamente.

$ phpunit -c app/ src/Blogger/BlogBundle/Tests/Controller/BlogControllerTest.php

PHPUnit te debe informar que la prueba 1 fue ejecutada con éxito. Mirando el código de testAddBlogComment() podemos ver que las cosas comienzan en el formato habitual, creamos un cliente, el cual solicita una página y comprueba que la página en que estamos es la correcta. A continuación, procede a obtener el formulario para agregar el comentario, y enviarlo. La forma en que poblamos los valores del formulario es ligeramente diferente a la versión anterior. Esta vez utilizamos el segundo argumento del método submit() del cliente para pasar los valores del formulario.

También puedes utilizar la interfaz orientada a objetos para establecer los valores de los campos del formulario. A continuación mostramos algunos ejemplos:

[codesyntax lang=”php”]

[/codesyntax]

Después de enviar el formulario, solicitamos al cliente que siga la redirección para que podamos comprobar la respuesta. De nuevo usamos el Crawler para obtener el comentario anterior del blog, el cual debe ser el que acabamos de presentar. Finalmente también revisamos los comentarios recientes en la barra lateral para ver que el comentario es el primero en la lista.

Repositorio del Blog

La última parte de la prueba de funcionamiento que vamos a explorar en este capítulo es la una prueba para el repositorio de Doctrine 2. Crea un nuevo archivo situado en src/Blogger/BlogBundle/Tests/Repository/BlogRepositoryTest.php con el siguiente contenido:

[codesyntax lang=”php”]

[/codesyntax]

Debido a que deseamos realizar pruebas que requieren una conexión válida a la base de datos, una vez más extendemos WebTestCase, ya que nos permite arrancar el kernel de Symfony2. Ejecuta esta prueba para este archivo con la siguiente orden:

$ phpunit -c app/ src/Blogger/BlogBundle/Tests/Repository/BlogRepositoryTest.php

Cobertura de código

Antes de avanzar, rápidamente tocaremos la cobertura de código. La cobertura de código nos da una idea de qué partes del código se ejecutan cuando se realizan las pruebas. Usando esta información, podemos ver las partes de nuestro código que no se está probando, y determinar si es necesario escribir prueba para ellos.

Para dar salida al análisis de la cobertura de código en tu aplicación ejecuta la siguiente orden:

Esta producirá el análisis de cobertura de código en el directorio phpunit-report. Abre el archivo index.html en tu navegador para ver el resultado del análisis.

Ve el capítulo análisis de cobertura de código de la documentación de PHPUnit para más información.

Conclusión

Hemos cubierto una serie de áreas clave en lo que respecta a las pruebas. Hemos explorado tanto las pruebas unitarias como las pruebas funcionales para garantizar que nuestro sitio web está funcionando correctamente. Hemos visto cómo simular peticiones del navegador y cómo utilizar la clase Crawler de Symfony2 para comprobar laRespuesta a nuestras Peticiones.

A continuación vamos a ver el componente de seguridad de Symfony2, específicamente la forma de utilizarlo para gestionar a los usuarios. También integraremos elFOSUserBundle y lo dejaremos listo para trabajar en la sección de administración de symblog.

© Copyright 2011, dsyph3r :: Traducido por Nacho Pacheco

Partes del artículo<< [Parte 5] Personalizando la vista: extensiones Twig, la barra lateral y Assetic

Deja un comentario

  • (will not be published)


7 + 6 =