En el trabajo, uno de mis proyectos consiste principalmente en tomar datos pasados de un cliente externo y conservarlos en una base de datos. Es una aplicación empresarial de Java que utiliza JPA y la mayor parte de nuestra lógica gira en torno a las operaciones CRUD.
La mayoría de nuestros errores involucran JPA de una forma u otra.
- Ejemplo 1: si hace clic dos veces en el botón Guardar, JPA podría intentar insertar la misma entidad en la base de datos por segunda vez, causando una violación de clave principal.
- Ejemplo 2: recupera una entidad de la base de datos, la edita e intenta actualizar sus datos. JPA puede intentar crear una nueva instancia en lugar de actualizar la anterior.
A menudo, la solución necesita agregar / eliminar / cambiar una anotación JPA. Otras veces tiene que ver con modificar la lógica DAO.
No puedo entender cómo obtener confianza en nuestro código utilizando pruebas unitarias y TDD. No estoy seguro de si es porque las pruebas unitarias y el TDD no encajan bien, o si me estoy acercando al problema mal.
Las pruebas unitarias parecen encajar mal porque solo puedo descubrir estos problemas en tiempo de ejecución y necesito implementarlos en un servidor de aplicaciones para reproducirlos. Por lo general, la base de datos debe estar involucrada, lo que considero que está fuera de la definición de una prueba unitaria: estas son pruebas de integración.
TDD parece un mal ajuste porque el bucle de retroalimentación de implementación + prueba es tan lento que me hace muy improductivo. El bucle de retroalimentación de implementación + prueba lleva más de 3 minutos, y eso es solo si ejecuto las pruebas específicamente sobre el código que estoy escribiendo. Ejecutar todas las pruebas de integración lleva más de 30 minutos.
Hay un código fuera de este molde y siempre hago pruebas unitarias siempre que puedo. Pero la mayoría de nuestros errores y los sumideros de tiempo más grandes siempre involucran JPA o la base de datos.
Hay otra pregunta que es similar , pero si siguiera el consejo estaría envolviendo la parte más inestable de mi código (el JPA) y probando todo menos eso. En el contexto de mi pregunta, estaría en la misma mala situación. ¿Cuál es el siguiente paso después de envolver el JPA? En mi opinión, esa pregunta es (quizás) un paso para responder a mi pregunta, pero no una respuesta.
fuente
unit testing != TDD
)Respuestas:
Una opción es usar una base de datos de prueba en memoria como H2 ; tiende a ser aproximadamente 10 veces más rápido que una base de datos estándar que usa discos, y con tiempos de arranque / desmontaje más bajos.
Si ayudará, dependerá en gran medida de si los problemas de JPA que está teniendo son lo suficientemente generales como para que aún fallen en diferentes bases de datos. No tiene mucho sentido ejecutar pruebas más rápido si pierden la mayor parte de los problemas.
Pero si puede hacer 10 carreras con H2 por cada una con el sistema completo, podría dar sus frutos.
fuente
Las bases de datos pueden ser muy fáciles de probar: necesita procedimientos y transacciones almacenados.
Esto es lo que Microsoft dice acerca de las pruebas de unidad de base de datos . También puede ejecutar pruebas unitarias en una base de datos, escribir sus pruebas en Java o C # mediante la configuración de una conexión de base de datos, comenzar una transacción, escribir los datos que desea utilizar para la prueba en la base de datos, ejecutar las pruebas y luego deshacer. No hay daños en la base de datos si estaba usando uno en el que también se implementó y obtiene pruebas completamente aisladas.
Espero que esto pueda darle una idea de cómo hacerlo dentro de su marco.
fuente
Otras personas han respondido con "¡Burla tu DB!" - ¿Pero cuál es el punto de burlarse de su capa de base de datos si realmente necesita probar cómo interactúa con su código?
Lo que está buscando son pruebas de integración y / o pruebas de IU automatizadas. Usted mencionó que el problema ocurre cuando:
La única forma de probar esto es escribir una prueba de IU automatizada para hacer clic dos veces en el botón. Tal vez echa un vistazo a Selenium.
Probablemente también necesitará una unidad de prueba DB y para sus pruebas apúntelo hacia eso. Un dolor de mantenimiento pero bienvenido a TDD en el mundo real.
fuente
En el ejemplo que da en su pregunta, no puede hacer una prueba de unidad / TDD en la situación de hacer clic en el botón dos veces para causar un error muy fácilmente. Pero lo que puede hacer una prueba unitaria es que en el código que se llama cuando hace clic en el botón, si obtiene una excepción de la capa de persistencia, la maneja adecuadamente (burlándose de la capa de persistencia o usando una base de datos en memoria como ha sido sugerido en otras respuestas), ya sea volviendo a lanzar o mostrando un error o lo que sea.
Tiene razón en que TDD puede comenzar a descomponerse cuando necesita realizar pruebas que no se ajustan bien a una prueba unitaria (es decir, pruebas de integración / sistema); esto formó bastante debate en el reciente "Is TDD ¿Muerto?" debates entre Kent Beck, Martin Fowler y David Heinemeier Hansson: http://martinfowler.com/articles/is-tdd-dead/
fuente