Hace ya bastante tiempo que en el blog estamos hablando sobre PhpUnit, TDD e incluso hemos nombrado a Silex, creo que ya va siendo hora de crear un pequeño proyecto en el que aplicar todo esto. Llevo ya unos días trabajando sobre mi cuenta de github (https://github.com/jeslopcru) en un pequeño proyecto PHP donde utilizo Silex, PHP y TDD. Es solo una pequeña prueba de concepto para ver que es posible hacer TDD utilizando Silex y por tanto también podría ser posible hacer TDD utilizando Symfony2.
En este proyecto montaremos todo el entorno utilizando Composer junto PhpUnit y symfony/browser-kit (para poder hacer tests funcionales a los controladores symfony). También utilizaremos monolog para los logs. Así que vamos manos a la obra.
Información acerca del proyecto
Vamos a crear una calculadora con la que podremos hacer operaciones básicas, para utilizarla haremos uso del navegador, es decir, como URL utilizaremos algo así http://www.example.com/add?numberA=2&numberB=3 y la respuesta será la suma de ambos parámetros.
Si, es cierto, en un primer momento no parece un gran proyecto, pero lo importante de esto es que construiremos todo esto utilizando el microframework Silex y trabajando mediante TDD.
Creando el proyecto
Para crear el proyecto lo más cómodo es utilizar una herramienta como virtualhost.sh. Este script permite crear toda la configuración necesaria para crear un crear un site en Apache, mapear la dirección en etc/hosts y configurar el log de apache. Para instalarlo solo tenemos que abrir un terminal y escribir brew install virtualhost.sh
Una vez que lo tengamos instalado solo tenemos que crear el proyecto, nosotros vamos a crear un proyecto llamado http://testingsilex.dev
Solo tenemos que responder a una serie de preguntas y al terminar tendremos algo como esto:
Ahora solo tenemos que abrir nuestro IDE favorito, en nuestro caso vamos a utilizar PHPStorm, pero podríamos hacer TDD utilizando Eclipse, Sublime o cualquier otro editor de texto. Además ya tenemos instalado lo más importante composer 😉
Utilizando composer
Composer es una herramienta par la gestión de dependencias en PHP. Básicamente editamos un archivo JSON en donde tenemos declaradas las dependencias, después con los comandos composer install
para la primera instalación y composer update
para ir actualizando a medida que vayamos modificando el fichero JSON.
Aquí tenemos nuestro primer fichero composer.json
{
"name": "jesuslc/testingsilex",
"description": "testing siles",
"minimum-stability": "dev",
"license": "Open Source",
"authors": [
{
"name": "JesusLC",
"email": "me@example.com"
}
],
"require-dev": {
"phpunit/phpunit": "3.7.*",
"silex/silex" : "1.*"
}
}
Una vez tenemos el archivo solo tenemos que hacer composer install
una vez se hayan descargado todas las dependencias tendremos una carpeta vendor con todas las dependencias.
Creando la aplicación con Silex
Ahora solo tenemos que crear la aplicación para comprobar que las dependencias se han instalado correctamente 🙂 Para ello creamos una carpeta app y dentro de la misma un archivo llamado bootstrap.php
<?php
require_once(__DIR__ . '/../vendor/autoload.php');
$app = new Silex\Application;
$app
->match('/', function () {return 'Running';})
->method('GET');
return $app;
En este archivo es donde incluiremos las rutas, ahora creamos el index.php con el que haremos funcionar la aplicación
<?php
$app = require_once(__DIR__ . '/../app/bootstrap.php');
$app->run();
Finalmente tendremos algo como esto:
Ahora solo tenemos que abrir un navegador y entrar en http://testingsilex.dev para ver si todo está funcionando, además siempre podemos entrar en la carpeta log y ver que está pasando leyendo el log 😉
Añadiendo log a la aplicación
Una de las cosas más útiles a la hora de programar y de solucionar problemas es disponer de un buen log, así que lo que vamos a hacer es algo que nos servirá para aprender 2 cosas, 1 es como añadir log a un proyecto Silex y la otra es como utilizar composer para actualizar dependencias. Lo que tenemos que hacer es actualizar nuestro fichero composer.json, para dejarlo así:
{
"name": "jesuslc/testingsilex",
"description": "testing siles",
"minimum-stability": "dev",
"license": "Open Source",
"authors": [
{
"name": "JesusLC",
"email": "me@example.com"
}
],
"require-dev": {
"phpunit/phpunit": "3.7.*",
"symfony/browser-kit": ">=2.3,<2.4-dev"
},
"require": {
"silex/silex" : "1.*",
"monolog/monolog": ">=1.6.0"
}
}
`
Una vez tenemos el composer.json tenemos que hacer composer update
para añadir las nuevas dependencias al proyecto.
Quizás sea necesario crear un fichero llamado ‘dev.log‘ dentro de la carpeta logs y darle permisos desde un terminal así chmod 777 logs/
Ahora vamos a añadir log dentro de la aplicación, tan solo tenemos que cargar la librería Monolog y utilizarla, así que abrimos el archivo bootstrap.php y la dejamos así:
<?php
require_once(__DIR__ . '/../vendor/autoload.php');
use Silex\Provider\MonologServiceProvider;
$app = new Silex\Application;
$app->register(new MonologServiceProvider(), array(
'monolog.logfile' => __DIR__ . '/../logs/dev.log'
));
$app
->match('/', function () use ($app) {
$app['monolog']->addInfo('Logging example in the status route');
return 'Up and running';
})
->method('GET|POST');
return $app;
básicamente lo que hacemos aquí es crear un servicio MonologServiceProvider y añadir trazas de log así $app['monolog']->addInfo('Logging example in the status route');
Ahora si accedemos a http://testingsilex.dev veremos como en archivo dev.log de la carpeta logs empiezan a aparecer trazas de log como esta:
[2014-05-07 20:41:10] myapp.INFO: Matched route "GET_POST_" (parameters: "_controller": "{}", "_route": "GET_POST_") [] []
[2014-05-07 20:41:10] myapp.INFO: > GET / [] []
[2014-05-07 20:41:10] myapp.INFO: Logging example in the status route [] []
[2014-05-07 20:41:10] myapp.INFO: < 200 [] []
Ya solamente nos queda configurar PHPUnit para empezar a hacer TDD con Silex
Configurando PHPUnit
Configurar PhpUnit para que podamos ejecutar test es sencillo, solo tenemos que crear en el directorio raíz de la aplicación un archivo xml llamado phpunit.xml.dist y una carpeta llamada tests donde crearemos todos los test
El archivo XML debe contener esto:
<?xml version="1.0" encoding="UTF-8"?>
<!-- http://www.phpunit.de/manual/current/en/appendixes.configuration.html -->
<phpunit
backupGlobals = "false"
backupStaticAttributes = "false"
colors = "true"
convertErrorsToExceptions = "true"
convertNoticesToExceptions = "true"
convertWarningsToExceptions = "true"
processIsolation = "false"
stopOnFailure = "false"
syntaxCheck = "false"
bootstrap = "vendor/autoload.php" >
<testsuites>
<testsuite name="Silex Tutorial Test Suite">
<directory>tests/</directory>
</testsuite>
</testsuites>
</phpunit>
Básicamente en este archivo de configuración indicamos a PHPUnit en que carpeta están los tests y donde el fichero de autoload para cargar todas las librerías del proyecto. Llegados a este punto deberemos tener el proyecto más o menos así:
Con esto tenemos configurado todo el proyecto para empezar a realizar tests y empezar a fondo con TDD en Silex.
Nuestros primeros tests
Llegados a este punto, debemos estar seguros de que todo lo que hemos hecho funciona y que esta bien configurado. La mejor manera de probarlo es hacer nuestro primeros tests.
Nuestro primer test con Phpunit solo sera un simple assertTrue, así que lo que tenemos que hacer es dentro de la carpeta tests, crear un archivo php llamado «Test.php», este archivo contendrá lo básico para hacer correr nuestro primer test. El contenido de nuestro primer test será más o menos este:
<?php
class Test extends PHPUnit_Framework_TestCase
{
public function testNothing()
{
$this->assertTrue(true,true);
}
}
Para ejecutarlo, podemos utilizar PHPStorm o un Terminal. Con un terminal es tan sencillo como navegar a la carpeta del proyecto y ejecutar el comando phpunit
Ahora solo nos queda comprobar que el routing esta correcto y que podemos incluso testear el log de la aplicación. para comprobar que el routing esta funcionando correctamente mediante el uso de test unitarios.
Utilizando «symfony/browser-kit» vamos a poder realizar test unitarios con los que testar no solo los métodos, sino también las peticiones GET, POST, … para comprobar los parámetros de las request, etc.
Así que para poder testar la aplicación lo que debemos hacer es crear otro test deserto lee la carpeta tests, llamado «BasicTest.php», en este archivo crearemos una clase con 2 métodos, uno de ellos arrancará la aplicación (createaplication) y el otro testará que la ruta que hemos creado y su respuesta son correctas.
<?php
namespace TutorialTest;
use Silex\WebTestCase;
class BasicTest extends WebTestCase
{
public function createApplication()
{
$app = require __DIR__ . '/../app/bootstrap.php';
$app['debug'] = true; return $app;
}
public function testStatusRoute()
{
$client = $this->createClient();
$client->request('GET', '/');
$this->assertTrue($client->getResponse()->isOk());
$this->assertEquals(
'Running with log',
$client->getResponse()->getContent()
);
}
}
Ahora podemos volver a lanzar los test para comprobar que todo sigue funcionando.
Conclusiones
Ya lo tenemos todo montado ahora solo falta empezar a crear la funcionalidad del proyecto. Como hemos visto configurar PHPunit con Silex es bastante sencillo si utilizamos Composer y testar aplicaciones es una tarea complicada, no por el hecho de hacer test, sino por el hecho de que cuando se empieza con TDD los pasitos son muy pequeños y nos da la sensación de ser las personas más lentas del mundo escribiendo cosas (al menos a mi). Cuando hago TDD me siento lento y torpe porque existen partes del código que escribiría en un minuto, pero el tener que hacer el test antes, pensarlo, refactorizar, en resumen ir dando pasitos pequeños es algo muy duro al principio.
Ahora, bien es cierto que cuando terminas de escribir el código, lanzas los test y ves que todo esta OK, haces modificaciones del código mucho más tranquilo.
Bueno, con esto ya podemos dar nuestros primeros pasos haciendo TDD con aplicaciones Silex, ya lo tenemos todo configurado y sabemos que los tests funcionan, solo queda empezar a trabajar. En el siguiente post empezaremos a trabajar con Silex realizando los tests antes que el código.
Muy bien y interesante.
Esperamos los proximos partes, es interesante ver como compruebas el controller y el view(la interfaz).
Me gustaMe gusta