Ir al contenido principal

TDD - Pruebas de unidad con PHPUnit en Ubuntu con Composer


TDD - Pruebas de unidad con PHPUnit

En esta entrada quiero enseñarte con un ejemplo como hacer  pruebas de unidad con PHPUnit. e instalarlo en Ubuntu.

Pero primero una pequeña introducción por si estás perdido ...


¿Qué es TDD ?. Si alguien puede explicar mucho mejor que yo qué es TDD , pues ese es Carlos Ble y su libro Diseño Ágil con TDD ya que yo practicamente estoy introduciéndome en el mundillo ya que TDD son muchas cosas . Pero en pocas palabras, TDD es hacer los test de tus funciones y luego codificar la función en sí.
TDD es una disciplina , es cambiar tu manera de programar de siempre.

Hacer TDD con PHPUnit es hacer una batería de pruebas de unidad (test) , para todas las funciones de tu programa y en caso de que alguna no supere la prueba, PHPUnit te avisará y sabrás que hay algo mal en tu código, en el sentido de que la función no devuelve lo esperado para el test. 

Podrás decir ... "Vaya rollo ! ¿No tengo poco trabajo con programar el código ,sino que encima me estás diciendo que haga una prueba de unidad antes de codificar cada función que necesite ???". Pues sí .

El tiempo que "pierdes" haciendo las pruebas, lo estás ganando en que si el test pasa como válido , es que tu función hace lo que tiene que hacer y por ejemplo , no te llamarán por teléfono diciendote ... "Oye , que estoy encriptando las claves de los usuarios con la función aquella que hiciste y esto no va ... no pueden loguearse ... , mira a ver que hiciste !! " .

Por  no haber hecho pruebas ... ahora , tienes que buscar el problema, que a lo mejor solucionas rápido ( o no), pero el "mal trago" y el tiempo perdido arreglando la función , no te lo quita nadie. 

Pues para que no te pase más esto , están las pruebas de unidad, para todo lo demás , Master Card ;).

Para no aburrirte mucho leyendo  voy a pasar a como instalar PHPUnit , y cómo usarlo en tus proyectos php con Composer.


Cómo instalar PHPUnit


PHPUnit es un framework que te permite hacer pruebas de unidad en php, es decir , tus test. Para instalarlo , simplemente tienes que seguir la documentación del proyecto en GitHub , pero para ahorrarte el trabajo , aquí te escribo lo que tienes que hacer, eso sí , en Linux.

Descargar PHPUnit:

wget https://phar.phpunit.de/phpunit.phar
chmod +x phpunit.phar
mv phpunit.phar /usr/local/bin/phpunit
¿Qué hacen esos comandos ? 

Pues con wget descargas el script .phar PHPUnit , luego le damos permisos de ejecución y finalmente lo movemos a nuestra carpeta /usr/local/bin , ya que en Ubuntu, en esa ruta podemos poner scripts y podrás acceder a ellos desde cualquier ruta del disco.

¿ Ya está ? , sí , ya tenemos el script PHPUnit en el sistema.

Manos a la obra.


Bien , ¿ Qué mejor que empezar con un ejemplo ? , quiero ponerte un ejemplo útil , no el típico ejemplo de la calculadora , sumar , restar , multiplicar y dividir , para que puedas ver la importancia de las pruebas de unidad. Por un lado quiero explicarte como descargar composer para crear un archivo composer.json y por otro cómo descargar las dependencias para  realizar nuestro objetivo.



Primer paso: Descargar Composer.


Para ello puedes ir a la   página oficial o ejecutar este comando ( te lo dirán en la página )


curl -sS https://getcomposer.org/installer | php



Con ello descargarás la útima versión de composer en el directorio donde ejecutes el comando.

Si quieres utilizar composer desde cualquier sitio , como con PHPUnit , muévelo con :


mv composer.phar /usr/local/bin/composer

Una vez ahí ya podrás utilizarlo desde cualquier sitio.


Segundo paso: Crear el fichero composer.json para descargar las dependencias.


Para que composer pueda descargar las dependencias de PHPUnit necesita un archivo que se tiene que llamar composer.json , y su contenido será un JSON donde pondremos las dependencias a descargar.


composer.json
{
    "require-dev": {
        "phpunit/phpunit": "4.0"
    }
}


Tercer paso: Descargar las dependencias.


Para descargar las dependencias , tenemos que situarnos en la carpeta de nuestro proyecto, donde tengamos el composer.json y ejecutar simplemente:


composer update
y se descargarán las dependencias.







Cuarto paso: El proyecto de ejemplo !


Crea una carpeta en tu /var/www llamada phpunit ( por ejemplo )  y los siguientes archivos: (También puedes descargar el proyecto de ejemplo en NetBeans en mi Github https://github.com/tsw1985/PHPUnit ).

index.php donde ahí llamaremos a la función incrementSalary() , en este caso solamente vamos a ver un "echo" de la salida de la función.

functions.php , ahí tendremos nuestras funciones para nuestro programa.

phpunit,xml , este será el archivo de configuración donde indicaremos en que carpeta están nuestros tests unitarios, y que queremos ver los resultados en color ,para ver mejor si se han superado los test o no.

Una carpeta llamada "test" y dentro este archivo MyTest.php , ésta será la clase que ejecutará nuestros test.


index.php
1:  <?php  
2:   $actualSalary = 1000;  
3:    
4:   require_once('./functions.php');  
5:   echo "El aumento de un 2% del sueldo de ".$actualSalary." Euros es ".incrementSalary( $actualSalary)." Euros";
6:  ?>  

functions.php
1:  <?php  
2:   function incrementSalary( $actualSalary ){  
3:     return ( 2 * $actualSalary ) /  100;  
4:   }  
5:  ?>  

test/MyTest.php
1:  <?php  
2:  require_once 'functions.php';  
3:  class MyTest extends PHPUnit_Framework_TestCase  
4:  {  
5:    public function testIncrementSalary()  
6:    {  
7:      $incrementSalary = incrementSalary( 1000 );  
8:      $this->assertEquals( 20, $incrementSalary );  
9:    }  
10:  }  
11:  ?>  


phpunit.xml
1:  <?xml version="1.0" encoding="UTF-8"?>  
2:  <phpunit colors="true">  
3:    <testsuites>  
4:      <testsuite name="Application Test Suite">  
5:        <directory>./test</directory>  
6:      </testsuite>  
7:    </testsuites>  
8:  </phpunit>  


Ya con esto , tenemos lo necesario para realizar las pruebas . Ten en cuenta que para que PHPUnit encuentre los test unitarios, el nombre de las funciones deben empezar por "test"

Si ejecutamos en la raiz del proyecto :
phpunit

Veremos que los test son válidos. Las funciones se ejecutan bien y devuelven lo esperado.



¿Cómo funcionan los test?


La clase MyTest.php extiende de PHPUnit_Framework_TestCase donde están todos los métodos asserts. Podemos tratar excepciones y muchas más cosas con ellos. Aquí tienes el listado de los assertions.

Assert en inglés significa "acierto","afirmación","coincidencia" y como su nombre indica , el método assertEquals comprobará si coincide un valor que conocemos previamente , con el valor que debe devolver la función.


  $incrementSalary = incrementSalary( 1000 );  
  $this->assertEquals( 20, $incrementSalary );  

El test almacenará en la variable $incrementSalary el resultado que devuelve nuestra función,  que es 20. Y el método assertEquals() está diciendo: "En mi primer parámetro sé que tengo que tener un 20 , y en el segundo parámetro tendré el resultado. Si es algo distinto a 20 , pues daré este test por negativo".


Como has visto , este test ha dado positivo. Ahora imagina por un momento , que la función incrementSalary() la refactorizas , o alguien pone que se haga el cálculo con un 20% en vez de con un 2% y ese código va a producción. Como ya has adivinado , el cálculo se hará mal, los salarios aumentarán en un 20% en vez de en un 2%.


El test negativo.

Como iba diciendo, vamos a cambiar el comportamiento de la función para ver como PHPUnit nos dice que hay una función que no pasa el test. Eso sí, si realmente quieres cambiar su comportamiento , en la función de test tienes que cambiar el valor esperado ya que realmente estas refactorizando la función original, pero en el supuesto caso de que no la quieras cambiar, pues el test unitario te avisa del error.

A la función le ponemos el 20%.
1:  <?php  
2:   function incrementSalary( $actualSalary ){  
3:     return ( 20 * $actualSalary ) /  100;  
4:   }  
5:  ?>  


El test unitario sigue esperando un 20.
 $incrementSalary = incrementSalary( 1000 );  
 $this->assertEquals( 20 , $incrementSalary );  


Vemos como PHPUnit nos avisa del error, esperaba 20 y obtuvo 200.






Conclusión.


PHPUnit ha realizado los test y nos está diciendo : "En el test de unidad testIncrementSalary de la clase MyTest , estaba esperando un 20 y la función me ha dado 200, esto no coincide , por lo tanto no pasa el test". 


Aquí ya vemos la importancia de los test unitarios, sobre todo para funciones importantes como éstas (en el supuesto caso de que fuera un programa real y un proyecto grande en el que trabajan muchos programadores). 

En este ejemplo es una función muy cortita , pero el caso se puede dar en la realidad , con otras funciones importantes que realizan cálculos , encriptación ... o cualquier otra cosa. Lo suyo es tener pruebas unitarias a todas las funciones del código. 


PHPUnit cubre muchas más funcionalidades, pero yo en esta entrada solamente quería centrarme en las pruebas de unidad , en como se instala PHPUnit en Ubuntu con Composer, ya que yo practicamente estoy iniciándome en el TDD.

Si quieres saber mucho más sobre las posibilidades que ofrece PHPUnit , aquí tienes la documentación.

Y nada más que añadir, según vaya aprendiendo más sobre TDD iré haciendo más entradas para explicar lo que haya aprendido para intentar ayudar a otros que también estén iniciándose y hacerles el camino un poco más fácil si no saben por donde empezar. 

También quise escribirlo lo más claro posible, de manera que si alguien no tiene ni idea de pruebas unitarias  que entienda los conceptos de una manera fácil.

Espero que este post te haya servido de ayuda ;).














Entradas populares de este blog

LPIC-1 101 y 102

Certificación LPIC-1 101-102. Linux Certification Institute. Esta entrada es especial para mi porque he aprobado el certificado LPIC-1 de Linux. Al buscar información sobre las certificaciones , pues encontré información confusa y sé de algunas personas que quieren prepararse el exámen para un futuro , y si las bases de los exámenes no cambian quería aclararle las dudas. Quien no sepa lo que es LPIC-1 , es una certificación del Linux Professional Institute  la cual avala que tienes los conocimientos mínimos para gestionar un sistema operativo Linux independientemente de su distribución, como siempre te pongo la información más extendida   aquí .  El LPIC-1 es el primer exámen de todos y te digo desde ya que tiene su dificultad. Esto lo digo porque yo mismo al llevar un par de años con Linux , creía que mis conocimientos en Linux eran suficientes y solo había visto la punta del iceberg. Y en el primer nivel tocas muchas cosas. Lo que te quiero decir con esto es que e

Juego de la Serpiente con Java Swing

En esta entrada les voy a mostrar como hice el juego de la serpiente. Cuando tenía 15 años lo intente hacer y en ese momento lo ví como algo extremadamente complejo.  En su momento no vi mucha información de como hacer el juego ( o no supe encontrar ) , y por si alguien está en esta situación , aquí va mi aportación para intentar aclarar sus dudas.    He visto muchos códigos que lo han hecho mucho mejor, dibujando en el Frame y mucho más trabajado, pero yo personalmente soy partidiario de que siempre es mejor ver las cosas desde su nivel más simple, y una vez entendida la idea, ya luego pasarla a otra cosa, darle mejor aspecto y adornos son valores añadidos. Para el que no sepa como funciona el juego de la serpiente ( cosa que dudo , todos tuvimos un Nokia ) , es una serpientita a la que le van apareciendo frutas , ella va comiendo y se va haciendo grande, hasta que llega un momento que se hace muy difícil controlarla porque es demasiado grande y chocamos con nosotros mismos.

Añadiendo autocompletado a un JTextField de Java Swing

Esta vez para un trabajo de clase en  Java Swing  me vi con la necesidad de tener un JTextField con autocompletado ( como la caja de texto de Google cuando buscas algo ) y como no viene por defecto el JTextField con esta característica , pues tuve que hacerme uno. Pero en este caso no me hacía falta consultar una base de datos para rellenarlo según vas escribiendo en él, sino que a este ya le doy los datos a filtrar de antemano. Tú dirás ... pero si hay miles en internet ya hechos , por qué reinventar la rueda ...,  Ya , ya lo sé , pero en algunos de los que ví , no me gustaba la manera de como se implementaban en el código para poder usarlo , otros no me gustaban como se veían visualmente , y lo más importante ... yo no me podía quedar con la duda de como se hacía uno ( esta última era la que más me podía jeje , yo y mi curiosidad ). ¿Cómo lo uso ? Te explico como funciona el componente GTextField , tan simple como instanciarlo y en su constructor pasarle t