PHPUnit

PHPUnit es el framework de testing estándar para PHP, utilizado para crear pruebas unitarias, de integración y funcionales. Se basa en la filosofía de TDD - Test Driven Development y permite garantizar la calidad del código mediante pruebas automatizadas.

  • TestCase: clase base de PHPUnit desde la cual heredan todas las pruebas.
  • Assertions: métodos para verificar resultados esperados (assertEquals, assertTrue, assertCount, etc.).
  • Fixtures: código de inicialización y limpieza antes o después de cada prueba (setUp, tearDown).
  • Mocks y Stubs: objetos simulados que reemplazan dependencias reales durante las pruebas.
  • Data Providers: mecanismos para ejecutar una misma prueba con distintos conjuntos de datos.
  • Annotations: metadatos usados para definir comportamiento (@test, @dataProvider, @depends, @group, etc.).

⚙️ Instalación y Configuración

PHPUnit se instala típicamente a través de Composer:

composer require --dev phpunit/phpunit

`

Para verificar la instalación:

vendor/bin/phpunit --version

Archivo de configuración recomendado (phpunit.xml):

<?xml version="1.0" encoding="UTF-8"?>
<phpunit bootstrap="vendor/autoload.php"
         colors="true"
         verbose="true">
    <testsuites>
        <testsuite name="App Test Suite">
            <directory>tests</directory>
        </testsuite>
    </testsuites>
</phpunit>

🧩 Estructura Básica de una Prueba

<?php

use PHPUnit\Framework\TestCase;

class MathTest extends TestCase
{
    public function testAddition()
    {
        $this->assertEquals(4, 2 + 2);
    }
}
  • Cada clase de prueba debe extender TestCase.
  • Los métodos de prueba comienzan con test o usan la anotación @test.
  • Las afirmaciones verifican resultados esperados.

🧱 Fixtures y Ciclo de Vida

PHPUnit ejecuta métodos especiales antes y después de cada prueba o conjunto de pruebas:

protected function setUp(): void
{
    // Preparar entorno antes de cada test
}

protected function tearDown(): void
{
    // Limpiar entorno después de cada test
}

public static function setUpBeforeClass(): void
{
    // Ejecutado una vez antes de todas las pruebas de la clase
}

public static function tearDownAfterClass(): void
{
    // Ejecutado una vez después de todas las pruebas de la clase
}

🧪 Assertions Comunes

Método Descripción
assertTrue($cond) Verifica que la condición sea verdadera
assertFalse($cond) Verifica que sea falsa
assertEquals($a, $b) Compara igualdad de valores
assertSame($a, $b) Compara igualdad estricta
assertCount($n, $arr) Verifica cantidad de elementos
assertInstanceOf($class, $obj) Comprueba tipo de objeto
assertStringContainsString($needle, $haystack) Verifica substring
assertArrayHasKey($key, $arr) Verifica clave en array

🧠 Mocks y Dobles de Prueba

Los mocks permiten aislar dependencias durante las pruebas.

$mock = $this->createMock(UserRepository::class);
$mock->method('find')
     ->willReturn(new User('John'));

$service = new UserService($mock);
$result = $service->getUser('123');
$this->assertEquals('John', $result->getName());

Tipos de dobles:

  • Stub: devuelve valores fijos.
  • Mock: verifica llamadas esperadas.
  • Spy: registra interacciones para verificarlas después.
  • Dummy: objeto sin comportamiento, solo relleno.

📦 Data Providers

Permiten ejecutar una misma prueba con múltiples entradas:

/**
 * @dataProvider additionProvider
 */
public function testAdd($a, $b, $expected)
{
    $this->assertEquals($expected, $a + $b);
}

public static function additionProvider(): array
{
    return [
        [2, 2, 4],
        [2, 3, 5],
        [5, 5, 10],
    ];
}

🔗 Dependencias entre Tests

Una prueba puede depender del resultado de otra:

public function testUserCreation(): User
{
    $user = new User('Alice');
    $this->assertNotNull($user);
    return $user;
}

/**
 * @depends testUserCreation
 */
public function testUserEmail(User $user)
{
    $user->setEmail('alice@example.com');
    $this->assertStringContainsString('@', $user->getEmail());
}

🧰 Integración con CI/CD

PHPUnit se integra fácilmente con sistemas de CI/CD como GitHub Actions, GitLab CI, Jenkins o Docker. Ejemplo con GitHub Actions (.github/workflows/phpunit.yml):


yaml name: PHPUnit Tests

on: [push, pull_request]

jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Set up PHP uses: shivammathur/setup-php@v2 with: php-version: ‘8.3’ - name: Install dependencies run: composer install - name: Run PHPUnit run: vendor/bin/phpunit


---

## 📊 Cobertura de Código


PHPUnit puede generar informes de cobertura usando Xdebug o PCOV.


bash vendor/bin/phpunit –coverage-html coverage/ ```

Resultado:

  • Carpeta /coverage con informe HTML.
  • Métricas de líneas, métodos y clases cubiertas.
  • Útil para integrarlo con SonarQube o Codecov.

🧱 Patrones y Buenas Prácticas

  • Nombra los tests con claridad (testShouldReturnValidResponse).
  • Una sola aserción principal por prueba.
  • Evita dependencias externas (DB, red) → usa mocks.
  • Automatiza la ejecución con CI.
  • Mantén las pruebas rápidas, independientes y determinísticas.
  • Separa unit tests, integration tests y feature tests.

🧭 Casos de Uso y Ejemplos Reales