2009-12-07 11 views
14

Tengo clases que anteriormente tenían métodos masivos, así que subdividí el trabajo de este método en métodos 'auxiliares'.¿Métodos de ayuda de prueba de unidad?

Estos métodos auxiliares se declaran private para hacer cumplir la encapsulación - sin embargo yo quiero probar unidad de los grandes métodos públicos. ¿Es bueno probar los métodos de ayuda también como si uno de ellos fallara, el método público que lo llama también fallará, y de esta manera podemos identificar por qué falló?

también con el fin de probar estas usando un objeto de burla que tendría que cambiar su visibilidad de lo privado a proteger, es aconsejable?

Respuesta

11

Una forma es omitir private y poner las pruebas en el mismo paquete. Entonces las pruebas pueden llamar a los métodos internos, pero nadie más (= fuera del paquete) puede hacerlo.

Además, al fallar los métodos internos, se deben generar mensajes de error que faciliten la solución del problema. Cuando ponga el código en producción, verá menos que las pruebas y estará bajo mucha presión para solucionar los problemas rápidamente. Así que un minuto pasado aquí te salvará una hora más tarde con tu jefe sentado en tu cuello.

+8

En lugar de convertirlos en paquetes privados, prefiero proteger los métodos auxiliares y probarlos desde una subclase anónima en la prueba JUnit. – rsp

+1

@rsp: Es una solución fantástica en la que nunca antes había pensado. ¡Debería ser su propia respuesta, así que puedo votarlo! :) –

3

Si desea probar Helper métodos puede cambiarlos de privado, pero podría considerar esto.

No debe dar prueba de la unidad detalles privados de su aplicación sobre todo porque podría variar debido a la refactorización y "romper" su prueba.

0

que básicamente tienen 2 opciones:

  1. aumentar el alcance de los métodos de ayuda del sector privado al defecto. Luego puede probar estos métodos (suponiendo que las clases de prueba están en el mismo paquete que el sujeto de prueba). Esto mejora la capacidad de prueba de la clase, pero se sacrifica parte de encapsulación

  2. Deja todo como está. Esto evitará que escriba pruebas muy precisas, pero no requiere que sacrifique ninguna encapsulación.

Personalmente, elegiría (2), porque no debería realmente necesitar probar métodos privados. La clase debe probarse a través de su interfaz pública (que a su vez llamará a los métodos privados. Probar métodos privados puede generar pruebas frágiles, es decir, pruebas que fallan cuando solo cambia el comportamiento interno de una clase.

Hay un tercero opción (que soy reacio a mencionar): utilice la reflexión (u otro vudú) para invocar métodos privados dentro de su clase de prueba. Esto tiene las desventajas de (1) y también las desventajas intrínsecas del código reflectivo (p. es difícil de leer)

+0

también podría usar una subclase definida en el caso de prueba que llama al método protegido, por lo que las clases de prueba no necesitan estar en el mismo paquete que la implementación – Aly

0

Como Don y Dror dicen, hacer que los métodos sean públicos para que pueda crear pruebas unitarias para ellos rompe la encapsulación. A continuación, se une a una implementación particular. Al hacerlos públicos, usted declara al mundo que estos métodos son parte de t publicó la interfaz y, por lo tanto, sus especificaciones están bloqueadas.

En lo personal, me gustaría ir para una solución más pragmática: mantenerlos privados y no escribir pruebas unitarias. Si llega a un caso en el que falla un método público y no puede averiguar por qué, pero cree que podría ser un problema en uno de sus métodos privados, conviértalo en público temporalmente, escriba la prueba de unidad, depure y cuando Hecho, haz que vuelvan a ser privados y comenta la prueba unitaria.

14

Esto huele como si tuviera un problema incorrecto. Lo que has descrito es similar a crear una "prueba unitaria", lo que me lleva a pensar que las pruebas de tu unidad realmente están probando una unidad después de todo.

Lo cual no es una crítica de lo que estás tratando de hacer: pasar de "donde estamos hoy" a "otro lugar que es mucho mejor" es un movimiento ganador. Sin embargo, es una sugerencia que retroceda un poco para evaluar dónde se encuentra: comprender cómo difiere su situación actual de algún ideal platónico podría ayudar a mostrar nuevas posibilidades.

Aquí hay muchas sugerencias sobre el alcance de sus métodos de ayuda. Otra posibilidad sería revisar la implementación para determinar si hay clases de ayuda al acecho en su implementación actual. Crear una nueva clase y un conjunto de pruebas para ejercitarlo siempre es aceptable.

Tenga en cuenta que este enfoque lo aísla de la refactorización: puede cambiar la implementación sin cambiar su conjunto de pruebas (porque las pruebas de unidad para el objeto auxiliar continúan pasando incluso cuando el objeto auxiliar ya no es parte de su implementación de producción) , y obtienes un empaquetado limpio de la implementación y las pruebas para ello (usecase: decides que bozo-sort es la implementación incorrecta, y ya no se debe usar. Si la implementación bozo-sort está aislada, entonces simplemente la eliminas) y sus pruebas. Pero cuando las pruebas de la implementación de bozo-sort están enredadas con todas las otras pruebas, hay más ideas involucradas).

También puede ser útil revisar por qué tiene pruebas unitarias para su código. Si una de las razones es "para que la refactorización sea segura", entonces no querrá escribir pruebas que lo bloqueen en una implementación.

1

Este es uno de esos casos en los que diría que seguir adelante y romper las reglas.

Si estaba diseñando la clase desde cero, definitivamente no desea que los métodos de ayuda se prueben por unidad, pero ... ya que está refaccionando una clase existente, es aceptable doblar las reglas para Asegúrate de no romper nada.

Hacerlos protegidos le permitirá probar a los ayudantes ellos mismos, para asegurarse de que todavía tienen el comportamiento que espera mientras saca la lógica del gran método de bola de pelo, así como también les permite anularlos y devolverlos respuestas para que pueda asegurarse de que el método grande que está refactorizando se comporte como se espera para ciertos resultados de los métodos de ayuda.

Pero aún no ha terminado en ese punto. Dividir el método no es realmente llegar a la raíz de su problema. Ahora que tiene el método dividido y un conjunto de pruebas (poco ortodoxas) que le muestran exactamente lo que hace toda la lógica, está en una buena posición para volver a examinar toda la clase y tratar de descubrir por qué el método era tan grande en primer lugar. Lo más probable es que toda tu clase también tenga que dividirse en unidades más pequeñas con responsabilidades discretas que luego serán más fáciles de probar sin doblar ninguna regla.

3

Estoy bastante sorprendido por algunas de las respuestas aquí.

En esencia algunas personas están diciendo "No probar el código privado, debido a que viola el paradigma TDD"

prueba el código maldita. Haga lo que necesite para asegurarse de que funciona exactamente como debería.

Personalmente, haría los métodos protegidos o predeterminados, escribiré las pruebas, ejecutaré las pruebas y, cuando tenga éxito, volveré a la privacidad.En este punto, comentaría las pruebas relevantes y dejaría un bloque de instrucciones sobre ellas:

/** Perdón por esto, pero heredé un desastre ... * si necesita probar estos métodos, exponga en origen y sin comentarios las siguientes * líneas */

Pero nunca dejamos que la adherencia rígida a una metodología de desarrollo obstaculice la mejora del código.

+6

Su sugerencia es básicamente dogmática: DEBE probar cada método individualmente, porque de lo contrario viola el paradigma TDD. Tonterías. Un método de ayuda puede ser una pieza de código común, y las herramientas de cobertura de código pueden verificar que, si es necesario, las pruebas de la unidad para los métodos públicos cubrieron todo. – M1EK

+0

Amen @ M1EK, ¡solo tenía que publicar una respuesta ya que nadie más había mencionado la cobertura del código! –

+0

El póster original expresó el deseo de probar esos métodos individualmente. "... pruebe también los métodos de ayuda, ya que si uno de ellos falla, el método público que lo llama también fallará, pero de esta forma podemos identificar por qué falló". –

0

Usted prueba estos métodos de ayuda al escribir pruebas unitarias que ejercitan esas partes de su código.

Usted definió una API pública en esta clase por alguna razón, ¿verdad? Prueba eso. Si funciona, la clase funciona.

Use las herramientas de cobertura de código para ayudarlo a saber si se está probando una parte suficiente de esa clase, y si no lo es, escriba más pruebas unitarias para ejercitar la API pública y acceda a las esquinas que no están cubiertas.

6

Si la clase es realmente tan grande, entonces suena como usted debe romper ayudante objetos, no sólo los métodos de ayuda (aunque la extracción de los métodos es a menudo un paso en el camino). Una vez que hayas hecho eso, tu clase anterior será más simple y fácil de probar (quizás con simulacros, quizás no), y puedes probar los métodos en las nuevas clases de soporte directamente.

Mi preferencia es probar a través de la API pública de un objeto. Si eso es demasiado difícil, entonces es una insinuación de que el objeto debe ser dividido.

+1

"Si eso es demasiado difícil, entonces es una pista de que el objeto se debe romper". Toma tu voto popular. – stalepretzel