Assertions en PHPUnit

2019-08-28 PHPUnit
Tags   PHPUnit 8

En nuestro post anterior hemos visto cómo instalar PHPUnit y cómo realizar realizar una prueba unitaria. El día de hoy, veremos las aserciones más comunes cuando diseñamos pruebas unitarias. Después de este post estarás en la capacidad de diseñar pruebas unitarias utilizando las siguientes aserciones:

- assertEquals
- assertNotEquals
- assertNull
- assertNotNull
- assertTrue
- assertNotTrue
- assertFalse
- assertNotFalse
- assertSame
- assertNotSame
- assertInstanceOf

Escenario de pruebas

Para el ejemplo, hemos creado la siguiente clase en PHP que realiza el cálculo del determinante de una matriz 2x2, el cálculo de su transpuesta y verifica si la matriz es cuadrada o no.

class Matriz
{
    /**
     * @var array
     */
    public $matriz = [];

    /**
     * Retorna el valor del atributo $matriz
     *
     * @return array
     */
    public function getMatriz()
    {
        return $this->matriz;
    }

    /**
     * Establece el atributo $matriz
     */
    public function setMatriz(array $matriz)
    {
        if (!self::esCuadrada($matriz)) {
            throw new \InvalidArgumentException('La matriz no es cuadrada');
	}

	$this->matriz = $matriz;
    }

    public function __construct(array $matriz)
    {
        $this->setMatriz($matriz);
    }

    /**
     * @return double
     */
    public function det()
    {
	$matriz = $this->matriz;
	return $matriz[0][0] * $matriz[1][1] - $matriz[0][1] * $matriz[1][0];
    }

    /**
     * @return Matriz
     */
    public function transpuesta()
    {
	$m = $this->matriz;
	
	return new self([
	    [$m[0][0], $m[1][0]],
            [$m[0][1], $m[1][1]]
	]);
    }

    /**
     * @return boolean
     */
    public static function esCuadrada(array $matriz)
    {
        if (count($matriz) !== 2) {
	    return false;
	}

	foreach ($matriz as $linea) {
	    if (count($linea) !== 2) {
	        return false;
	    }
	}

	return true;
    }
}

Diseño de la Prueba

El primer paso para verificar que esta clase funciona perfectamente es realizar pruebas unitarias sobre los setters y getters. Veamos entonces las aserciones que no ayudarań a comprobar esta funcionalidad.

assertEquals / assertNotEquals

El método assertEquals verifica (sin distinción de tipo) que un valor dado es igual a un valor esperado. El método assertNotEquals es la inversa de este método, es decir, verifica que los valores sean diferentes. Adicionalmente se puede enviar un mensaje que indica que estos valores son iguales/diferentes.

- assertEquals(mixed $expected, mixed $actual[, string $message = ''])
- assertNotEquals(mixed $expected, mixed $actual[, string $message = ''])

assertNull / assertNotNull

El método assertNull verifica que un valor dado sea nulo (tipo NULL). El método assertNotNull es la inversa de este método, es decir, verifica que un valor sea distinto de nulo. Adicionalmente se puede enviar un mensaje cuando no se cumple la condición.

- assertNull(mixed $variable[, string $message = ''])
- assertNotNull(mixed $variable[, string $message = ''])

Ahora veamos a continuación cómo utilizar estas aserciones.

namespace Test;

Use Matriz;
use PHPUnit\Framework\TestCase;

class MatrizTest extends TestCase
{    
    public function testAsignaYCambiaCorrectamenteLaMatriz()
    {
        $matriz1 = [
	    [2, 3],
	    [5, 1]
        ];

	$mat = new Matriz($matriz1);

	// comprueba que se haya asignado correctamente la matriz en el constructor
	$this->assertEquals($matriz1, $mat->getMatriz());
     
     	$matriz2 = [
	    [1, 2],
	    [3, 4]
        ];

	$res = $mat->setMatriz($matriz2);

	// comprueba que el modificador no devuelve ningún valor
	$this->assertNull($res);

	// comprueba que se reasigne correctamente una matriz diferente con el setter
	$this->assertNotEquals($matriz1, $mat->getMatriz());
	$this->assertEquals($matriz2, $mat->getMatriz());
    }
}

assertTrue / assertNotTrue

El método assertTrue verifica que un valor dado sea el valor booleano TRUE. El método assertNotTrue es la inversa de este método, es decir, verifica que un valor sea distinto de TRUE. Adicionalmente se puede enviar un mensaje cuando no se cumple la condición.

- assertTrue(bool $condition[, string $message = ''])
- assertNotTrue(bool $condition[, string $message = ''])

assertFalse / assertNotFalse

El método assertFalse verifica que un valor dado sea el valor booleano FALSE. El método assertNotFalse es la inversa de este método, es decir, verifica que un valor sea distinto de FALSE. Adicionalmente se puede enviar un mensaje cuando no se cumple la condición.

- assertFalse(bool $condition[, string $message = ''])
- assertNotFalse(bool $condition[, string $message = ''])

Ahora veamos a continuación cómo utilizar estas aserciones adicionando este método a la clase de test.

public function testVerificaSiLaMatrizEsCuadrada2n()
{
    $matriz = [
        [2, 3],
        [5, 1]
    ];

    // comprueba que la matriz dada es cuadrada
    $this->assertTrue(Matriz::esCuadrada($matriz));

    $matriz = [
        [2, 3, 4],
        [5, 1, 9]
    ];

    // compruba que la matriz data no es cuadrada
    $this->assertFalse(Matriz::esCuadrada($matriz));
}

assertSame / assertNotSame

El método assertSame verifica (con distinción de tipo) que un valor dado es igual a un valor esperado. El método assertNotSame es la inversa de este método, es decir, verifica que los valores sean diferentes incluso en su tipo. Adicionalmente se puede enviar un mensaje cuando no se cumple la condición.

- assertSame(mixed $expected, mixed $actual[, string $message = ''])
- assertNotSame(mixed $expected, mixed $actual[, string $message = ''])

Veamos el siguiente método que utiliza estas aserciones.

public function testCalculaElDeterminante()
{
    $matriz = [
        [2, 3],
        [5, 1]
    ];

    $mat = new Matriz($matriz);

    // comprueba que el determinante sea -13 y comprueba el tipo
    $this->assertSame(-13, $mat->det());
}

assertInstanceOf / assertNotInstanceOf

El método assertInstanceOf verifica que un objeto es instancia de una clase específica. El método assertNotIntanceOf es la inversa de este método, es decir, verifica que un objeto no es instancia de una clase específica. Adicionalmente se puede enviar un mensaje cuando no se cumple la condición.

- assertInstanceOf($expected, $actual[, $message = ''])
- assertNotInstanceOf($expected, $actual[, $message = ''])

Veamos el siguiente método que utiliza estas aserciones:

public function testObtieneLaTranspuesta()
{
    $matriz = [
        [2, 3],
        [5, 1]
    ];

    $mat = new Matriz($matriz);

    // comprueba que devuelve una instancia de Matriz
    $this->assertInstanceOf(Matriz::class, $mat->transpuesta());
}

Recomendaciones

A primera vista, pudiera parecer que los métodos assertFalse y assertNotTrue son iguales. Esto mismo sucede con otras duplas como assertEquals y assertNotSame. Sin embargo no realizan la misma comprobación. Espero que con este post puedas detectar el por qué y que hayas aprendido a utilizar las aserciones más usadas. Hasta pronto!.

Acerca de Darío Rivera

Author

Ingeniero de desarrollo en PlacetoPay , Medellín. Darío ha trabajado por más de 6 años en lenguajes de programación web especialmente en PHP. Creador del microframework DronePHP basado en Zend y Laravel.

Sólo aquellos que han alcanzado el éxito saben que siempre estuvo a un paso del momento en que pensaron renunciar.