2010-03-17 11 views
14

Una pregunta muy específica de un principiante al TDD:demasiados métodos pública obligó por Test Driven Development

Me separada mis pruebas y mi aplicación en diferentes paquetes. Por lo tanto, la mayoría de mis métodos de aplicación deben ser públicos para que las pruebas accedan a ellos. A medida que avance, se hace obvio que algunos métodos pueden volverse privados, pero si hago ese cambio, las pruebas que acceden a ellos no funcionarán. ¿Me estoy perdiendo un paso, o estoy haciendo algo mal, o es solo una caída de TDD?

+0

creo que querrías pruebas en la misma "unidad de archivo de código" como las cosas que se están probando. De esa forma tienen acceso a las agallas internas. –

+0

Como TDD newb, todavía estoy confundido por las directivas TDD duales: "no escriba una línea sin probar" y "no pruebe las partes internas". Si se siguen ambos, implica que las cosas comienzan de forma pública, pero se vuelven privadas mediante la refactorización y solo a través de la refactorización. Cuando realizas esa refactorización, puedes estar seguro de que simplemente estás exprimiendo el código ya probado en una configuración de código diferente. Hasta ahora, tan desconcertante. Pero el verdadero rascado de la cabeza se produce cuando también se acepta la tercera directiva sagrada: "nunca haga público un método solo para fines de prueba". –

Respuesta

18

Esto no es una caída de TDD, sino más bien un enfoque de prueba que cree que debe probar cada propiedad y cada método. De hecho, no debes preocuparte por los métodos privados cuando realizas pruebas, ya que solo deberían existir para facilitar parte de la API pública.

¡Nunca cambie algo de privado a público para fines de prueba!

Intente verificar solo el comportamiento visible públicamente. El resto son detalles de implementación y específicamente desea evitar probarlos. TDD está destinado a proporcionarle un conjunto de pruebas que le permitirán cambiar fácilmente los detalles de implementación sin romper las pruebas (cambio de comportamiento).

Digamos que tengo un tipo: MyClass y quiero probar el método DoStuff. Lo único que me importa es que el método DoStuff hace algo significativo y devuelve los resultados esperados. Puede llamar a cientos de métodos privados para llegar a ese punto, pero no me importa como consumidor de ese método.

+4

Pero ** quieres ** una forma de probar esos cientos de métodos internos, ¿no? –

+4

@Ian - Si está haciendo TDD, entonces ya deberían probarse. Su propia existencia significa que fueron puestos allí para hacer un pase de prueba. Sin embargo, esos métodos son un detalle de implementación que no debe ser conocido por el consumidor de la clase. Si después descubro que puedo refactorizar esos 100 métodos en 50 métodos, no debería tener que volver a escribir mis pruebas. Entonces ... sí los evalúas, pero no directamente porque solo te importa la API pública. Si hay algún método privado que no se puede ejercer a través de la API pública, entonces es inútil y debe eliminarse. – Josh

+0

Estoy siguiendo la 'Guía práctica' de David Astels -señala que usted prueba esas cosas y luego se refactoriza cuando hay demasiada intamacidad- eso me haría cambiar muchos métodos de público a privado (no privado a público) pero luego refactorizar mis conjuntos de pruebas para eliminar los que ya no prueban el comportamiento público: ¿suena razonable? – RoryG

9

No especifica el idioma que está utilizando, pero sin duda en la mayoría de ellos puede poner las pruebas de una manera que tenga un acceso más privilegiado a la clase. En Java, por ejemplo, la prueba puede estar en el mismo paquete, con el archivo de clase real en un directorio diferente, por lo que es independiente del código de producción.

Sin embargo, cuando está haciendo TDD real, las pruebas están impulsando el diseño de la clase, por lo que si tiene un método que existe solo para probar algún subconjunto de funcionalidad, probablemente (no siempre) está haciendo algo mal, y debería considerar técnicas como inyección de dependencia y burlas para guiar mejor su diseño.

+3

Me encontré con un problema similar en C# hace un tiempo: en ese lenguaje/marco, desea la directiva 'InternalsVisibleTo'. – Tim

1

Al menos en Java, es una buena práctica tener dos árboles fuente, uno para el código y otro para las pruebas. Así que usted puede poner su código y sus pruebas en el mismo paquete, mientras que todavía están en directorios diferentes:

src/org/my/xy/X.java 
test/org/my/xy/TestX.java 

entonces puede presentar su paquete métodos privada.

+0

Me pregunté sobre esto ... pero, siguiendo los libros (por ejemplo, Growing OO Software Guided by Tests), parece una buena práctica aplicar una jerarquía de directorio basada en el tipo de pruebas (pruebas unitarias, pruebas funcionales, fin) pruebas de extremo a extremo ... que explotan la posibilidad de usar paquetes privados. Llegué a la conclusión de que debes dejar esto como una estrategia ... (aunque soy un TDD newb :)) –

+0

@mike rodent: Aún puedes usar "unit-test/org/my/xy/UnitTestX.java" "y" functional-test/org/my/xy/FunctionalTestX.java ". Además, puede que no sea necesario acceder al código privado del paquete mediante _todos los tipos de pruebas. –

7

Aquí es donde aparece frecuentemente el viejo refrán, "TDD se trata de diseño". Una clase con demasiados métodos públicos probablemente tenga demasiadas responsabilidades, y el hecho de que usted lo esté probando solo lo expone; no causa el problema

Cuando se encuentre en esta situación, la mejor solución es encontrar un subconjunto de los métodos públicos que se pueden extraer en una nueva clase ("clase de brotes"), y luego darle a su clase original una variable de instancia del clase germinada Los métodos públicos merecen ser públicos en la nueva clase, pero ahora son, con respecto a la API de la clase original, privados. Y ahora tiene una mejor adherencia a SRP, acoplamiento más flexible, menor cohesión, mejor diseño.

Todo porque las características expuestas de su clase TDD que de otro modo se habrían deslizado bajo el radar. TDD se trata de Diseño.

+0

Esto tiene mucho sentido. Si solo hubiera un libro real que lo tomó de la mano y le mostró cómo entender "olores de diseño" del tipo que necesita para desarrollar sensibilidad para TDD. Aprender de la experiencia (amarga) tiene sus méritos, pero no requiere mucho tiempo. –

Cuestiones relacionadas