php - tutorial - pruebas unitarias codeigniter
¿Cómo escribo pruebas unitarias en PHP con una base de código de procedimiento? (3)
Estoy convencido de los beneficios de las pruebas unitarias, y me gustaría comenzar a aplicar el concepto a una base de código grande existente escrita en PHP. Menos del 10% de este código está orientado a objetos.
He examinado varios marcos de prueba de unidades (PHPUnit, SimpleTest y phpt). Sin embargo, no he encontrado ejemplos para ninguno de estos que prueban el código de procedimiento. ¿Cuál es el mejor marco para mi situación y hay ejemplos de pruebas unitarias de PHP usando un código que no sea OOP?
Las pruebas unitarias funcionan bien, y para lo que debe usarlas, cuando tiene un código, ingresa un número determinado de entradas y espera obtener un cierto número de salidas. La idea es que, cuando agregue la funcionalidad más adelante, puede ejecutar sus pruebas y asegurarse de que todavía está realizando la funcionalidad anterior de la misma manera.
Por lo tanto, si tiene una base de código de procedimiento, puede lograr esto llamando a sus funciones en los métodos de prueba
require ''my-libraries.php'';
class SomeTest extends SomeBaseTestFromSomeFramework {
public function testSetup() {
$this->assertTrue(true);
}
public function testMyFunction() {
$output = my_function(''foo'',3);
$this->assertEquals(''expected output'',$output);
}
}
Este truco con las bases de código PHP es que, a menudo, el código de su biblioteca interferirá con la ejecución de su marco de prueba, ya que su base de código y los marcos de prueba tendrán una gran cantidad de código relacionado con la configuración de un entorno de aplicación en un navegador web (sesión, compartida variables globales, etc.). Espere pasar algún tiempo llegando a un punto donde pueda incluir el código de su biblioteca y ejecutar una prueba sencilla (la función testSetup arriba).
Si su código no tiene funciones, y es solo una serie de archivos PHP que generan páginas HTML, no tiene suerte. Su código no se puede separar en unidades distintas, lo que significa que las pruebas unitarias no serán de mucha utilidad para usted. Sería mejor pasar su tiempo en el nivel de "pruebas de aceptación" con productos como Selenium y Watir . Esto le permitirá automatizar un navegador y luego revisar las páginas en busca de contenido como ubicaciones / formularios específicos.
Puede intentar incluir su código non-oop en una clase de prueba usando
require_once ''your_non_oop_file.php'' # Contains fct_to_test()
Y con phpUnit usted define su función de prueba:
testfct_to_test() {
assertEquals( result_expected, fct_to_test(), ''Fail with fct_to_test'' );
}
Usted puede probar PHP de procedimiento, no hay problema. Y definitivamente no estás de suerte si tu código está mezclado con HTML.
En el nivel de aplicación o prueba de aceptación, su PHP de procedimiento probablemente depende del valor de los superglobales ( $_POST, $_GET, $_COOKIE
, etc.) para determinar el comportamiento, y finaliza incluyendo un archivo de plantilla y escupiendo el resultado.
Para realizar pruebas a nivel de aplicación, solo puede establecer los valores superglobal; iniciar un búfer de salida (para evitar que un montón de html inunde tu pantalla); llamar a la página; afirmar contra cosas dentro del búfer; y tirar el búfer al final. Entonces, podrías hacer algo como esto:
public function setUp()
{
if (isset($_POST[''foo''])) {
unset($_POST[''foo'']);
}
}
public function testSomeKindOfAcceptanceTest()
{
$_POST[''foo''] = ''bar'';
ob_start();
include(''fileToTest.php'');
$output = ob_get_flush();
$this->assertContains($someExpectedString, $output);
}
Incluso para los enormes "marcos" con muchas inclusiones, este tipo de prueba le dirá si tiene características de nivel de aplicación funcionando o no. Esto será realmente importante a medida que comience a mejorar su código, porque incluso si está convencido de que el conector de la base de datos todavía funciona y se ve mejor que antes, querrá hacer clic en un botón y ver que sí, aún puede iniciar sesión y cerrar sesión a través de la base de datos.
En los niveles inferiores, hay variaciones menores según el alcance de la variable y si las funciones funcionan por efectos secundarios (devolviendo verdadero o falso), o devolviendo el resultado directamente.
¿Se pasan las variables de forma explícita, como parámetros o matrices de parámetros entre funciones? ¿O son las variables establecidas en muchos lugares diferentes, y se pasan implícitamente como globales? Si es el caso (bueno) explícito, puede probar una función por (1) incluyendo el archivo que contiene la función, luego (2) alimentar los valores de prueba de la función directamente y (3) capturar la salida y hacer valer contra ella. Si está utilizando globales, solo debe tener mucho cuidado (como se muestra arriba, en el ejemplo de $ _POST) para anular cuidadosamente todos los globales entre pruebas. También es especialmente útil mantener las pruebas muy pequeñas (5-10 líneas, 1-2 afirmaciones) cuando se trata de una función que empuja y atrae a muchos globales.
Otro problema básico es si las funciones funcionan devolviendo la salida o alterando los parámetros pasados, devolviendo verdadero / falso en su lugar. En el primer caso, la prueba es más fácil, pero nuevamente, es posible en ambos casos:
// assuming you required the file of interest at the top of the test file
public function testShouldConcatenateTwoStringsAndReturnResult()
{
$stringOne = ''foo'';
$stringTwo = ''bar'';
$expectedOutput = ''foobar'';
$output = myCustomCatFunction($stringOne, $stringTwo);
$this->assertEquals($expectedOutput, $output);
}
En el caso negativo, donde su código funciona por efectos secundarios y devuelve verdadero o falso, aún puede probar con bastante facilidad:
/* suppose your cat function stupidly
* overwrites the first parameter
* with the result of concatenation,
* as an admittedly contrived example
*/
public function testShouldConcatenateTwoStringsAndReturnTrue()
{
$stringOne = ''foo'';
$stringTwo = ''bar'';
$expectedOutput = ''foobar'';
$output = myCustomCatFunction($stringOne, $stringTwo);
$this->assertTrue($output);
$this->Equals($expectedOutput, $stringOne);
}
Espero que esto ayude.