2010-11-28 19 views
7

Tengo esta clase que quería construir usando TDD, pero fallé. Es una clase bastante básica llamada SubMissions, y todo lo que hace es obtener algunos datos de una base de datos SQL.Desarrollo basado en pruebas que no funciona para mi clase

por lo que tiene como métodos getSubMissionForPage(), etc .. getSubMissionFromId()

Probé la construcción de ésta utilizando TDD. Mi primera prueba contenía una llamada al getSubMissionPage(), cuyo único propósito es devolver datos. Así que hacer que esta prueba falle es bastante difícil, ya que puede devolver cualquier dato, no pude encontrar una manera de hacerlo fallar.

Sé que hacer que su prueba falle es el primer paso para saber qué implementar, pero ¿qué hace cuando no hay manera de reprobar una prueba?

+1

En estas situaciones, puede precargar la base de datos con datos específicos que espera que devuelva. Luego puede verificar eso (por ejemplo, el ID de la fila o el número de filas) para asegurarse de que obtiene aproximadamente los datos correctos. – obfuscation

Respuesta

8

Siempre que confíe en una fuente de datos externa, su prueba siempre puede fallar. ¿Qué pasa si la conexión se cae a su DB? ¿Qué sucede si la tabla no existe de la que está tratando de obtener datos? ¿Qué sucede si los datos que recibe no son los que espera?

Las clases de prueba que se conectan a DB son un poco más complicadas que probar HelloWorld.java, porque necesita un poco de forma de mock the DB. Puede obtener más información sobre Mock Objects here.

Respuesta breve, sus pruebas/software SIEMPRE pueden fallar. Si no cree que su prueba puede fallar, no está pensando lo suficiente sobre el espacio problemático.

+0

+1 para la respuesta corta. –

+0

Sí, las pruebas siempre pueden fallar, pero esto no responde la pregunta con respecto a CÓMO hacer que la prueba falle en la primera instancia mientras se hace TDD. –

2

Bien. hay algunas cosas de tipo estándar para probar: nula y vacía cadena de primavera a la mente. Si los datos realmente pueden ser cualquier cosa, entonces todo es válido.

Comenzar con las pruebas de una base de datos probablemente no sea la mejor manera de sumergirse en TDD. Comience con una clase que no tenga dependencias. Imagine un juego de ajedrez, es posible que tenga clases como:

  • Junta
  • Plaza
  • Ubicación (la fila, columna de la casilla del tablero)

Me gustaría empezar con la ubicación ya no tiene dependencias, luego Square, ya que solo depende de la ubicación, del tablero, ya que solo depende de Square.

3

La belleza de TDD es que si encuentra una prueba difícil de escribir, apunta a un problema potencial en el diseño. En este caso, la abstracción de su lógica de acceso a datos.

Por ejemplo, puede usar Dependency Injection para enviar una interfaz a un repositorio de acceso a datos (utilizando un simulacro en su caso de prueba) que le permitirá aislar sus pruebas de acceso a datos de sus pruebas lógicas. es decir, crea un SubmissionRepository que maneja el acceso a los datos, y tu clase de envíos maneja la lógica de negocios, yendo a tu repositorio para las operaciones básicas de crud y shaping.

Naturalmente, en algún momento tendrá que probar algunos datos de acceso como parte de una prueba de integración, pero siempre utilizo el ejercicio de comenzar con TDD para ayudar a conducir más diseños desacoplados.

+0

Como ejemplo, podría construir un repositorio falso que devuelva un registro falso dado un ID, o una matriz dada una página, etc. - de esa manera puede probar las dos primeras funciones, y considerar cosas como la forma en que su repositorio debe manejar identificaciones inválidas, etc. –

+0

+1 para la inyección de dependencia. Eso de hecho va de la mano con tdd –

+0

+1 para burlarse o fingir recursos externos – JeffH

0

No tiene que escribir una prueba para cada método. Si cree que una prueba es demasiado fácil de romper, puede decidir no escribir una prueba para ella. Algunos argumentarán que todavía deberías escribir una prueba, pero creo que hay casos en los que no es necesario.

Tome un vistazo a este JUnit FAQ: http://junit.sourceforge.net/doc/faq/faq.htm#best_3

0
  1. modificar su clase para lanzar cualquier tiempo de ejecución y ver que falla la prueba.
  2. mofify su prueba a esperar y ver excepción carece de esa

(1) y (2) fueron sólo los ejercicios que le ayudará a estar seguro de que la prueba está funcionando.

Ahora hágase la pregunta: ¿cuál podría ser el motivo de la falla en la prueba? Creo que, en su caso, la lista de razones es así: 1. hay conexión a DB 2. esquema DB 3. datos inconsistentes equivocadas

Éstas son las formas para simular estas razones: 1. apague el DB o cambie las credenciales/jdbc URL que está utilizando para conectarse. 2. suelte una tabla interesante o cambie el nombre (s) de sus columnas. 3. es un poco difícil hacer que los datos sean inconsistentes. Esto sucede típicamente cuando las restricciones de DB no están definidas correctamente. A veces las personas lo hacen para que el esquema sea más genérico. Si no es tu caso, olvídate del # 3.

¡Buena suerte con TDD! Creo que en el futuro sus escenarios de prueba serán más sofisticados.

1

'getSubMissionPage' no debe devolver datos, se supone que debe realizar una solicitud específica y luego devolver algo en función de la solicitud.

Debe configurar 'SubMissions' para usar un origen de datos falso y luego probar que la clase realiza las solicitudes de correlación y correlaciona los datos en los objetos correctamente.

+0

Tiene razón, en realidad devuelve una especie de tipo de datos de mapa con claves específicas. Entonces, ¿sería un buen caso de prueba asegurar que esas claves realmente existen? –

+0

comienza con la devolución nula. Luego verifique que las claves requeridas estén presentes en el mapa. –

3

Haga que el método arroje una RuntimeException si desea que la prueba falle. Eclipse completará los stubs del método con una UnsupportedOperationException adecuada para usted.

Luego, para que la prueba se ponga verde, simplemente haga que el método devuelva nulo en lugar de arrojar.

No se moleste en conectarse a la base de datos hasta que una o dos pruebas adicionales lo obliguen a hacerlo.

+0

'throw new RuntimeException (" fail ");' generalmente funcionará muy bien. –

+0

+1 Normalmente uso 'throw new UnsupportedOperationException();'. Absolutamente de acuerdo con esta respuesta. –

+0

+1 y otro voto para UnsupportedOperationException(). Si no puede hacer que la prueba falle, es porque ya ha implementado el código. Hazlo una vez que tengas la prueba. Por cierto, @Luca Matteis, su clase es responsable de algo más que obtener datos SQL; probablemente esté creando la conexión de la base de datos, juntando la consulta y ejecutándola. Podrías delegar algunos de ellos y burlarlos. – Lunivore

5

La recuperación desde una base de datos no es el lugar para comenzar con TDD.

Puede hacer bien en mirar algunos ejemplos de TDD en la red. El bowling game scoring de Bob Martin es un lugar divertido para comenzar.

Dicho esto ...

Mi primer examen a una llamada a getSubMissionPage(), que es único propósito para devolver datos. Así que hacer que esta prueba falle es bastante difícil, ya que puede devolver cualquier dato, no pude encontrar una manera de hacerlo fallar.

El propósito no es devolver datos, sino devolver los datos correctos.

La manera de hacer una prueba para esto es proporcionarle una base de datos que debe hacer que devuelva un resultado específico y que así sea. Y, por supuesto, no lo hará hasta que escriba el código correcto, de modo que primero escriba la prueba y la implementación real después de ver que falla.

La parte más difícil con TDD que involucra una base de datos es que las pruebas con una base de datos real pueden ser lentas y hacer la prueba repetible puede ser difícil ya que las pruebas a veces cambiarán los datos. Para lidiar con estos problemas, puede obtener ayuda de herramientas como DbUnit, simular JDBC, usar una base de datos en memoria y usar reversiones para asegurarse de que sus pruebas no hagan cambios permanentes.

Pero es mejor que no comience con cosas de la base de datos.

Cuestiones relacionadas