2010-01-20 13 views
13

Estoy tratando de entrar en la prueba de unidad para los aspectos positivos que presenta, y estoy tratando de escribir una prueba de unidad para una clase que escribí el otro día. (Sé que esto es lo opuesto a TDD, por favor tengan paciencia)Pregunta de prueba de PHPUnit: cómo probar la unidad en mi clase

Mi clase, Image, se usa junto con algunos otros para la manipulación de imágenes.

Image esencialmente envuelve un recurso de imagen GD y almacena datos junto con él. Por ejemplo, una instancia de Image siempre contendrá su estado actual, es decir, su nueva anchura/altura si cambiar de tamaño, los datos originales de imagen, etc.

La clase Image también contiene métodos para,

  • Creación de sí mismo desde un archivo, datos de cadena o URL, por ejemplo $image->loadFromPath()
  • Creación de un nuevo recurso de imagen GD a partir de las propiedades de la instancia actual Image, p. para cambiar el tamaño de imagen para mantener la transparencia de fondo, etc.
  • Clonación del recurso de imagen GD para su uso en las clases de manipulación

Lo que estoy luchando con es la forma de unidad de prueba de esta clase correctamente con PHPUnit. He leído algo y tengo algunas ideas contradictorias sobre cómo abordarlo y no sé qué es lo correcto. Puedo,

  1. escribir una prueba para cada método de la clase. Leí en alguna parte que debería probar todos y cada uno de los métodos. Sin embargo, algunos de los métodos ejecutan otros (con razón también puedo agregar), entonces tienes una cadena de dependencia. Pero también leí que cada prueba de Unidad debería ser independiente de la otra. Entonces, ¿qué hago si este es el caso?
  2. Escriba cada prueba como una ruta de uso de la clase. También leí en alguna parte que cada prueba debería representar una ruta de ruta/uso que puede tomar con la clase. Por lo tanto, si cubre cada uso, finalmente obtendrá una cobertura de código completa.

Entonces, ¿cuál de estos es correcto, si corresponde?

+0

¿Conoces la cobertura del código? OMI es más importante ejecutar cada línea de código al menos una vez en lugar de crear una prueba para cada método, lo que no siempre es necesario por la misma razón que usted mencionó. – Franz

+0

+1 para ingresar a UnitTests – Gordon

+0

Sé qué cobertura de código es sí, y que debe apuntar al 100%, que es que cada línea debe ejecutarse al menos una vez. ¿Es definitivamente mejor escribir el caso de prueba donde cada prueba es una acción que realiza su clase en lugar de que cada prueba sea para un método específico? –

Respuesta

8

Las pruebas de unidades se deben escribir para evaluar la interfaz pública de una clase. Su caso de prueba debe usar la clase como pretende que se use en su programa. La idea aquí es probar el comportamiento (condiciones esperadas, inesperadas o de borde) de la clase.

Las dos ideas que publicó son correctas. En teoría, debe tener suficientes casos de prueba (rutas a través de su código) que se ejecutan todos sus métodos en la clase.

Como se mencionó, la cobertura de prueba del 100% es un buen objetivo, pero no siempre realista.

Además, en el caso de GD, tenga cuidado con las pruebas de unidad de escritura que prueban la funcionalidad de GD (ya se ha probado, no es necesario que pierda el tiempo probando nuevamente). Me gustaría read up on utilizando los simulacros y los resguardos de PHPUnit (y burlando el sistema de archivos) en el manual de PHPUnit.

Esto es lo que una prueba de ejemplo podría ser:

public function testImageIsResized() 
{ 
    $image = new Image(); 
    $image->loadFromPath('some/path'); 
    $image->resize(200, 300); 
    $this->assertEquals(200, $image->getWidth()); 
    $this->assertEquals(300, $image->getHeight()); 
} 

Ahora, dependiendo del comportamiento esperado de la clase de imagen, esta prueba podría pasar sin problema, o podría fallar, ya que estaba esperando las nuevas dimensiones para ser proporcionalmente restringido a las dimensiones de la imagen original. Pero no llamamos explícitamente al método interno que verifica esa restricción en la prueba en sí.

+0

¡Casi todos mis pensamientos ahora! Gracias por el resumen –

5

Puede usar el covers annotation para especificar si una prueba cubre varios métodos. Entonces, si uno de sus métodos llama a otro método, simplemente puede agregar la anotación al docblock de la prueba y se agregará a las estadísticas de cobertura de su código, p.

/** 
* @test 
* @covers MyClass::something() 
* @covers MyClass::_somethingElse() 
*/ 
public function somethingWorksAsExpected() 
{ 
    $this->assertSame($expected, $this->testObject->something()); 
} 

Para proyectos personales, 100% de cobertura de código está bien. Sin embargo, he visto charlas en conferencias donde se duda que el 100% sean necesarias. A pesar de todos los beneficios, las pruebas se toman un tiempo para escribir y, en un proyecto presupuestado, podría ser suficiente con solo probar 80/20 y dejar de lado las funciones críticas de poca prioridad de su aplicación.

En cuanto a cómo probar su clase, eche un vistazo al capítulo en Behaviour Driven Development in the PHPUnit Manual. En su caso, probaría la funcionalidad que describió en su pregunta.

0

Stephen Melrose dijo:

Sin embargo, algunos de los métodos de gestión a otros (con razón puede que añadir), por lo que continuación, tiene una cadena de dependencia. Pero también leído que cada prueba Unidad debe ser independiente de la otra

independencia prueba no es acerca de no probar el mismo código dos veces, se trata de si el resultado (o la falta de resultado) de una prueba afecta el resultado de otro. Si su primera prueba inserta algunos datos y luego falla antes de que pueda eliminar esos datos, su segunda prueba podría obtener resultados diferentes a los esperados. Lo ideal sería que pueda ejecutar sus pruebas en orden aleatorio, o ejecutar algunas y no otras.

Cuestiones relacionadas