unitarias tutorial pruebas framework example ejemplos descargar php unit-testing phpunit

pruebas - phpunit tutorial



¿Cómo pruebo las excepciones múltiples con PHPUnit? (5)

Al probar las excepciones con PHPUnit, ¿cuál es la mejor manera de exigir que cada declaración o aseveración deba lanzar una excepción para que la prueba pase?

Básicamente quiero hacer algo como esto:

public function testExceptions() { $this->setExpectedException(''Exception''); foo(-1); //throws exception foo(1); //does not throw exception } //Test will fail because foo(1) did not throw an exception

Se me ocurrió lo siguiente, que cumple su función, pero es bastante feo de la OMI.

public function testExceptions() { try { foo(-1); } catch (Exception $e) { $hit = true; } if (!isset($hit)) $this->fail(''No exception thrown''); unset($hit); try { foo(1); } catch (Exception $e) { $hit = true; } if (!isset($hit)) $this->fail(''No exception thrown''); unset($hit); }


Ampliando la respuesta de @dave1010, aquí es cómo resolví este problema. Esto le permite mantener todas estas "afirmaciones" ordenadas y ordenadas dentro de una prueba. Simplemente defina una matriz de variables que deberían fallar en la prueba, y luego haga un ciclo a través de cada una y vea si se produce una excepción. Si alguno falla (no se lanza ninguna excepción), la prueba falla, de lo contrario la prueba pasa.

<?php public function testSetInvalidVariableType() { $invalid_vars = array( '''', // Strings array(), // Arrays true, // Booleans 1, // Integers new /StdClass // Objects ); foreach ($invalid_vars as $var) { try { $object->method($var); $this->fail(''No exception thrown for variable type "'' . gettype($var) . ''".''); } catch (/Exception $expected) { } } }


Código ligeramente más limpio (pero aún así sugeriría dividir tus pruebas:

try { foo(-1); $this->fail(''No exception thrown''); } catch (Exception $e) {}


Como las excepciones son eventos tan grandes en el flujo del programa, probar varios en una sola prueba es problemático.

Lo más fácil es simplemente dividirlo en dos pruebas: la primera requiere una excepción para poder aprobar, la segunda simplemente se ejecuta y, si fallaba, arrojaba una. Si lo desea, puede agregar algunas otras pruebas en la segunda (tal vez confirmar un valor de retorno), pero me inclino a asegurarme de que todavía hiciera lo único esencial, de acuerdo con su denominación.

/** * @expectedException Exception */ public function testBadFooThrowsException() { // optional, can also do it from the ''@expectedException x'' //$this->setExpectedException(''Exception''); foo(-1); //throws exception -- good. } public function testFooDoesNotThrowException() { foo(1); //does not throw exception }


Creo que esta es una situación muy común en las pruebas unitarias. El enfoque que utilizo en estos casos es usar phpunit dataProviders . Todos funcionan como se espera, y el código de prueba se vuelve más claro y conciso.

class MyTest extends PHPUnit/Framework/TestCase { public function badValues(): array { return [ [-1], [1] ]; } /** * @dataProvider badValues * @expectedException Exception */ public function testFoo($badValue): void { foo($badValue); } }


Esto no tiene sentido para mí.

Supongo que está intentando probar varias cosas por separado con un caso de prueba, lo que es una mala práctica.

Cuando foo() lanza la excepción esperada, el caso de prueba es exitoso y la bar() no se ejecuta.

Simplemente cree dos casos de prueba separados, que es mucho menos código que lo que produjo en la segunda lista.

O explique por qué tendría sentido ejecutar bar() , después de que foo() fallado con una excepción, cuando también se lanzará una excepción.