Hay muchas formas diferentes de probar su aplicación de software, y la prueba unitaria es importante.
Entonces, ¿qué son las pruebas unitarias y cómo puedes hacerlas? Aprenderás eso y más en este artículo.
¿Qué es PHPUnit?
Puede realizar pruebas unitarias en PHP con PHPUnit, un marco de pruebas para PHP orientado al programador. PHPUnit es una instancia de la arquitectura xUnit para marcos de prueba unitaria. Es muy fácil de instalar y comenzar.
Instalación de PHPUnit
Puede instalar PHPUnit globalmente en su servidor. También puede instalarlo localmente, por proyecto, en tiempo de desarrollo como una dependencia de su proyecto usando composer. Este artículo explicará cómo usarlo por proyecto.
Para comenzar, cree e inicie un nuevo proyecto con composer usando estos comandos:
$ mkdir mi-app
$ cd mi-app
$ composer init
El primer comando crea una carpeta en su directorio actual, proyecto de prueba y el segundo comando se mueve a él. El último comando inicia un shell interactivo.
Siga las instrucciones y complete los detalles según sea necesario (los valores predeterminados están bien). Puede establecer la descripción del proyecto, el nombre del autor (o los nombres de los colaboradores), la estabilidad mínima para las dependencias, el tipo de proyecto, la licencia y definir sus dependencias.
Puede omitir la parte de las dependencias, ya que no estamos instalando ninguna dependencia. Se supone que PHPUnit es una dependencia de desarrollo porque las pruebas en su conjunto solo deberían ocurrir durante el desarrollo.
Ahora, cuando el mensaje pregunte Would you like to define your dev dependencies (require-dev) interactively [yes]?
, presione enter para aceptar. Luego escriba phpunit/phpunit
para instalar PHPUnit como una dependencia de desarrollo.
Acepte los demás valores predeterminados y proceda a generar el archivo composer.json. El archivo generado debería verse así actualmente:
{
"name": "ricardo/mi-app",
"require-dev": {
"phpunit/phpunit": "^9.6"
},
"autoload": {
"psr-4": {
"Ricardo\\MiApp\\": "src/"
}
},
"authors": [
{
"name": "RicardoGeek",
"email": "[email protected]"
}
],
"require": {}
}
Cómo escribir pruebas en PHPUnit
Escribir pruebas en PHPUnit es bastante simple. Aquí hay algunas convenciones para comenzar:
- Para probar una clase en PHP, creará una clase de prueba con el nombre de esa clase. Por ejemplo, si tuviera algún tipo de clase de usuario, la clase de prueba se llamaría UserTest.
- La clase de prueba, UserTest, normalmente heredará la clase PHPUnit\Framework\TestCase.
- Las pruebas individuales en la clase son métodos públicos nombrados con prueba como prefijo. Por ejemplo, para probar un método sayHello en la clase User, el método se llamará testSayHello.
- Dentro del método de prueba, diga testSayHello, usa el método de PHPUnit como assertSame para ver que algún método devuelve algún valor esperado.
Una convención popular es tener todas las pruebas en un directorio de pruebas y todo el código fuente en el directorio src.
Ejemplo de prueba de PHPUnit
Para ayudar a comprender este artículo, aquí hay una clase de usuario de muestra con métodos simples que se probarán:
<?php
namespace Ricardo\MiApp;
use InvalidArgumentException;
class User {
public int $edad;
public array $pelis_favoritas = [];
public string $nombre;
/**
* @param int $edad
* @param string $name
*/
public function __construct(int $edad, string $nombre) {
$this->edad = $edad;
$this->nombre = $nombre;
}
public function decirNombre(): string {
return "Mi nombre es " . $this->nombre . ".";
}
public function decirEdad(): string {
return "Tengo " . $this->edad . " años.";
}
public function agregarPelicula(string $pelicula): bool {
$this->pelis_favoritas[] = $pelicula;
return true;
}
public function quitarPelicula(string $pelicula): bool {
if (!in_array($pelicula, $this->pelis_favoritas)) throw new InvalidArgumentException("No tengo esa peli: " . $pelicula);
unset($this->pelis_favoritas[array_search($pelicula, $this->pelis_favoritas)]);
return true;
}
}
Esta clase de usuario podría ser la clase de Usuario en su aplicación de transmisión de películas. El usuario tiene un nombre, una edad y una lista de películas favoritas que puede actualizar. En el resto del artículo, probaremos que todas estas funciones funcionan como se espera.
Cree una clase UserTest en la carpeta de pruebas. Pega esto para comenzar:
<?php
namespace Ricardo\MiApp;
use PHPUnit\Framework\TestCase;
final class UserTest extends TestCase
{
// Pon los tests aqui
}
Probando el constructor
Normalmente, no estaría probando el método __construct. Sin embargo, dado que estamos configurando valores en él, solo tiene sentido asegurarse de que los valores se configuren correctamente.
Esto parece algo muy pequeño para probar, pero ese es el objetivo de las pruebas unitarias: garantizar que las partes más pequeñas de su aplicación funcionen como se espera.
Cree un método testClassConstructor para probar el constructor:
public function testClassConstructor()
{
$user = new User(18, 'Juanito');
$this->assertSame('Juanito', $user->nombre);
$this->assertSame(18, $user->edad);
$this->assertEmpty($user->pelis_favoritas);
}
Cómo ejecutar pruebas en PHPUnit
Puede ejecutar todas las pruebas en un directorio utilizando el binario PHPUnit instalado en la carpeta de su proveedor.
$ ./vendor/bin/phpunit --verbose tests
También puede ejecutar una sola prueba proporcionando la ruta al archivo de prueba.
$ ./vendor/bin/phpunit --verbose tests/UserTest.php
Utiliza el indicador –verbose para obtener más información sobre el estado de la prueba.
Ahora, podemos ejecutar la prueba y ver el resultado:
El resultado muestra que ejecutamos 1 prueba e hicimos 3 afirmaciones en ella. También vemos cuánto tiempo llevó ejecutar la prueba, así como cuánta memoria se usó para ejecutar la prueba.
Estas afirmaciones son las que utiliza PHPUnit para comparar los valores devueltos por los métodos con su valor esperado.
Este ejemplo usa assertSame para verificar si las propiedades de nombre y edad en el objeto de usuario coinciden con los valores ingresados. También usa assertEmpty para verificar que la matriz de películas favoritas esté vacía.
Para ver una lista de todas estas afirmaciones, puede consultar los documentos de PHPUnit aquí.
Edite el código para verificar si la edad del usuario es la misma que 21.
public function testClassConstructor()
{
$user = new User(18, 'John');
$this->assertSame('John', $user->nombre);
$this->assertSame(21, $user->edad;
$this->assertEmpty($user->pelis_favoritas);
}
Al correr esta prueba con este error obvio obtenemos este resultado:
El resultado ahora muestra que ejecutamos 1 prueba, con 2 afirmaciones exitosas y también una fallida. Podemos ver alguna explicación de la falla, mostrando el valor esperado, el valor obtenido y la línea de donde proviene el error.
El resto de pruebas unitarias
Ahora escribimos pruebas para el resto de metodos de la clase:
public function testDecirNombre()
{
$user = new User(18, 'Juanito');
$this->assertIsString($user->decirNombre());
$this->assertStringContainsStringIgnoringCase('Juanito', $user->decirNombre());
}
La prueba utiliza las aserciones assertIsString y assertStringContainsStringIgnoringCase para comprobar que el valor de retorno es una cadena y que contiene la cadena John, respectivamente.
El método testAge es muy similar a testName y usa la misma lógica. Su prueba será similar a la anterior:
public function testDecirEdad()
{
$user = new User(18, 'Juanito');
$this->assertIsString($user->decirEdad());
$this->assertStringContainsStringIgnoringCase('18', $user->decirEdad());
}
Ahora agreguemos algunas peliculas
public function testAgregarPelicula()
{
$user = new User(18, 'Juanito');
$this->assertTrue($user->agregarPelicula('Avengers'));
$this->assertContains('Avengers', $user->pelis_favoritas);
$this->assertCount(1, $user->pelis_favoritas);
}
Aquí, usamos algunas aserciones nuevas (afirmar Verdadero, afirmarContiene y afirmarCuenta) para verificar que el valor devuelto sea verdadero, que contenga la cadena recién agregada y que la matriz ahora tenga un elemento.
public function testQuitarPelicula()
{
$user = new User(18, 'Juanito');
$this->assertTrue($user->agregarPelicula('Avengers'));
$this->assertTrue($user->agregarPelicula('Justice League'));
$this->assertTrue($user->quitarPelicula('Avengers'));
$this->assertNotContains('Avengers', $user->pelis_favoritas);
$this->assertCount(1, $user->pelis_favoritas);
}
Aquí, estamos agregando algunas películas a la lista. Luego, eliminamos uno de ellos y confirmamos que la función devolvió verdadero. A continuación, confirmamos la eliminación comprobando que el valor ya no está en la lista. Finalmente, confirmamos que solo tenemos una película en la lista, en lugar de dos.
Conclusión
Ahora sabe cómo configurar PHPUnit en sus proyectos y cómo probar y asegurarse de que está creando un software de clase mundial.