Mejora la calidad de tu código con Git y los tests automáticos

Los programadores profesionales utilizan herramientas como Git para gestionar el código de sus aplicaciones y herramientas como PHPUnit para asegurar su calidad. Los mejores profesionales van un paso más allá y nunca suben al repositorio ningún código que previamente no haya pasado todos los tests de la aplicación. Este artículo explica cómo automatizar este proceso.

En primer lugar, asegúrate de tener Git instalado y bien configurado. Para ello, puedes utilizar nuestra guía de instalación de Git. Después, assegúrate de que al ejecutar el comando phpunit -c app no se producen errores. Este comando ejecuta todos los tests unitarios y funcionales de tu aplicación Symfony2.

Personalizando Git con scripts propios

Git permite ejecutar tus propios scripts cuando se producen eventos importantes, un mecanismo similar al de otros sistemas de control de versiones. Estos scripts se llaman hooks y se pueden ejecutar tanto en la parte del cliente (el programador que envía cambios al repositorio) como en en la parte del servidor (el servidor que actualiza su código desde el repositorio).

Los hooks se definen en el directorio .git/hooks/ de tu proyecto. Dentro de ese directorio verás varios hooks de prueba creados por Git y que te pueden servir para aprender cómo crear hooks avanzados.

En nuestro caso necesitamos que se ejecuten todos los tests de la aplicación antes de subir el código al repositorio. Por tanto, necesitamos crear un hook de tipo pre-commit. Crea el archivo .git/hooks/pre-commit y copia en su interior el siguiente contenido (que está adaptado del que puedes ver aquí):

#!/usr/bin/php
<?php
printf("%s > pre-commit > ejecutando los tests ... %1\$s", PHP_EOL);
 
$proyecto = basename(getcwd());
 
exec('phpunit -c app/', $output, $returnCode);
 
if ($returnCode !== 0) {
    $minimalTestSummary = array_pop($output);
 
    printf(" [ERROR] Algún test de %s ha producido un error: ", $proyecto);
    printf("( %s ) %s%2\$s", $minimalTestSummary, PHP_EOL);
 
    return false;
}
 
printf(" [OK] Los tests de %s han pasado correctamente.%s%2\$s", $proyecto, PHP_EOL);
 
return true;

¡Ya está! Haz cualquier cambio en cualquier archivo del proyecto y trata de subirlo al repositorio con el comando git commit. Verás que ahora se ejecutan los tests antes de subir el código:

$ git commit -a
 
 > pre-commit > ejecutando los tests ...
 [OK] Los tests de symfony.es han pasado correctamente.
 
[master ...] ...
 1 file changed, 7 insertions(+), 2 deletions(-)

Acelerando la ejecución de los tests

Cuando tu aplicación contenga muchos tests, este proceso puede ser tan lento que te desespere subir código al repositorio. Para solucionarlo, puedes añadir la opción --no-verify para evitar que Git ejecute los hooks:

$ git commit -a --no-verify

Esta solución es válida cuando el código que subes al repositorio no es crítico o contiene modificaciones muy menores. Otra solución mejor consiste en dividir los tests de tu aplicación en grupos.

PHPUnit permite añadir la anotación @group en cada test para agrupar los tests por funcionalidades. De esta forma, podrías crear un grupo llamado @rendimiento para los tests que aseguran que tu aplicación es rápida, otro grupo llamado @no_importante para los tests no esenciales de tu aplicación, etc.

class MiTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @group rendimiento
     */
    public function testPrimero() { ... }
 
    /**
     * @group no_importante
     * @group error_56332
     */
    public function testSegundo() { ... }
}

Después, PHPUnit te permite ejecutar solamente los tests que pertenecen a un grupo con la opción --group:

$ phpunit -c app --group=rendimiento

Además, también puedes ejecutar todos los tests salvo los que pertenezcan a los grupos que indiques en la opción --exclude-group:

$ phpunit -c app --exclude-group=no_importante

Siguiendo esta idea, puedes agrupar en @importante todos los tests esenciales de tu aplicación y hacer que solamente se ejecuten esos al subir código al repositorio. Para ello, modifica el código del hook anterior por lo siguiente:

#!/usr/bin/php
<?php
printf("%s > pre-commit > ejecutando los tests ... %1\$s", PHP_EOL);
 
$proyecto = basename(getcwd());
 
exec('phpunit -c app/ --group=importante', $output, $returnCode);
 
if ($returnCode !== 0) {
    $minimalTestSummary = array_pop($output);
 
    printf(" [ERROR] Algún test de %s ha producido un error: ", $proyecto);
    printf("( %s ) %s%2\$s", $minimalTestSummary, PHP_EOL);
 
    return false;
}
 
printf(" [OK] Los tests de %s han pasado correctamente.%s%2\$s", $proyecto, PHP_EOL);
 
return true;

Recursos útiles

Compartir en

¿Has visto algún error?

Avísanos en [email protected] para que podamos corregirlo. Gracias.

Proyectos Symfony destacados

La plataforma de eCommerce 100% Symfony que rivaliza con Magento y PrestaShop. Ver más

Síguenos en @symfony_es para acceder a las últimas noticias.