Configurar TravisCI para que corra nuestros test

Que pasa muchachos?

Hoy vengo con un artículo que me gusta especialmente. Los que me conocen a nivel profesional ya sabrán que me encanta la integración continua, desde que me inicié con Jenkins hasta ahora que para cada proyecto que hago me preparo mi modulo de test y lo engancho con TravisCI. Las maravillas que nos brinda la integración continua nos permite tener siempre una versión depurada de nuestro código y libre de bugs. En el fondo, la integración continua, consiste en hacer un despliegue de control cada vez que vamos a subir a producción y así tenerlo todo bien testeado y probado antes de llevarnos nuestro código a un entorno real.

Como os he dicho, conocí la integración continua con Jenkins. Trabajaba en un proyecto demasiado grande en el que había configuradas varias tareas para el servidor de integración, pero para que os hagáis una idea, cuando hacíamos un pase a producción y mezclábamos la rama de staging contra master, el servidor de Jenkins se encargaba de hacer lo siguiente:

  • Cogía los scripts con la estructura de la base de datos y montaba una.
  • Cogía los scripts con los inserts e iba alimentando a la base de datos.
  • Clonaba el código fuente y minificaba archivos CSS y Javascript.
  • Pasaba un análisis Sonar para evaluar la calidad del código.
  • Hacía un primer pre-compilado temporal de la aplicación.
  • Corría los test unitarios y funcionales.
  • Preparaba la documentación.
  • Compilaba la versión definitiva para el servidor de producción.

Obviamente todo esto lo hacia en varias fases y con distintos servicios enganchados (Jenkins, Maven, Ant, Git, Sonar…), pero toda la potencia de la integración continua reside en la libertad para configurar todas las tareas que te den la gana.

Para este artículo no vamos a hacer una configuración tan complicada, nos dedicaremos a realizar una que, cuando se haga un commit en nuestro repositorio, el servidor de integración continua, de ahora en adelante TravisCI, se encargue de clonar el proyecto y ejecutar los test que tenemos en el directorio de test.

Y para ilustrar el ejemplo, vamos a montar un proyecto con las siguientes tecnologías:

  • Grunt: para el automatizado de tareas, en este caso nos interesan dos, la compresión de ficheros y el lanzamiento de la suite de test que prepararemos.
  • Uglify: para comprimir ficheros, en este caso haremos una versión minificada de nuestra librería.
  • NPM: para la gestión de dependencias.
  • jQuery: para el manejo del DOM.
  • qUnit: para la creación de test unitarios y funcionales.
  • TravisCI: para realizar el proceso de build e integración continua.
  • Github: para almacenar nuestro código fuente.

Comenzando. Instalamos NPM

Cómo he dicho mas arriba, NPM es un gestor de dependencias construido en NodeJs, por lo que necesitamos NodeJs si o si. Si aún no lo tenéis instalado en vuestro equipo lo podéis bajar desde aquí. Cuando ya lo tengáis bajado e instalado en vuestro ordenador, hay que instalar NPM y para ello hay que ejecutar en una terminal lo siguiente:

sudo npm install npm -g

Cuando acabe podéis mirar que se ha instalado correctamente comprobando su versión.

Versión de npm
Versión de npm

Y para inicializar un proyecto con NPM, tan solo tenemos que escribir npm init en una terminal y completar toda la información que nos pide para poder crear correctamente el fichero package.json.

Sobre este fichero nos encargaremos de definir el proyecto. Aquí indicamos el autor, el nombre del proyecto, licencia, repositorio público, versión, dependencias…

Además el fichero package.json será el encargado de decirle a nuestro servidor de integración continua que tareas ha de ejecutar y para ello tenemos que añadir lo siguiente:

    "scripts" : {
        "test": "grunt travis --verbose"
    },

Además, como decía, tenemos que añadir las dependencias que necesitamos en el proyecto, en este caso necesitamos grunt, qunit y uglify y para ello añadimos el bloque de devDependencies:

"devDependencies": {
    "grunt": "^0.4.5",
    "grunt-contrib-qunit": "^0.7.0",
    "grunt-contrib-uglify": "^0.11.0",
} 

A continuación os voy a dejar un packages.json de uno de mis proyectos para que veáis cuales serian sus opciones básicas. Podéis verlo desde mi repositorio de Github.

Definiendo nuestro fichero de tareas

Todas las tareas automatizadas que queramos llevar a cabo las tenemos que definir el fichero gruntfile.js que se situará en la raíz del proyecto pero antes de ello necesitamos instalar qunit y uglify y para ello desde la terminal vamos a hacer uso del gestor de paquetes NPM.

npm install qunit
npm install uglify-js

Al final la terminal nos tiene que escupir algo como lo siguiente:

Terminal después de instalar uglify
Terminal después de instalar uglify

Tal y como hemos indicado en nuestro packages.json, TravisCI necesita de una tarea específica para correr los test, en el packages.json la hemos llamado travis y para ello nuestro es necesario que definamos una tarea travis en nuestro gruntfile.js

module.exports = function(grunt) {
   grunt.initConfig({
    	pkg: grunt.file.readJSON('package.json'),    
    	qunit: {
            files: ['test/*.html']
    	},
    	qunit_junit: {
            options: {
                dest: '_build/test-reports'
            }
        }
   });

   grunt.loadNpmTasks('grunt-contrib-qunit');
   grunt.loadNpmTasks('grunt-qunit-junit');
  	
   grunt.registerTask('default', ['qunit_junit', 'qunit']);
   grunt.registerTask('travis', ['qunit_junit', 'qunit']);
};

Seteando nuestro fichero de TravisCI

Antes de crear nuestro fichero de configuración para TravisCI, es necesario loguearnos en la plataforma y decirle al servidor de integración qué repositorio queremos añadir. El login podemos (y deberíamos) hacerlo con github ya que es allí donde estamos dejando nuestro código.

Según la documentación de TravisCI, se necesita un fichero llamado .travis con todas las especificaciones necesarias para que sepa que hay que hacer.

Fichero de configuración de Travis
Fichero de configuración de TravisCI

Éste es un fichero de configuración mínima. En él estamos indicando que vamos a correr un proyecto construido con NodeJS y que su versión es la 0,10. Para más colmo, podemos controlar la ejecución del script indicando con la directiva before_script que instale en el servidor grunt antes de correr los test. Como he dicho esto es lo más básico que podemos poner en el fichero de configuración, sin embargo, tenemos miles de opciones mas para customizar nuestra build, puedes leerlo aquí.

El fichero de configuración ha de situarse en la raíz del proyecto con el nombre de .travis.yml y no hace falta que hagamos nada mas ya que según la documentación de TravisCI, por defecto va a buscar cualquier tarea que se llame travis y eso ya lo hemos definido un poquito mas arriba, en nuestro gruntfile.

Después de todo esto, cuando hagamos un commit a nuestro repositorio, TravisCI va a detectar que hay cambios y va a lanzar la ejecución del script que construye nuestro build. Si veis la consola dentro de TravisCI, veréis que hace muchísimas cosas, setea el entorno, instala Grunt, minimifica archivos css y js… pero lo que nos interesa es la ejecución de los test.

Test Suite Case OK
Test Suite Case OK

Conclusión

Está claro que no se necesitan de todas estas herramientas para construir software, es más, todos estos conceptos, herramientas y ayudas llevan “muy poco tiempo” entre los desarrolladores en comparación con otras áreas de la informática, sin embargo, cuando estamos trabajando en un proyecto que tiene la capacidad de escalar rápido, necesitamos “olvidarnos” de ciertas tareas para focalizarnos en lo realmente importante, la construcción de software de calidad.

Mucha gente está en contra de la realización de test funcionales/unitarios, por lo general, esa gente van a ser gestores de proyectos a los que solo les importa los deadlines y que te ven como un recurso mas, pues bien, ni puto caso y a aplicar TDD to the limit.

A continuación os dejo con un vídeo de un desarrollador que ha hecho un walkthrough sobre como testear javascrit con TravisCI, no hay desperdicio 😉

Test funcionales con PHPUnit

Llevo ya un buen tiempo sin escribir, si no recuerdo mal mi última entrada fue del mes pasado y es verdad que los últimos posts se han centrado más en temas de SEO, poquito a poco he ido olvidándome del tema del que se iba a centrar el blog en un principio, desarrollo, que para eso soy desarrollador…

En los últimos 6 meses de mi vida me he visto centrado en un mega proyecto en el que se han pasado las buenas prácticas de programación por el beicon por eso en esta entrada quiero hablar de una metodología que me gusta especialmente y es el TDD o Test-Driven Development, para el que no lo sepa, tests a cascoporro.

¿En qué consiste el TDD?

El desarrollo guiado por pruebas se basa en que antes de ponernos a desarrollar un módulo de una aplicación, primero escribamos una serie de pruebas que por su propia naturaleza cuando las vayamos a correr por primera vez fallarán y a partir de estos primeros fallos, vayamos escribiendo y refactorizando el código necesario para hacer que los tests no fallen. Obviamente esta práctica hará que los plazos de entrega se retrasen pero esto le da una robustez al código y a la aplicación que no conseguiríamos sin tener que ir tirando del ya mítico prueba y error y arreglando los bugs que vayan saliendo hasta dejar estable la aplicación.

Dentro del TDD podemos y debemos hacer dos tipos de test diferentes, por un lado tenemos los tests unitarios y por otra parte los tests funcionales.

  • Test unitarios: se centran en probar una parte atómica de nuestra aplicación como puede ser el envío de emails del módulo mailer o la conexión con la base de datos. Normalmente suelo escribir este tipo de test en el CRUD de cada entidad. Para automatizar la ejecución de los test, podemos engancharlos con sistemas de Integración Continua como Jenkins o TravisCI
  • Test funcionales: este tipo de test añaden complejidad a las pruebas y consisten en probar módulos completos de una aplicación como el registro de un usuario o la compra a través de un ecommerce. Estos test los podemos enganchar con Selenium.

A día de hoy podemos realizar test con cualquier lenguaje de programación de los más utilizados y de hecho existen librerias como NUnit para .Net y Mono, JUnit para Java, QUnit para Javascript o de la que vamos a hablar hoy PHPUnit para PHP. Antes de entrar en el meollo tengo que aclarar que yo soy de los que si están desarrollando una webapp en la que, lógicamente, se utilizan varios lenguajes, me gusta realizar pruebas para todos los lenguajes…

Instalar PHPUnit

Tal y como nos explican en su página web.

PHPUnit is a programmer-oriented testing framework for PHP.
It is an instance of the xUnit architecture for unit testing frameworks.

Tenemos varias formas de instalar phpunit en nuestra máquina y todo dependerá del tipo de proyecto que tengamos y del alcance que queramos darle.

Descarga global

Con este método nos estamos asegurando que tendremos la librería instalada para poder utilizar en cualquier proyecto, es tan sencillo como descargárnosla y moverla a cualquier directorio de nuestro sistema.

$ wget https://phar.phpunit.de/phpunit.phar
$ chmod +x phpunit.phar
$ sudo mv phpunit.phar /usr/local/bin/phpunit
$ phpunit --version

Descarga en nuestro proyecto

Nos vamos a la raíz de nuestro proyecto y escribimos en una terminal lo siguiente.

$ wget https://phar.phpunit.de/phpunit.phar
$ php phpunit.phar --version

Descarga a través de Composer

Composer es una herramienta que la utilizamos en el desarrollo de aplicaciones web escritas con Symfony aunque no es algo exclusivo, algunos la consideran la versión hiper mejorada de PEAR. Composer es un instalador de dependencias, para el que venga del mundo Java es el Maven de PHP.

Mediante Composer podemos instalar PHPUnit de dos maneras. Si lo hacemos a través de la terminal tendremos que escribir lo siguiente:

$ composer global require "phpunit/phpunit=4.6.*"

También podemos hacerlos añadiendo la dependencia en nuestro fichero composer.json y actualizar, para ello…

{
    "require-dev": {
        "phpunit/phpunit": "4.6.*"
    }
}

Si eres un poco vaguete y no te gusta tirar de código (no sé que haces viendo este artículo sinceramente) tengo otro método que hará las delicias para el que configura sus programas de manera gráfica y es hacerlo a través de las opciones de configuración del PHPStorm.

Para ello nos tendremos que ir a Tools > Composer > Init Composer. Una vez que se haya inicializado hacemos click derecho en el proyecto y seleccionamos la opción de Composer | Add Dependency… y buscamos phpunit/phpunit.

Añadiendo la dependencia de PHPUnit a Composer
Añadiendo la dependencia de PHPUnit a Composer

Una vez que se haya instalado, podremos ver que el directorio vendor, es el que guarda las librerías que necesitará nuestro proyecto, se ha creado un directorio para PHPUnit.

Para que PHPStorm sepa que hemos instalado esta librería y podamos ejecutar los test tendremos que decírselo a través de la configuración global del proyecto, para ello nos dirigimos a Settings > PHP > PHPUnit. Hay varias formas de configurarlo pero lo más fácil es cargando el autoload de nuestras librerías.

¿Desde dónde voy a cargar phpunit?
¿Desde dónde voy a cargar phpunit?

Una vez configurado ya podemos empezar a escribir nuestros test. Esta librería tiene muchísimos métodos para probar cualquier funcionalidad que imaginemos por eso es recomendable que tengas la documentación a mano, pero para que os vaya sonando, un test sencillito se vería tal que así.

    class NotasTest extends PHPUnit_Framework_TestCase{
           public function testAssertTrue(){
                $this->assertTrue(1=1);
           }
           public function testAssertFalse(){
                $this->assertFalse(1=0);
           }
    }

Una vez que ejecutemos estos test, obtendremos algo parecido a lo siguiente.

Los tests han pasado
Los tests han pasado

Con Symfony hay un “problemilla” a la hora de probar el CRUD de nuestras entidades y es que cuando se van a ejecutar las pruebas, el framework todavía no ha cargado el Kernel de la aplicación y por ende el contenedor de servicios no contiene la referencia a Doctrine para poder operar con la base de datos, por ello, yo me he sacado de la manga una implementación de clases base e interfaces que resuelven el problema. Para que se vea con claridad pondré un ejemplo de un proyectillo mio…

Diagrama de mi solución
Diagrama de mi solución

Tal y como se puede ver en el diagrama de la clase base, se hace uso de tres funciones públicas que son necesarias para hacer que esto funciones.

  • Función setUp(): esta función se ejecuta antes de que se ejecute nuestro test, en ella se definen temas de configuración como la carga del kernel y del entity manager. Su ejecución la hace de manera automática la librería liberándonos a nosotros de cualquiera tarea salvo de implementarla y escribir en ella lo que consideremos importante.
  • Función tearDown(): se ejecuta cuando ha terminado de correr nuestro test, normalmente se utiliza para terminar tareas con la base de datos como hacer un flush o un rollback en el caso en que no trabajemos en una base de datos de test.
  • Función getContainer(): como su nombre indica nos devuelve el contenedor de servicios, así de simple.

Voy a dejar el código de cada clase en Pastebin para que podáis pillarlo y utilizar mi implementación en vuestros test pero a cambio os pido que le deis un +1 en Google, un Me gusta en Feisbú o lo compartáis a través de twittah para que así llegue a más personas 😉

[sociallocker id=446]

Descarga clase base

Descarga Interface

Descarga Test

[/sociallocker]

¡Hasta que volvamos a olernos!