2011-07-29 26 views
5

Por lo que sé de eXtreme Programming y pruebas unitarias, los ensayos deben ser realizados por otro desarrollador antes de que otro desarrolle el método probado (o por los mismos desarrolladores, pero la prueba debe escribirse antes de la implementación del método).¿Para burlarse o no para burlarse?

Ok, parece bueno, solo tenemos que probar si un método tiene un buen comportamiento cuando le doy algunos parámetros.

Pero la diferencia entre la teoría y la práctica es que, en teoría, no hay pero en la práctica no existe ...

La primera vez que he intentado probar, he encontrado que es difícil en algunos casos debido a las relaciones entre los objetos. Descubrí la práctica de la burla y la encontré muy útil, pero algunos conceptos me hacen dudar.

Primero, burlarse implícito dice: "Ya sabes cómo funciona el método porque debes saber qué otros objetos necesita ...". Bueno, en teoría, ese es mi amigo Bob que escribe la prueba y simplemente sabe que el método debe volverse verdadero cuando le doy la cadena "john" ... Soy yo quien codifica este método usando un dao para acceder a una base de datos en lugar de usar un hashtable en la memoria ...

¿Cómo mi pobre amigo Bob va a escribir su prueba? Anticipará mi trabajo ...

Ok, parece que no es la teoría pura, pero no importa. Pero si miro la documentación de muchos frameworks simulados, me permiten probar cuántas veces se llama un método y en qué orden. ouch ...

Pero si mi amigo Bob debe probar este método así para asegurar el buen uso de las dependencias, el método debe escribirse antes de la prueba, ¿no es así?

Hum ... ayudar a mi amigo Bob ...

¿Cuándo dejamos de usar mecanismo de maqueta (verificación de pedidos, etc.)? Cuando los mecanismos simulados son útiles? Teoría, práctica y simulacro: ¿cuál es el mejor equilibrio?

Respuesta

6

Lo que parece que falta en su descripción es el concepto de separar el contrato de la implementación. En C# y Java, tenemos interfaces. En C++, una clase compuesta solo de funciones virtuales puras puede cumplir este rol. Estos no son realmente necesarios, pero son útiles para establecer la separación lógica. Entonces, en lugar de la confusión que pareces experimentar, la práctica debería ser más parecida a la siguiente: Bob escribe las pruebas unitarias para una clase/unidad de funcionalidad en particular. Al hacerlo, define una o más interfaces (contratos) para otras clases/unidades que se necesitarán para respaldar esta. En lugar de tener que escribirlos ahora mismo, los rellena con objetos simulados para proporcionar la entrada y salida indirecta requerida por su prueba y el sistema bajo prueba. Por lo tanto, la salida de un conjunto de pruebas unitarias no es solo las pruebas para impulsar el desarrollo de una sola unidad, sino que más los contratos deben ser implementados por otro código para soportar la unidad actualmente en desarrollo.

+3

Aún así, el hecho de que Bob necesite especificar qué es compatible con el método probado no se siente bien. De hecho, al especificar los contratos de los que habla, Bob definirá la implementación real de un método probado. Y ese no es su trabajo. El uso de interfaces realmente no resuelve el problema.[Komarro] (http://code.google.com/p/komarro/) intenta proporcionar algunas mejoras sobre este problema. Echar un vistazo... –

0

No estoy seguro de cuál es exactamente el problema. Por lo tanto, es posible que no responda con precisión la pregunta, pero lo intentaré.

Supongamos que está escribiendo el sistema A, donde A necesidad de obtener datos (digamos que una cadena de simplicidad) de un proveedor, y luego un inverso esa cadena y enviarlo a otro sistema C.

B y C se le proporcionan, y en realidad son interfaces, las implementaciones en la vida real pueden ser BImpl y CImpl.

para los fines de su trabajo, ya sabe, que necesita llamar a readData() desde el sistema B, y sendData (String) desde el sistema C. Su amigo Bob también debe saberlo, usted no debe enviar la información antes de que la obtengas Además, si obtiene "abcd" debe enviar "dcba"

parece que tanto usted como Bob deberían saber esto, él escribe las pruebas, y usted escribe el código ... ¿dónde está el problema en eso?

por supuesto, la vida real es más complicada, pero aún así debería poder modelarla con interacciones simples que pruebe usted mismo.

1

Cuando está escribiendo una prueba unitaria, está probando el resultado y/o el comportamiento de la clase bajo prueba frente a un esperado resultado y/o comportamiento.

Las expectativas pueden cambiar a lo largo del tiempo que desarrolle la clase; pueden presentarse nuevos requisitos que modifiquen el comportamiento de la clase o el resultado de llamar a un método en particular. Nunca se establece en piedra y las pruebas unitarias y la clase bajo pruebas evolucionan juntas.

Inicialmente puede comenzar con unas pocas pruebas básicas en un nivel muy granular, que luego evolucionan en más y más pruebas, algunas de las cuales pueden ser muy particulares a la implementación real de su clase bajo prueba (al menos como tanto como se refiere al comportamiento observable de esa clase).

Hasta cierto punto, puede escribir muchas de sus pruebas contra un trozo sin procesar de su clase bajo prueba, que produce el comportamiento esperado pero la mayoría todavía no tiene implementación. Entonces puedes refactorizar/desarrollar la clase "de verdad".

En mi opinión, es una quimera escribir todas las pruebas al principio y luego desarrollar completamente la clase; en mi experiencia, tanto las pruebas como las pruebas de clase evolucionan juntas. Ambos pueden ser escritos por el mismo desarrollador también.

Por otra parte, ciertamente no soy un purista de TDD, simplemente tratando de obtener el máximo provecho de las pruebas unitarias de una manera pragmática.

4

No estoy seguro de entender su pregunta.

Utilice simulaciones para verificar la colaboración entre los objetos. Por ejemplo, supongamos que tiene un método de Login() que toma un nombre de usuario y contraseña. Ahora supongamos que quiere que este método Log Logs inot the failed. En su prueba de unidad, crearía un objeto Logger falso y establecería una expectativa sobre el cual se llamará. Luego, la dependencia lo insertaría en su clase de inicio de sesión y llamaría a su método de inicio de sesión con un nombre de usuario y una contraseña incorrectos para activar un mensaje de registro.

La otra herramienta que tiene en su bolsa de herramientas de prueba de unidad son los talones. Use stubs cuando no esté probando colaboraciones, pero falsifique dependencias para hacer que su clase se pruebe.

Roy Osherove, el autor de la El arte de la Unidad de Pruebas, tiene un buen video de burla: TDD - Understanding Mock Objects

También recomiendo ir a su página web http://artofunittesting.com/ y viendo los videos gratis en el lado derecho debajo de la encabezado "Vídeos de prueba de unidad".