PHPUnit, al igual que la mayoría de los frameworks de testing, se basa fuertemente en el supuesto de que la aplicación a verificar está desarrollada bajo el paradigma de Orientación a Objetos.
Sin embargo, es muy común en nuestros días encontrarnos con aplicaciones tipo spaghetti… ¿es posible hacer testing automatizado sobre ellas?
La respuesta es sí.
Claro que las respuestas a qué testear y cómo testear son un poco diferentes.
Qué puede testearse en una aplicación que no usa objetos
Obviamente, no será posible verificar una clase porque… la aplicación no tiene clases.
De modo que podemos testear:
- La página que se presentará al usuario (Lo que podríamos asemejar a un test funcional)
- El resultado de ejecutar alguna función en particular
- El resultado de correr algún script
Cómo testear el resultado de una página php
Para este escenario nos tendremos que valer de un pequeño truco: las funciones ob_start y ob_get_clean (Además de tener instalado phpUnit, claro).
La idea es muy simple en realidad.
Se crea un caso de test, se abre un buffer y se incluye el archivo que queremos validar.
A continuación se levantan los contenidos del buffer y se examinan usando assertions.
Veamos un ejemplo simple:
El archivo que queremos validar se llama wrong.php
<html> <body> <p><?php echo 'Bye bye world'; ?></p> </body> </html>
Y este sería el caso de test:
<?php use PHPUnit\Framework\TestCase; class PageTest extends TestCase { public function testGreeting() { ob_start(); require_once 'wrong.php'; $this->assertRegExp('/<p>Hello World!<\/p>/', ob_get_clean()); } }
Para correr el test usamos el comando vendor/bin/phpunit PageTest.php
y la salida será:
PHPUnit 9.3.7 by Sebastian Bergmann and contributors. F 1 / 1 (100%) Time: 00:00.004, Memory: 4.00 MB There was 1 failure: 1) PageTest::testGreeting Failed asserting that '<html>\n <body>\n <p>Bye bye world</p>\n </body>\n </html>\n ' matches PCRE pattern "/<p>Hello World!<\/p>/". /home/mauro/Code/testing/PageTest.php:11 FAILURES! Tests: 1, Assertions: 1, Failures: 1.
Cómo testear el resultado de una función php
Este caso es bastante similar al anterior, aunque un poco más simple.
Aquí lo que haremos será, en lugar de validar la salida completa, verificaremos qué sucedió como resultado de ejecutar la función.
Empecemos por modificar el archivo a testear:
<?php function duplicate(int $p) : int { return $p * 3; }
Y ahora hagamos un nuevo test:
<?php use PHPUnit\Framework\TestCase; class FunctionTest extends TestCase { public function testFunction() { ob_start(); require_once 'wrong.php'; $this->assertEquals(4, duplicate(2)); } }
El resto sigue igual al caso anterior
Cómo testear la ejecución de un script php
Por último, podríamos requerir testear el funcionamiento de un script de línea de comandos (Un cronjob por ejemplo).
Imaginemos un script como este:
<?php echo 'Bye bye '.$argv[1].'!';
Y este test:
<?php use PHPUnit\Framework\TestCase; class ScriptTest extends TestCase { public function testGreeting() { $this->assertEquals('Hello World!', shell_exec('php script.php World')); } }
Nos dará este resultado:
PHPUnit 9.3.7 by Sebastian Bergmann and contributors. F 1 / 1 (100%) Time: 00:00.026, Memory: 4.00 MB There was 1 failure: 1) ScriptTest::testGreeting Failed asserting that two strings are equal. --- Expected +++ Actual @@ @@ -'Hello World!' +'Bye bye World!' /home/mauro/Code/testing/ScriptTest.php:9 FAILURES! Tests: 1, Assertions: 1, Failures: 1.
Conclusión
En defintiva, no es cierto que es imposible testear aplicaciones php que no se basen en POO… lo que sí es cierto es que los tests van a ser más engorrosos y menos informativos.
Claro que eso es consecuencia de un diseño poco modular de la aplicación que estamos testeando… ¡pero esa fue precisamente la premisa del ejercicio!
Espero te haya dado alguna idea nueva, ¡espero tus comentarios!
- Cómo agregar una página de error 500 en un proyecto PHP - 31/10/2024
- ¿Cuántos contenedoresnecesita tu php? - 28/10/2024
- Cuál es el mejor framework PHP para hacer APIs REST - 25/10/2024
Primero que nada, muchas felicidades por tu blog.
Me fué de gran ayuda para darme una idea de como realizar test unitarios a codigo de php estruvturado.
Tengo una duda, si necesito pasar arametros al archivo como si fuera una petición http (GET, POST) como podria hacerlo?
Estuve investigando acerca del tema pero no encontré información.
Hola Marcos:
Gracias por tu comentario, me alegra haberte sido de ayuda.
Respecto de la pregunta, se me ocurre que algo que podrías hacer es manipular en forma directa los arreglos
POST
yGET
.Algo así como:
$_GET['parametro'] = "un valor";
require_once 'archivo_a_testear.php';
Saludos,