PHPUnit
- Testing
- PHP
- docs
- guias
- PHPUnit - Guía avanzada y patrones de testing profesional
-
Testing de APIs REST y Microservicios con PHPUnit y Mockery
🧠 Conceptos Fundamentales
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
testo 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
/coveragecon 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
- Validar controladores y servicios en frameworks como Laravel, Symfony, Slim.
- Probar integraciones con bases de datos SQLite en memoria.
- Simular API externas con mocks o Mockery.
- Ejecutar tests paralelos con
--parallel. - Generar reportes XML para herramientas de análisis continuo.
📚 Recursos y Referencias
- Documentación Oficial de PHPUnit
- Assertions Reference
- Mock Objects
- Test Suites y Configuración
- TDD - Test Driven Development
- CICD
- SonarQube
- PHP
¿Te gusta este contenido? Suscríbete vía RSS