DEV Community

Cover image for Agregar PHPUnit a tu proyecto PHP con composer
Javier Ledezma
Javier Ledezma

Posted on • Originally published at blog.javierledezma.com

Agregar PHPUnit a tu proyecto PHP con composer

Con el tiempo, los proyectos y librerías tienden a evolucionar ya sea para agregar nuevas funcionalidades o simplemente para mejorar el rendimiento y desempeño. Una manera de garantizar que nuestra librería se mantendrá estable a lo largo de éstas mutaciones es a través de una serie de pruebas.

Una prueba es un fragmento de código que se asegura de que una función o clase haga exactamente lo que se le designó.

PHP Unit es un framework que nos permite crear y ejecutar pruebas para nuestro código de una manera muy sencilla, a demás de brindarnos herramientas para revisar que tanto porcentaje de nuestro código ha sido probado (coverage) y la complejidad de nuestro código (complexity).

Para ésta guia utilizaremos el código creado en el blog "Inicializa un proyecto PHP usando composer" para establecer los primeros pasos, si deseas leerlo puedes ingresar aquí, de lo contrario, te dejo el repositorio en github, el cual puedes clonar o descargar como zip.

La estructura inicial de nuestro proyecto debería verse de la siguiente manera:

fabulosa_libreria/
|--- composer.json
|--- README.md
|--- src/
    |--- funciones_globales.php
    |--- Mensajes.php
    |--- Utilerias/
        |--- Calculadora.php
Enter fullscreen mode Exit fullscreen mode

Primero que nada debemos instalar PHPUnit, teniendo composer esto se fácilita bastante, solo debemos ejecutar el siguiente comando:

composer require --dev phpunit/phpunit
Enter fullscreen mode Exit fullscreen mode

Se utiliza la bandera --dev para indicarle a composer que la libreŕia solo e utilizará en entornos de desarrollo.

Una vez ejecutado éste comando, composer se encargará de realizar la instalación de todos los elementos necesarios. Estos elementos se encontrarán situados en la carpeta vendor .

Si estás utilizando algún sistema de control de versiones, es importante que agregues la carpeta vendor a los archivos ignorados, ya que con composer se pueden volver a instalar fácilmente.

Si queremos asegurarnos de que phpunit se ha instalado correctamente, podemos revisar el archivo composer.json el cual debería tener una nueva entrada llamada require-dev con algo similar a lo siguiente:

"require-dev": {
  "phpunit/phpunit": "^8.5"
}
Enter fullscreen mode Exit fullscreen mode

En esta ocasion, composer instaló la versión 8.5 de phpunit, ésto puede variar dependiendo de la fecha en la que se lleve a cabo ésta guia.

Regsitrar carpeta de pruebas en composer

Para organizar nuestro proyecto crearemos la carpeta pruebas en ella colocaremos de manera ordenada todas las pruebas que se irán crando a lo largo del desarrollo, ésta carpeta estará registrada en composer para poder utilizar los nombres de espacio de nuestro proyecto sin complicaciones.

Para ello, creamos la carpeta en la raiz de nuestro proyecto, quedando una estructura similar a la siguiente:

fabulosa_libreria/
|--- composer.json
|--- README.md
|--- src/
    |--- funciones_globales.php
    |--- Mensajes.php
    |--- Utilerias/
        |--- Calculadora.php
|--- pruebas/
Enter fullscreen mode Exit fullscreen mode

Ahora, registraremos la carpeta pruabas con el namespace Javleds\Pruebas, para ello, editaremos el archivo composer.json, y agregaremos la entrada autoload-dev.psr-4, de la siguiente manera:

{
  "name": "javleds/fabulosa-libreria",
  "description": "Mi fabulosa librería",
  "type": "library",
  "authors": [
    {
      "name": "Javier Ledezma",
      "email": "contact@javierledezma.com"
    }
  ],
  "version": "1.0",
  "license": "MIT",
  "autoload": {
    "psr-4": {
      "Javleds\\FabulosaLibreria\\": "src/"
    },
    "files": [
      "src/funciones_globales.php"
    ]
  },
  "autoload-dev": {
    "psr-4": {
      "Javleds\\Pruebas\\FabulosaLibreria\\": "pruebas/"
    }
  },
  "require-dev": {
    "phpunit/phpunit": "^8.5"
  }
}

Enter fullscreen mode Exit fullscreen mode

Nota: En el ejemplo utilizamos el namespace Javleds\FabulosaLibreria, pero tu deberias utilizar un nombre de espacio único para tu proyecto compuesto de USUARIO_GIT\NOMBRE_LIBRERIA.

A diferencia de la entrada autoload, las clases y archivos registrados en la entrada autoload-dev solo estarán disponibles para entornos de desarrollo.

Es tiempo de revisar si phpunit funciona correctamente, para ello, crearemos una prueba para la funciónelementoAleatorio que se encuentra en el archivo funciones_globales.php, esta función luce así:

if (! function_exists('elementoAleatorio')) {
    /**
     * @param array $elementos
     *
     * @return mixed
     */
    function elementoAleatorio($elementos)
    {
        $valorMaximo = count($elementos) - 1;
        $indiceAleatorio = rand(0, $valorMaximo);
        return $elementos[$indiceAleatorio];
    }
}
Enter fullscreen mode Exit fullscreen mode

La función recíbe un arreglo con elementos de cualquier tipo y regresa un elemento de manera aleatoria, nuestra prueba se encargará de asegurarse que la función elementoAleatorio nos regresa siempre algún valor, y cuyo valor debe estar contenido en ese arreglo. Crearemos el archivo pruebas/FuncionesGlobalesTest.php con lo siguiente:

<?php

namespace Javleds\Pruebas\FabulosaLibreria;

use PHPUnit\Framework\TestCase;

final class FuncionesGlobalesTest extends TestCase
{
    public function testElementoAleatorioDebeRegresaUnValor()
    {
        $elementos = [1, 2, 3, 4, 5];
        $elemento = elementoAleatorio($elementos);

        $this->assertNotNull($elementos);
        $this->assertContains($elemento, $elementos);
    }
}
Enter fullscreen mode Exit fullscreen mode

Las prubas deben extender de la clase PHPUnit\Framework\TestCase, en ésta clase se encuentan todas las utilidades que nos brinda PHPUnit para crear pruebas.

La prueba que creamos inicializa un arreglo con los valores del 1 al 5, posteriormente manda a llamar la función elementoAleatorio y revisa que:

  1. El valor regresado no sea nulo
  2. Que el valor regresado por la función exista dentro del arreglo inicial.

Ahora, llamaremos le indicaremos a PHPUnit que queremos ejecutar esa prueba con el comando:

./vendor/bin/phpunit pruebas/
Enter fullscreen mode Exit fullscreen mode

Este comando buscará dentro de la carpeta pruebas todos los archivos que terminen con la palabra Test.php y ejecutará las funciones que comiencen con el sufijo test o tengan la anotación @test.

Si todo sale bien, podremos ver un resultado similar al siguiente:

PHPUnit 8.5.8 by Sebastian Bergmann and contributors.

.                                                                   1 / 1 (100%)

Time: 24 ms, Memory: 4.00 MB

OK (1 test, 2 assertions)
Enter fullscreen mode Exit fullscreen mode

Esto quiere decir que se ejecuto 1 prueba, de las cuales 1 cumple con lo establecido, en ella se realizaron 2 asersiones (la del valor nulo y la del valor existe en el arreglo).

Creando un archivo de configuración de PHPUnit

Ahora bien, ya sabiendo que podemos ejecutar pruebas, lo ideal sería configurar PHPUnit para no tener que específicar las rutas de nuestras pruebas en cada ocasión, a demás de otra serie de configuraciones. Para ello crearemos el archivo phpunit.xml en la raíz del proyecto con lo siguiete:

<?xml version="1.0" encoding="UTF-8"?>

<phpunit 
    bootstrap = "vendor/autoload.php"
    colors = "true"
    convertErrorsToExceptions = "true"
    convertNoticesToExceptions = "true"
    convertWarningsToExceptions = "true">

    <testsuites>
        <testsuite name="Pruebas del proyecto">
            <directory>pruebas</directory>
        </testsuite>
    </testsuites>

    <filter>
        <whitelist>
            <directory suffix=".php">src/</directory>
        </whitelist>
    </filter>
</phpunit>
Enter fullscreen mode Exit fullscreen mode

El directorio debería quedar de la siguiente manera:

fabulosa_libreria/
|--- composer.json
|--- README.md
|--- src/
    |--- funciones_globales.php
    |--- Mensajes.php
    |--- Utilerias/
        |--- Calculadora.php
|--- pruebas/
|--- phpunit.xml
Enter fullscreen mode Exit fullscreen mode

En el archivo podemos encontrar las configuraciones necesarias para nuetro proyecto, pero en cuanto se requieran más configuraciones, puedes irlas agregando acorde a la documentación oficial, más información aquí

En cuyo documento tenemos:

  • phpunit.bootrstrap: Le indicamos a PHPUnit que debe cargar el archivo vendor/autoload.php antes de comenzar a ejecutar las pruebas, por si no estás muy familiarizado con composer, el archivo vendor/autoload.php contiene el registro de todas clases y funciones de las que depende nuestro proyecto, incluyendo las que registramos manualmente en las seccion autoload del archivo compoaser.json, este archivo se crea automáticamente por composer cada que instalamos una nueva dependencia y/o cuando ejecutamos el comando composer dump-autoload.
  • phpunit.colors: Le indicamos a PHPUnit que al terminar nos indique con colores rojo y verde el resultado de nuestras pruebas. Rojo cuando hay errores o verde cuando todo se ejecutó correctamente.
  • phpunit.convertErrorsToExceptions: Le indicamos a PHPUnit que convierta cualquier error en una ecepción.
  • phpunit.convertNoticesToExceptions: Le indicamos a PHPUnit que convierta cualquier evento de información en una ecepción.
  • phpunit.convertWarningsToExceptions: Le indicamos a PHPUnit que convierta cualquier alerta de PHP en una ecepción.
  • testsuites.testsuite: Le indicamos a PHPUnit cual es el directorio que contiene nuestras pruebas, en este apartado se pueden crear grupos de pruebas dependiendo de su función, pero en éste ejemplo solo tenemos una para todo el proyecto.
  • filter.whitelist: Esta configuración le indica a PHPUnit que los archivos contenidos en el directorio src deberán ser contemplados para calcular la covertura de pruebas.

Ahora bien, para ejecutar nuestra suite de pruebas solamente debemos ejecutar el comando:

./vendor/bin/phpunit
Enter fullscreen mode Exit fullscreen mode

De manea automática, este comando leerá el archivo phpunit.xml y ejecutara las suites declaradas allí, ya no será necesario indicarle nada más.

Covertura de código

Otra ventaja de tener definidas suites de pruebas en el arcivo phpunit.xml es que podemos generar un reporte con la covertura de pruebas que tiene nuestro código, PHPUnit nos brinda diversos formatos para éste reporte, yo te recomiendo el formato HTML, quien te genera una página web con los resultados.

Para genera ese reporte solo debemos agregar la bandera --coverage-html con el nombre del directorio en el que se guargarán los archivos, ejemplo:

./vendor/bin/phpunit --coverage-html coverage
Enter fullscreen mode Exit fullscreen mode

Este comando ejecutara todas las pruebas del archivo phpunit.xml y a demás nos creará la carpeta coverage con algunos archivos, nosotros abriremos con nuestro navegador de preferencia el archivo coverage/index.html y debe mostrarnos de manera interactiva que archivos ya tienen pruebas y qué procentaje de ese código ha sido probado. Si seguiste el tutorial con el código del blog "Inicializa un proyecto PHP usando composer", entonces, deberías poder ver algo similar a lo siguiente:

coverage

En dónde el reporte nos indica que el archivo src/funciones_globales.php tiene un 100% de covertura, sin embargo, no tenemos pruebas definidas para src/Mensajes.php y src/Utilerias/Calculadora.

Conclusión y tips

Agregar o no pruebas siempre ha sido un tema de controversia, en mi experiencia, las pruebas son necesarias si quieres que tu proyecto sea escalable y esté pensado para ser un proyecto colaborativo. Las pruebas permiten que tu código crezca y a demás se pueda refactorizar con el tiempo sin temor a dañar las partes de código que ya funcionan, a demás de que te permiten integrar herramientas de integración y despliegue continuo.

Tips:

  • Antes de comenzar a escribir código, se recomienda diseñar una prueba primero, posterior a la prueba, comenzar a desarrollar la funcionalidad que esperas siempre se apegará al proposito original. Realizar la prueba y posteriormente el código es una buena práctica y una métodología conocida como TDD (Test Driven Design).
  • No te preocupes por tener el 100% de covertura de tu código, enfocate en probar aquellas cosas que requieran procesamiento de la computadora, por ejemplo, operaciones matematicas complejas, creaciónes de archivos, inserciónes y ediciones de la base de datos, entre otros. Un 80% de covertura es muy aceptable.
  • Piensa tus pruebas orientadas a casos de uso o a tus reglas de negocio.
  • Elabora pruebas sencillas de leer, ninguna prueba debe ser más compleja que el código que se está probando.
  • Si tu proyecto consume API's de terceros, procura que ninguna de tus pruebas utilice esos servicios, hay técnicas para "simular" una llamada a una API, estas se conocen como mocks o stubs, puedes revisar un poco más aquí.
  • Dentro de tu carpeta de pruebas/ intenta ordenar el código de tal manera que sea un espejo de la carpeta src/, esto facilitará el mantenimiento de las pruebas y mantendrá el código organizado, un ejemplo para el proyecto actual sería:
  fabulosa_libreria/
  |--- src/
    |--- funciones_globales.php
    |--- Mensajes.php
    |--- Utilerias/
        |--- Calculadora.php
  |--- pruebas/
    |--- FuncionesGlobalesTest.php
    |--- MensajesTest.php
    |--- Utilerias/
        |--- CalculadoraTest.php
Enter fullscreen mode Exit fullscreen mode

¡Gracias por tu tiempo!, esta guia es un poco larga, pero espero que te sirva mucho en tu día a día, te invito a que agregues pruebas a tus proyectos y si ya has trabajdo con PHPUnit te invito a que nos cuentes tu experiencia en los comentarios.

¡Hasta la próxima!

Top comments (0)