Para hacer un poco más rápida y fácil la generación de tests unitarios sobre un proyecto que ya tenemos en marcha lo mejor es automatizar la generación de las clases de test que vayamos a usar… En este ejemplo voy a utilizar el repositorio import-export-legacy que aun tiene mucho coverage pendiente. Suponiendo que ya tenemos una instalación válida de PHP el proceso será sencillo, descargamos los paquetes phar de PHPUnit, generamos un archivo bootstrap para inicializar el autoload de composer, generamos una configuración en xml para PHPUnit y tras esto podremos empezar a desarrollar los tests…

Instalando las librerias

Os dejo aquí abajo copiadas las instrucciones de la web oficial.. no es nada complicado.

Linux, abrimos un terminal y con la ejecución de estos comandos lo tendremos ya preparado.

1
2
3
4
wget https://phar.phpunit.de/phpunit.phar
chmod +x phpunit.phar
sudo mv phpunit.phar /usr/local/bin/phpunit
phpunit --version

Windows, primero deberás incluir la carpeta de tu instalación de PHP en tu PATH, posteriormente descargas el phar de la web oficial https://phar.phpunit.de/phpunit.phar y lo guardas en la carpeta de los ejecutables de PHP que acabas de incluir en tu path, ahora solo te falta crear un wrapper para el comando, abres un cmd y…

1
2
3
C:\Users\username> cd C:\ruta\php
C:\ruta\php> echo @php "%~dp0phpunit.phar" %* > phpunit.cmd
C:\ruta\php> exit

Una vez que podamos ejecutar el comando phpunit –version, realizamos los mismos pasos para obtener el paquete phpunit sekeleton generator.

Linux

1
2
3
wget https://phar.phpunit.de/phpunit-skelgen.phar
chmod +x phpunit-skelgen.phar
mv phpunit-skelgen.phar /usr/local/bin/phpunit-skelgen

Windows, descargamos y movemos https://phar.phpunit.de/phpunit-skelgen.phar a la carpeta de ejecutables PHP y lo envolvemos con un wrapper como se indica en las siguientes lineas.

1
2
3
C:\Users\username> cd C:\ruta\php
C:\ruta\php> echo @php "%~dp0phpunit-skelgen.phar" %* > phpunitSkelgen.cmd
C:\ruta\php> exit

Configurando los tests

En este ejemplo vamos a utilizar la librería mbarquin/import-export-legacy, la cual debemos descargar a nuestro puesto de trabajo, mediante un clone de GIT, descargando directamente un ZIP, o mediante el IDE, en mi caso netbeans.

La estructura del proyecto es simple, vamos a ignorar la carpeta tmp y la carpeta logs. En la raíz vamos a prestar atención a una carpeta llamada build donde almacenaremos los ficheros de coverage o puntuaciones de cualquier tipo resultantes de los tests, esta carpeta contiene un archivo .gitignore para evitar la subidas accidentales de estos al repositorio. También atención a la carpeta src donde tendremos todo nuestro código fuente dividido en las carpetas LegacyFile (El código fuente del proyecto), tests (Donde se almacena todo lo relacionado con los tests) y vendor (lugar donde se almacena el código fuente de las dependencias)

Vamos a generar los casos de test para una aplicación que gestiona las dependencias mediante composer, por lo que utiliza el sistema autoload de composer para importar las librerías y generar rutas sobre su propio namespace. Lo primero necesitamos crear un archivo Bootstrap.php en la raíz de la carpeta tests, muy simple, para inicializar este sistema antes de la ejecución.

1
2
<?php
require dirname(__file__).'../../vendor/autoload.php';

También vamos a crear un archivo de configuración para los tests, donde indicaremos donde dejar los archivos con el resultado de las distintas métricas del análisis.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<phpunit colors="true" bootstrap="./Bootstrap.php">
<testsuite name="Modules Test Suite">
<directory>./LegacyFile</directory>
</testsuite>
<php>
<includePath>.:../LegacyFile:./LegacyFile</includePath>
<ini name="memory_limit" value="256M" />
</php>
<filter>
<whitelist processUncoveredFilesFromWhitelist="true">
<directory suffix=".php">../LegacyFile</directory>
</whitelist>
</filter>
<logging>
<log type="coverage-html" target="../../build/phpUnit"
lowUpperBound="35" highLowerBound="70"/>
<log type="coverage-clover" target="../../build/phpunit-coverage.xml" />
<log type="junit" target="../../../build/phpunit.xml" />
</logging>
</phpunit>

Primera prueba

Ya tenemos todo listo, solo nos falta hacer una prueba para generar la primera clase, con ayuda del comando que hemos creado nos situamos en la carpeta raíz del proyecto y ejecutamos:

1
2
3
4
5
php /usr/local/bin/phpunit-skelgen "--ansi" "generate-test" \
"--bootstrap=/var/www/import-export-legacy/src/tests/Bootstrap.php" \
"mbarquin\LegacyFile\FileProcess" "/var/www/import-export-legacy/src/LegacyFile/FileProcess.php" \
"mbarquin\LegacyFile\FileProcessTest" \
"/var/www/import-export-legacy/src/tests/LegacyFile/FileProcessTest.php"

Con esto tendremos ya generada la primera clase esqueleto para empezar a generar los test para esta librería. En la carpeta src\tests\LegacyFile\ podemos echar un ojo al fuente generado.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
<?php

namespace mbarquin\LegacyFile;

/**
* Generated by PHPUnit_SkeletonGenerator on 2016-04-13 at 12:43:04.
*/
class ExportTest extends \PHPUnit_Framework_TestCase
{

/**
* @var Export
*/
protected $object;

/**
* Sets up the fixture, for example, opens a network connection.
* This method is called before a test is executed.
*/
protected function setUp()
{
$this->object = new Export;
}

/**
* Tears down the fixture, for example, closes a network connection.
* This method is called after a test is executed.
*/
protected function tearDown()
{

}

/**
* @covers mbarquin\LegacyFile\Export::regToFixedString
* @todo Implement testRegToFixedString().
*/
public function testRegToFixedString()
{
// Remove the following lines when you implement this test.
$this->markTestIncomplete(
'This test has not been implemented yet.'
);
}

/**
* @covers mbarquin\LegacyFile\Export::writeRow
* @todo Implement testWriteRow().
*/
public function testWriteRow()
{
// Remove the following lines when you implement this test.
$this->markTestIncomplete(
'This test has not been implemented yet.'
);
}

/**
* @covers mbarquin\LegacyFile\Export::getActualLine
* @todo Implement testGetActualLine().
*/
public function testGetActualLine()
{
// Remove the following lines when you implement this test.
$this->markTestIncomplete(
'This test has not been implemented yet.'
);
}

}

Nos hará falta tocar un poco el código fuente para que no de errores al intentar pasar los test, ya que la clase export tiene un constructor con parámetro que el generador no ha sabido interpretar… pero es un buen comienzo.

Configurando NetBeans

Si como yo utilizas NetBeans para desarrollar voy a indicar un poco como configurar NetBeans y el proyecto para lanzar los tests y generar las clases automáticamente.

Desplegamos en la barra de menú de la ventana principal la sección Tools (Herramientas) y pinchamos en Options (Opciones). En la ventana que aparece escogemos el apartado PHP, en la primera pestaña de esta sección (General) indicamos el path al ejecutable PHP.

Cambiamos a la pestaña Frameworks & Tools (Frameworks y Herramientas) y escogemos PHPUnit en el navegador de la izquierda, ya en el marco central de la ventana, en PHPUnit script y Skeleton generator script escribimos o escogemos las rutas a los comandos que hemos instalado anteriormente.

Configurando PHPUnit para el proyecto en NetBeans

Pulsamos el botón derecho sobre el proyecto PHP que queremos configurar y en el menú desplegable escogemos la última opción, Propiedades. Al abrirse la ventana de dialogo, en el navegador situado a la izquierda, seleccionamos el apartado Testing para configurar el directorio de tests del proyecto y activar PHPUnit.

Una vez terminamos escogemos la sección PHPUnit que se encuentra un poco mas abajo en el mismo navegador lateral. Ahí indicaremos la ruta a los dos archivos, Bootstrap.php y phpunit.xml, que preparan y configuran la ejecución de los tests, hemos de tener cuidado en marcar para que se utilice el archivo Bootstrap para generar las clases, ya que sin el autoload va a dar errores en la generación.

Ahí estamos! :)

Confiando que hayamos hecho todo correctamente, al estar editando un fuente PHP del proyecto, bastará con presionar alt+F6 para lanzar los tests. Generar el esqueleto de las clases que nos interese será tan fácil como pulsar con el botón derecho sobre la carpeta o fuente deseado y escoger la opción Tools (Herramientas) y entre las opciones desplegadas escoger Create/Update Tests, los deja en la raíz de la carpeta de tests, después hay que moverlos a su carpeta correspondiente, retocar el código para completarlos y corregir aquellas cosillas que escapan del generador automático.