2008-10-08 12 views
9

Después de leer el Mocks Aren't Stubs de Martin Fowler, descubrí que he estado practicando TDD al estilo "mockist".Como practicante de TDD "simulado", ¿debería burlarme de otros métodos en la misma clase que el método bajo prueba?

Pero me pregunto si incluso en Mockist TDD si uno puede tomar la burla demasiado lejos.

He aquí un actualizan ejemplo, en estilo pseudo-código Python:

def sync_path(self): 
    if self.confirm_or_create_connection(): 
     self.sync(self.dirpath) 

El método confirm_or_create_connection() crea una conexión con un servidor.

Probé un método similar a este en dos pruebas, las cuales simulan confirm_or_create_connection() y sync() (aunque ambos son métodos en la misma clase). En una prueba, el simulador confirm_or_create_connection() devuelve True y la prueba confirma que se llamó a sync(), y en el otro el simulacro confirm_or_create_connection() devuelve False y la prueba confirma que no se llamó a sync().

¿Es esto razonable? ¿O debería burlarme de los objetos que confirman la llamada de confirm_or_create_connection() y sync()? (Tengo otras pruebas de estos dos métodos que ya lo hacen.)

No conteste la pregunta explicando que debería estar practicando el TDD "clásico" en su lugar. Esa es una respuesta a otra pregunta: Should I practice mockist or classical TDD?

Respuesta

8

La técnica se llama "objetos simulados", no "métodos simulados" por algún motivo. Fomenta diseños que dividen el sistema en objetos de fácil composición y colaboración, y lejos del código de procedimiento. El objetivo es elevar el nivel de abstracción para que pueda programar al componer objetos y rara vez escribir declaraciones de flujo de control de bajo nivel.

1

editado por ejemplo el nuevo
A mí me parece como si estuviera apagando confirm_or_create_connection, sólo está interesado en la definición de la llamada de retorno y que estás burlando de sincronización, aquí estás interesado en probar si realmente se llama. (Tendré que verificar si mi definición de trozo o burla es la misma que la del artículo de Fowler que mencionaste. Ha pasado algún tiempo desde que la leí y he estado usando rhinomocks en C# que podría tener su propia defensa de estos términos :-))

Creo que para lo que está probando burlarse y pegar esas llamadas es el camino correcto. No desea que la prueba falle si una de esas funciones tiene un error, existen otras pruebas para eso. Solo quiere probar la operación de sync_path.

Estoy de acuerdo con Avdi en que esto es algo maloliente. Las pruebas están bien, pero tu clase podría estar haciendo demasiado.

+0

Intentaré aclarar mi pregunta. –

5

Personalmente, creo que burlarse de sí mismo es casi siempre un olor a código. Está probando la implementación en lugar del comportamiento.

+0

¿Pero qué sucede cuando una función no devuelve un resultado, solo efectos secundarios? (Como en mi ejemplo anterior) –

+0

Dependiendo de la situación, me gustaría o resisto los objetos que confirman o crean conexiones() o pondría confirm_or_create_connection() en un objeto contenido y sustituyo una implementación de ese objeto en el momento de la prueba . – Avdi

0

¿Se puede tomar el burlarse demasiado? No sé demasiado, pero se puede hacer mal, de modo que en realidad estás probando los simulacros en lugar del código, o peor, para que tengas pruebas frágiles.

Pero mientras redacte buenas pruebas, pruebas que confirmen su comportamiento esperado, pruebas que lo ayuden a escribir el código, ¡entonces insista!

4

Editado para la muestra actualizada:

Ahora veo. Tienes problemas para probar esta clase porque tiene fallas de diseño. Esta clase viola el principio de responsabilidad individual. Está haciendo dos cosas. Primero, es administrar una conexión a una base de datos. También se está sincronizando.

Necesita una clase aparte para administrar su conexión a la base de datos. Esta clase será una dependencia de la clase bajo prueba.La clase de conexión de la base de datos se puede simular cuando se prueba la clase bajo prueba.

Anteriormente:

Como probador interacción compañero, considerar refactorización si tiene una necesidad para hacer esto. Esa clase es probablemente haciendo demasiado.

Déjeme ponerlo de esta manera: llamando al un método privado no hace una interacción .

Este es uno de los puntos principales de TDD. Cuando duele su diseño puede ser mejorado.

1

Adivinar violentamente, parece que la actividad de la conexión podría pertenecer en otro objeto que debe ser delegada a, en cuyo caso se puede burlarse que. Por lo general, recomiendo evitar burlarse de una parte de un objeto para probar otra parte. Sugiere que hay dos conceptos unidos entre sí.

0

He aquí una buena lectura en él: "Principio: No modifique el SUT" en http://xunitpatterns.com/Principles%20of%20Test%20Automation.html#Don

modificación de la clase que está probando al burlarse o apagando partes de su implementación es un olor código. La refactorización para alejarse de ella es mover la parte que estás burlando/tropezando a otra clase. Eso dijo que no siempre es algo terrible. Es un olor a código, pero no siempre es inapropiado. Para lenguajes como C# o Java donde tiene buenas herramientas de refactorización, es fácil corregir este código y normalmente lo haría (en C#, suponiendo que Java sea similar). Hago mucho desarrollo en Lua y Javascript, donde las cosas son un poco diferentes. Crear y administrar muchas clases en esos idiomas es más difícil, por lo que soy más tolerante con la modificación del SUT en las pruebas. Siempre es algo que puedo arreglar más tarde una vez que la cobertura de la prueba inicial está allí. Requiere cuidado extra.

Cuestiones relacionadas