La guía de Newbie para el desarrollo guiado por pruebas

Probar su código es molesto, pero el impacto de no hacerlo puede ser órdenes de magnitud más molestos. En este artículo, usaremos el desarrollo guiado por pruebas para escribir y probar nuestro código de manera más efectiva.


¿Qué es el desarrollo basado en pruebas??

Desde el comienzo de la era de las computadoras, los programadores y los insectos han luchado por la supremacía. Es una ocurrencia inevitable. Incluso los mejores programadores caen presa de estas anomalías. Ningún código es seguro. Es por eso que hacemos pruebas. Los programadores, al menos los sanos, prueban su código ejecutándolo en máquinas de desarrollo para asegurarse de que hace lo que se supone que debe hacer.


Sane programador que prueba sus programas..
Imagen cortesía de http://www.youthedesigner.com
Loco programador que no prueba sus programas..
Imagen cortesía de http://www.internetannoyanceday.com

Desarrollo guiado por pruebas es una técnica de programación que requiere que usted escriba código real y código de prueba automatizado simultáneamente. Esto asegura que usted prueba su código y le permite volver a probar su código rápida y fácilmente, ya que es automático.

Como funciona?

El desarrollo guiado por pruebas, o TDD, como lo llamaremos a partir de ahora, gira en torno a un ciclo de desarrollo iterativo corto que dice algo como esto:

  1. Antes de escribir cualquier código, primero debe escribir una prueba automatizada para su código. Al escribir las pruebas automatizadas, debe tener en cuenta todas las posibles entradas, errores y salidas. De esta manera, tu mente no está nublada por ningún código que ya haya sido escrito.
  2. La primera vez que ejecute su prueba automatizada, la prueba debe fallar, lo que indica que el código aún no está listo.
  3. Después, puedes comenzar a programar. Dado que ya existe una prueba automatizada, siempre que el código falle, significa que todavía no está listo. El código puede ser arreglado hasta que pase todas las aserciones.
  4. Una vez que el código pasa la prueba, puede comenzar a limpiarlo mediante la refactorización. Mientras el código pase la prueba, significa que aún funciona. Ya no tienes que preocuparte por los cambios que introducen nuevos errores..
  5. Empieza todo de nuevo con algún otro método o programa..

El ciclo de desarrollo basado en pruebas.
Imagen cortesía de http://en.wikipedia.org/wiki/Test-driven_development

Genial, pero ¿cómo es esto mejor que las pruebas regulares??

¿Alguna vez ha omitido intencionalmente probar un programa porque:

  • Sentiste que era una pérdida de tiempo probar, ya que solo fue un ligero cambio de código?
  • Te sentiste perezoso probando todo otra vez?
  • No tuvo tiempo suficiente para realizar la prueba porque el jefe de proyecto quería que pasara a producción lo antes posible?
  • Te dijiste que lo harías "mañana"?
  • Debes elegir entre las pruebas manuales o ver el último episodio de tu programa de televisión favorito (The Big Bang Theory)?

La mayoría de las veces, no sucede nada, y usted mueve con éxito su código a producción sin ningún problema. Pero a veces, después de pasar a la producción, todo va mal. Estás atascado arreglando cien agujeros en un barco que se hunde, con más apareciendo cada minuto. Tú lo haces no quiero encontrarte en esta situación.


Atorníllalo, solo muévelo a producción.!
Imagen cortesía de http://phenomenaonbreak.wordpress.com

TDD estaba destinado a eliminar nuestras excusas. Cuando un programa se ha desarrollado utilizando TDD, nos permite realizar cambios y realizar pruebas de forma rápida y eficiente. Todo lo que necesitamos hacer es ejecutar las pruebas automatizadas, y listo! Si pasa todas las pruebas automatizadas, entonces estamos bien, si no, entonces solo significa que rompimos algo con los cambios. Al saber qué partes exactas de la prueba fallaron, también nos permite identificar fácilmente en qué parte de los cambios se rompió, lo que facilita la solución de errores..


Estoy vendido. Cómo hacemos esto?

Hay una multitud de marcos de prueba automatizados de PHP que podemos usar. Uno de los marcos de prueba más utilizados es PHPUnit..

PHPUnit es un excelente marco de prueba, que puede integrarse fácilmente en sus propios proyectos u otros proyectos construidos sobre los marcos de PHP populares.

Sin embargo, para nuestros propósitos, no necesitaremos la multitud de funciones que ofrece PHPUnit. En su lugar, optaremos por crear nuestras pruebas utilizando un marco de prueba mucho más sencillo, llamado SimpleTest.

En los siguientes pasos, supongamos que estamos desarrollando una aplicación de libro de visitas donde cualquier usuario puede agregar y ver las entradas del libro de visitas. Supongamos que el marcado se ha completado, y que simplemente estamos haciendo una clase que contiene el lógica de aplicación del libro de visitas, que es donde la aplicación inserta y lee en la base de datos. La parte de lectura de esta clase es lo que vamos a desarrollar y probar..


Paso 1. Configurar SimpleTest

Este es posiblemente el paso más fácil de todos. Incluso este tipo podría hacerlo:


¿Puedo hacer esto? Puedo usar, mi, um? cerebro!
Imagen cortesía de http://longstreet.typepad.com/

Descargue SimpleTest aquí y extraiga a la carpeta de su elección, preferiblemente la carpeta donde va a desarrollar su código, o su ruta de inclusión de PHP para un fácil acceso.

Para este tutorial, he configurado la carpeta así:

Index.php ejecutará guestbook.php, invocará el método de visualización y mostrará las entradas. Dentro de la carpeta de clases es donde colocaremos la clase guestbook.php, y la carpeta de prueba es donde ubicaremos la biblioteca más simple.


Paso 2. Planifica tu ataque


Imagen cortesía de http://connections.smsd.org/veterans

El segundo paso, que en realidad es el más importante, es comenzar a crear las pruebas. Para esto, realmente necesita planificar y pensar qué hará su función, qué entradas posibles obtendrá y las salidas correspondientes que enviará. Este paso se asemeja a jugar un juego de ajedrez: necesitas saber todo sobre tu oponente (el programa), incluidas todas sus debilidades (posibles errores) y fortalezas (qué sucede si se ejecuta con éxito).

Así que para nuestra aplicación de libro de visitas, vamos a establecer los esquemas:

Ver

  • Esta función no tendrá ninguna entrada, ya que solo recuperará todas las entradas de la base de datos y enviará de vuelta los datos para imprimirlos..
  • Devolverá una serie de registros del libro de visitas, indicando el nombre del póster y su mensaje. Si no hay registros, entonces debería devolver una matriz vacía.
  • Si hay registros, la matriz tendrá 1 o más valores en ella.
  • Al mismo tiempo, la matriz tendrá una estructura específica, algo como:
 Array ([0] => Array (['name'] = "Bob" ['message'] = "Hola, soy Bob.") [1] => Array (['name'] = "Tom" ['mensaje'] = "Hola, soy Tom."))

Paso 3. Escribe una prueba!


Imagen cortesía de http://cflhomeless.wordpress.com

Ahora, podemos escribir nuestra primera prueba. Empecemos creando un archivo llamado guestbook_test.php dentro de la carpeta de prueba.

  

Entonces, vamos a convertir lo que hemos determinado en el paso dos,.

 agregar ("Bob", "Hola, soy Bob"); $ guestbook-> add ("Tom", "Hola, soy Tom."); $ entries = $ guestbook-> viewAll (); $ count_is_greater_than_zero = (count ($ entries)> 0); $ this-> assertTrue ($ count_is_greater_than_zero); $ this-> assertIsA ($ entries, 'array'); foreach ($ entries como $ entry) $ this-> assertIsA ($ entry, 'array'); $ this-> assertTrue (isset ($ entry ['name'])); $ this-> assertTrue (isset ($ entry ['message']));  function testViewGuestbookWithNoEntries () $ guestbook = new Guestbook (); $ guestbook-> deleteAll (); // Borre todas las entradas primero para que sepamos que es una tabla vacía $ entries = $ guestbook-> viewAll (); $ this-> assertEqual ($ entries, array ()); 

Las afirmaciones aseguran que cierta cosa es lo que se supone que es, básicamente, asegura que lo que se devuelve es lo que usted espera que regrese. Por ejemplo, si se supone que una función devuelve true si tiene éxito, entonces en nuestra prueba, deberíamos afirmar que el valor de retorno es igual a verdadero.

Como puede ver aquí, probamos la visualización del libro de visitas con entradas y sin ellas. Verificamos si estos dos escenarios pasan nuestros criterios del paso dos. Probablemente también haya notado que cada una de nuestras funciones de prueba comienza con la palabra 'prueba'. Hicimos esto porque, cuando SimpleTest ejecuta esta clase, buscará todas las funciones que comienzan con la palabra "prueba" y la ejecutan.

En nuestra clase de prueba, también hemos usado algunos métodos de afirmación, como assertTrue, assertIsA y assertEquals. La función assertTrue verifica si un valor es verdadero o no. AssertIsA verifica si una variable es de un determinado tipo o clase. Y, por último, assertEquals verifica si una variable es totalmente igual a un cierto valor.

Hay otros métodos de afirmación proporcionados por SimpleTest, que son:

assertTrue ($ x) Falla si $ x es falso
assertFalse ($ x) Falla si $ x es verdadero
assertNull ($ x) Fallo si se establece $ x
assertNotNull ($ x) Fallo si $ x no se establece
assertIsA ($ x, $ t) Falla si $ x no es la clase o el tipo $ t
assertNotA ($ x, $ t) Falla si $ x es de la clase o tipo $ t
assertEqual ($ x, $ y) Falla si $ x == $ y es falso
assertNotEqual ($ x, $ y) Falla si $ x == $ y es verdadero
assertWithinMargin ($ x, $ y, $ m) Fallo si abs ($ x - $ y) < $m is false
assertOutsideMargin ($ x, $ y, $ m) Fallo si abs ($ x - $ y) < $m is true
assertIdentical ($ x, $ y) Fallo si $ x == $ y es falso o una falta de coincidencia de tipo
assertNotIdentical ($ x, $ y) Fallo si $ x == $ y es verdadero y los tipos coinciden
assertReference ($ x, $ y) Falla a menos que $ x y $ y sean la misma variable
assertClone ($ x, $ y) Falla a menos que $ x y $ y sean copias idénticas
assertPattern ($ p, $ x) Falla a menos que la expresión regular $ p coincida con $ x
assertNoPattern ($ p, $ x) Falla si la expresión regular $ p coincide con $ x
expectError ($ x) Traga cualquier error próximo coincidente
afirmar ($ e) Fallo en el objeto de expectativa fallida $ e

Lista de métodos de aserción cortesía de http://www.simpletest.org/en/unit_test_documentation.html


Paso 4. No puedes ganar


Imagen cortesía de http://verydemotivational.com

Una vez que haya terminado de escribir el código, debe ejecutar la prueba. La primera vez que ejecutas la prueba, DEBE FALLAR. Si no lo hace, entonces significa que tu prueba no prueba nada.

Para ejecutar su prueba, simplemente ejecute guestbook_test.php en tu navegador Deberías ver esto primero:

Esto sucedió porque todavía no hemos creado nuestra clase de libro de visitas. Para hacerlo, crea guestbook.php dentro de tu carpeta de clases. La clase debe contener los métodos que planeamos utilizar, pero al principio no debe contener nada. Recuerda, primero estamos escribiendo las pruebas. antes de escribiendo cualquier código.

  

Cuando vuelva a ejecutar la prueba, debería verse algo como esto:

Como podemos ver aquí, nuestra prueba ahora está ganando al fallar. Esto significa que nuestra prueba ahora está lista para ser "contestada".


Imagen cortesía de http://www.gamercastnetwork.com/forums

Paso 5. Contesta tu prueba escribiendo un código


En algún momento, todos nos hemos sentido así cuando estamos programando.
Imagen cortesía de http://fermentation.typepad.com/fermentation

Ahora que tenemos una prueba automatizada de trabajo, podemos comenzar a escribir código. Abre tu guestbook.php Clase y empieza a crear la respuesta a tu prueba..

  'Kirk', 'mensaje' => 'Hola, soy Kirk'. ), array ('name' => 'Ted', 'message' => 'Hi, I \' m Ted. ')); public function viewAll () // Aquí, deberíamos recuperar todos los registros de la base de datos. // Esto se simula devolviendo $ _entries array return self :: $ _ entries;  función pública add ($ nombre, $ mensaje) // Aquí, simulamos la inserción en la base de datos agregando un nuevo registro en la matriz $ _entries // Esta es la forma correcta de hacerlo: self :: $ _ entries [] = array ('nombre' => $ nombre, 'mensaje' => $ mensaje); self :: $ _ entries [] = array ('notname' => $ name, 'notmessage' => $ message); // Vaya, hay un error aquí en algún lugar devuelto true;  public function deleteAll () // Acabamos de configurar la matriz $ _entries para simular self :: $ _ entries = array (); devuelve verdadero 

Esta clase guestbook.php tiene algunos errores a propósito, por lo que podemos ver cómo se ve si falla nuestra prueba..

Una vez que ejecutamos nuestra prueba, deberíamos ver algo como esto:

El resultado de la prueba nos muestra en qué prueba y en qué afirmación falló nuestro código. A partir de esto, podemos señalar fácilmente que la línea 16 y 17 fue la afirmación de que arrojó el error.

 assertTrue (isset ($ entry ['name'])); $ this-> assertTrue (isset ($ entry ['message'])) ;? 

Esto claramente nos dice que la matriz de entrada devuelta no tenía la clave de matriz correcta. Sobre esta base, sabremos fácilmente qué parte de nuestro código salió mal.

  $ nombre, 'mensaje' => $ mensaje); //¡fijo! devuelve verdadero ? 

Ahora, cuando volvamos a ejecutar nuestra prueba, debería mostrarnos:


Paso 6. Refactoriza y refina tu código


Imágenes cortesía de http://www.osborneink.com y http://phuketnews.phuketindex.com

Dado que el código que estamos probando aquí es bastante simple, nuestras pruebas y corrección de errores no duraron mucho. Pero si se tratara de una aplicación más compleja, tendría que realizar varios cambios en su código, hacerlo más limpio para que sea más fácil de mantener y muchas otras cosas. El problema con esto, sin embargo, es que el cambio generalmente introduce errores adicionales. Aquí es donde entra nuestra prueba automatizada; una vez que hacemos cambios, simplemente podemos ejecutar la prueba nuevamente. Si aún pasa, significa que no rompimos nada. Si falla, sabemos que cometimos un error. También nos informa dónde está el problema y, con suerte, cómo podremos solucionarlo..


Paso 7. Enjuague y repita


Imagen cortesía de http://www.philstockworld.com

Eventualmente, cuando su programa requiera una nueva funcionalidad, deberá escribir nuevas pruebas. ¡Eso es fácil! Enjuague y repita los procedimientos del paso dos (ya que sus archivos de SimpleTest ya deberían estar configurados), y comience el ciclo nuevamente..


Conclusión

Hay muchos más artículos de desarrollo guiados por pruebas en profundidad por ahí, e incluso más funcionalidad para SimpleTest que lo que se mostró en este artículo, cosas como objetos simulados, talones, que facilitan la creación de pruebas. Si desea leer más, la página de desarrollo guiada por prueba de Wikipedia debería ponerlo en el camino correcto. Si está interesado en utilizar SimpleTest como marco de prueba, explore la documentación en línea y asegúrese de revisar sus otras características..

Las pruebas son una parte integral del ciclo de desarrollo, sin embargo, a menudo es lo primero que se debe recortar cuando los plazos son inminentes. Con suerte, después de leer este artículo, apreciará lo útil que es invertir en desarrollo basado en pruebas..

¿Qué piensas sobre el desarrollo guiado por pruebas? ¿Es algo que te interesa implementar o crees que es una pérdida de tiempo? Házmelo saber en los comentarios!