Creación: 04-03-2012
Índice de contenidos
1. Introducción
2. Entorno
3. Como instalar PHP
4. Como instalar PEAR
5. Como instalar PHPUnit
6. Un ejemplo de uso de PHPUnit
7. Como instalar XDebug
4. Conclusiones
5. Sobre el autor
1. Introducción
La vida da muchas vueltas y en estos días me he tenido que poner a hacer algunas cosillas en PHP. Como no tenía ni idea lo primero
que hice fue leerme el manual, y ya puedo afirmar «Ya sé PHP!». Bueno, en realidad sigo sin tener ni idea, pero por lo menos conozco
los principios del lenguaje 😉
Ante este panorama lo segundo que hice fue investigar como se puede hacer TDD en PHP. Para mi esto es fundamental, no
sólo porque considere que el TDD es imprescindible en si mismo, sino porque teniendo en cuenta mi inexperiencia con PHP, no me atrevo a tocar
ni una sola línea de código si no es con un buen test que me proteja de la caída.
Así, en este tutorial, voy a contaros como he configurado mi entorno (Mac OS X) para poder desarrollar en PHP con TDD y pruebas
automáticas con PHPUnit; un framework de pruebas unitarias del estilo xUnit,
donde incluso tenemos soporte para Stubs, Mocks, análisis
de cobertura, y muchas más cosas (de verdad muy recomendable si trabajamos con PHP).
2. Entorno
El tutorial está escrito usando el siguiente entorno:
- Hardware: Portátil MacBook Pro 15′ (2.5 GHz Intel i7, 8GB 1333 Mhz DDR3, 256GB Solid State Drive).
- AMD Radeon HD 6770M 1024 MB
- Sistema Operativo: Mac OS X Lion 10.7.3
- PHP 5.3.8
- PEAR 1.9.4
- PHPUnit 3.6.10
3. Como instalar PHP
Con Mac OS X ya tenemos instalado Apache (servidor Web) y PHP, sólo tenemos que activarlo.
Para ello editamos /etc/apache2/httpd.conf, buscamos la línea:
#LoadModule php5_module libexec/apache2/libphp5.so
Y le quitamos la #
, es decir activamos el módulo de PHP del Apache.
Por defecto el directorio donde el Apache espera encontrar nuestras páginas es /Library/WebServer/Documents. Pero
esta ruta puede ser poco conveniente para albergar nuestros proyectos, así que en el mismo httpd.conf podemos crearnos
un Virtual Host, para ello añadimos algo como:
<Directory "/mis-proyectos/autentia/php/tutorial/php-unit"> Options FollowSymLinks MultiViews AllowOverride All Order allow,deny Allow from all </Directory> <VirtualHost www.tutorial-phpunit.com> ServerName tutorial-phpunit.com DocumentRoot "/mis-proyectos/autentia/php/tutorial/php-unit" </VirtualHost>
Donde /mis-proyectos/autentia/php/tutorial/php-unit es la ruta donde queremos tener los fuentes de nuestro proyecto PHP.
Nótese también que estamos usando el dominio www.tutorial-phpunit.com, este lo tendremos que haber definido en el
fichero /etc/hosts para que apunte a nuestra máquina:
127.0.0.1 www.tutorial-phpunit.com
También vamos a poner el fichero de configuración de PHP, el php.ini. Crear este
fichero de configuración va a ser muy sencillo porque nuevamente Mac OS X nos lo facilita dándonos uno por defecto,
así sólo tendremos que hacer:
$ sudo cp /etc/php.ini.default /etc/php.ini
Ahora reiniciamos el Apache con el comando:
$ sudo /usr/sbin/apachectl restart
(también podemos hacerlo desde System Preferences… -> Sharing -> Web Sharing)
4. Como instalar PEAR
PEAR, tal como lo definen en su propia página web, es un framework y un sistema de distribución para componentes PHP reutilizables. Básicamente podríamos decir que es un sistema de gestión de paquetes, al estilo de apt-get para los paquetes de Debian, o gem para las gemas de Ruby, o Maven para las librerías de Java.
En esta ocasión lo necesitamos para poder instalar luego PHPUnit.
De nuevo en Mac OS X su instalación es muy sencilla, basta con ejecutar:
$ cd /usr/lib/php ; sudo php install-pear-nozlib.phar
La salida del comando debe ser algo como:
[PEAR] Archive_Tar - installed: 1.3.7 [PEAR] Console_Getopt - installed: 1.3.0 [PEAR] Structures_Graph- installed: 1.0.4 [PEAR] XML_Util - installed: 1.2.1 [PEAR] PEAR - installed: 1.9.4 Wrote PEAR system config file at: /private/etc/pear.conf You may want to add: /usr/lib/php/pear to your php.ini include_path
Ahora tal como nos dice la última línea, vamos a modficiar el fichero/etc/php.ini, para tener en cuenta el
directorio donde se ha instalado PEAR. Para ello en dicho fichero buscamos la línea:
;include_path = ".:/php/includes"
Y la cambiamos por:
include_path = ".:/usr/lib/php/pear"
5. Como instalar PHPUnit
PHPUnit es el estándar de facto para hacer test unitarios en proyectos PHP.
Para instalar PHPUnit basta con hacer:
$ sudo pear config-set auto_discover 1
$ sudo pear install pear.phpunit.de/PHPUnit
La salida de este último comando será algo similar a:
Attempting to discover channel "pear.phpunit.de"... downloading channel.xml ... Starting to download channel.xml (804 bytes) ....done: 804 bytes Auto-discovered channel "pear.phpunit.de", alias "phpunit", adding to registry Attempting to discover channel "pear.symfony-project.com"... downloading channel.xml ... Starting to download channel.xml (865 bytes) ...done: 865 bytes Auto-discovered channel "pear.symfony-project.com", alias "symfony", adding to registry Did not download optional dependencies: phpunit/PHP_Invoker, use --alldeps to download automatically phpunit/PHPUnit can optionally use package "phpunit/PHP_Invoker" (version >= 1.1.0) phpunit/PHP_CodeCoverage can optionally use PHP extension "xdebug" (version >= 2.0.5) downloading PHPUnit-3.6.10.tgz ... Starting to download PHPUnit-3.6.10.tgz (118,595 bytes) ...done: 118,595 bytes downloading File_Iterator-1.3.1.tgz ... Starting to download File_Iterator-1.3.1.tgz (5,157 bytes) ...done: 5,157 bytes downloading Text_Template-1.1.1.tgz ... Starting to download Text_Template-1.1.1.tgz (3,622 bytes) ...done: 3,622 bytes downloading PHP_CodeCoverage-1.1.2.tgz ... Starting to download PHP_CodeCoverage-1.1.2.tgz (132,552 bytes) ...done: 132,552 bytes downloading PHP_Timer-1.0.2.tgz ... Starting to download PHP_Timer-1.0.2.tgz (3,686 bytes) ...done: 3,686 bytes downloading PHPUnit_MockObject-1.1.1.tgz ... Starting to download PHPUnit_MockObject-1.1.1.tgz (19,897 bytes) ...done: 19,897 bytes downloading YAML-1.0.6.tgz ... Starting to download YAML-1.0.6.tgz (10,010 bytes) ...done: 10,010 bytes downloading PHP_TokenStream-1.1.3.tgz ... Starting to download PHP_TokenStream-1.1.3.tgz (9,860 bytes) ...done: 9,860 bytes install ok: channel://pear.phpunit.de/File_Iterator-1.3.1 install ok: channel://pear.phpunit.de/Text_Template-1.1.1 install ok: channel://pear.phpunit.de/PHP_Timer-1.0.2 install ok: channel://pear.symfony-project.com/YAML-1.0.6 install ok: channel://pear.phpunit.de/PHP_TokenStream-1.1.3 install ok: channel://pear.phpunit.de/PHP_CodeCoverage-1.1.2 install ok: channel://pear.phpunit.de/PHPUnit_MockObject-1.1.1 install ok: channel://pear.phpunit.de/PHPUnit-3.6.10
Podemos instalar más módulos de PHPUnit en función de nuestras necesiadads (integración con base de datos, test de Selnium, …),
para ello podemos encontrar más información en
la página de instalación de PHPUnit.
6. Un ejemplo de uso de PHPUnit
Una buena forma de organizar nuestros test es separarlos del código de producción y tener un fichero de test por cada clase o fichero
php, duplicando la estructura de directorios de producción en el directorio de test, como si se tratara de un espejo. Por ejemplo,
la librería Object Freezer sigue al siguiente estructura:
Object Tests |-- Freezer |-- Freezer | |-- HashGenerator | |-- HashGenerator | | `-- NonRecursiveSHA1.php | | `-- NonRecursiveSHA1Test.php | |-- HashGenerator.php | | | |-- IdGenerator | |-- IdGenerator | | `-- UUID.php | | `-- UUIDTest.php | |-- IdGenerator.php | | | |-- LazyProxy.php | | | |-- Storage | |-- Storage | | `-- CouchDB.php | | `-- CouchDB | | | | |-- WithLazyLoadTest.php | | | | `-- WithoutLazyLoadTest.php | |-- Storage.php | |-- StorageTest.php | `-- Util.php | `-- UtilTest.php `-- Freezer.php `-- FreezerTest.php
Nosotros vamos a hacer un ejemplo más sencillo donde vamos a tener un directorio main con el código de producción,
y un directorio test con el código de los test. De esta forma tendremos los ficheros:
<?php /** /mis-proyectos/autentia/php/tutorial/php-unit/AdictosTutorial.php */ class AdictosTutorial { public function greet() { return 'Hola Adictos Al Trabajo !!!'; } } ?>
<?php /** /mis-proyectos/autentia/php/tutorial/php-unit/test/AdictosTutorialTest.php */ require_once 'main/AdictosTutorial.php'; class AdictosTutorialTest extends PHPUnit_Framework_TestCase { public function testReturnGreeting() { $adictos = new AdictosTutorial(); $this->assertEquals('Hola Adictos Al Trabajo !!!', $adictos->greet()); } } ?>
Desde el directorio /mis-proyectos/autentia/php/tutorial/php-unit ejecutaremos el siguiente comando
para lanzar los test:
$ phpunit test
Y obtendremos la siguiente salida con los resultados de la ejecución de los test (cada . representa un test):
PHPUnit 3.6.10 by Sebastian Bergmann. . Time: 0 seconds, Memory: 5.50Mb OK (1 test, 1 assertion)
Esto es sólo la punta del iceberg, así que os recomiendo que leáis la completísima documentación de PHPUnit.
7. Como instalar XDebug
XDebug es una herramienta de depuración y análisis para PHP. En principio la parte de
depuración no nos interesa porque nosotros preferimos el camino del TDD 😉 pero si nos puede venir muy bien para hacer análisis de
rendimiento o para ver la cobertura de nuestros test de PHPUnit.
Para activarlo editamos el fichero /etc/php.ini y buscamos la línea:
;zend_extension="/usr/lib/php/extensions/no-debug-non-ztsV-20090626/xdebug.so"
Le quitamos el ;
para descomentarla y ya estamos listos!
Si vamos a querer hacer análisis de cobertura necesitamos definir nuestra zona horaria, para ello buscamos la línea:
;date.timezone =
Y pondremos los datos de nuestra zona horaria, por ejemplo para Madrid:
; Madrid, Spain, Europe date.timezone = "Europe/Madrid" date.default_latitude = 40.416126 date.default_longitude = -3.696706
Ahora para lanzar los test y medir la cobertura podemos ejecutar:
$ phpunit --coverage-html ./report test
Donde ./report es el directorio donde dejaremos los resultados del análisis de cobertura en formato HTML,
y test es el directorio donde tenemos los tests.
4. Conclusiones
PHP! Quién dijo miedo?!?!?! Haciendo TDD y teniendo una buena batería de test, no hay lenguaje que se nos resista!
5. Sobre el autor
Alejandro Pérez García, Ingeniero en Informática (especialidad de
Ingeniería del Software) y Certified ScrumMaster
Socio fundador de Autentia (Desarrollo de software, Consultoría,
Formación)
mailto:alejandropg@autentia.com
Autentia Real Business Solutions S.L. – «Soporte a Desarrollo»