Estas son las reglas de Robert C. Martin para TDD :
- No está permitido escribir ningún código de producción a menos que sea para aprobar una prueba de unidad que falla.
- No se le permite escribir más de una prueba unitaria de la que es suficiente para fallar; y las fallas de compilación son fallas.
- No está permitido escribir más código de producción del que sea suficiente para pasar la prueba de una unidad que falla.
Cuando escribo una prueba que parece que vale la pena pero que pasa sin cambiar el código de producción:
- ¿Eso significa que hice algo mal?
- ¿Debo evitar escribir tales pruebas en el futuro si me pueden ayudar?
- ¿Debo dejar esa prueba allí o eliminarla?
Nota: Estaba tratando de hacer esta pregunta aquí: ¿Puedo comenzar con una prueba de unidad aprobada? Pero no pude articular la pregunta lo suficientemente bien hasta ahora.
testing
unit-testing
tdd
Daniel Kaplan
fuente
fuente
Respuestas:
Dice que no puede escribir código de producción a menos que sea para aprobar una prueba de unidad que falla y no que no pueda escribir una prueba que pase desde el principio. La intención de la regla es decir "Si necesita editar el código de producción, asegúrese de escribir o cambiar una prueba primero".
A veces escribimos pruebas para probar una teoría. La prueba pasa y eso refuta nuestra teoría. Entonces no eliminamos la prueba. Sin embargo, podríamos (sabiendo que tenemos el respaldo del control de origen) romper el código de producción, para asegurarnos de que entendemos por qué pasó cuando no lo esperábamos.
Si resulta ser una prueba válida y correcta, y no está duplicando una prueba existente, déjelo allí.
fuente
Significa que:
La última situación es más común de lo que piensas. Como un ejemplo completamente engañoso y trivial (pero aún ilustrativo), digamos que usted escribió la siguiente prueba de unidad (pseudocódigo, porque soy vago):
Porque todo lo que realmente necesitas es el resultado de 2 y 3 sumados.
Su método de implementación sería:
Pero digamos que ahora necesito agregar 4 y 6 juntos:
No necesito reescribir mi método, porque ya cubre el segundo caso.
Ahora digamos que descubrí que mi función Agregar realmente necesita devolver un número que tenga un límite máximo, digamos 100. Puedo escribir un nuevo método que pruebe esto:
Y esta prueba ahora fallará. Ahora debo reescribir mi función
para hacerlo pasar.
El sentido común dicta que si
pasa, no hace que su método falle deliberadamente solo para que pueda tener una prueba fallida y pueda escribir un nuevo código para hacer que pase la prueba.
fuente
add(2,3)
pase, literalmente regresarías 5. Codificado. Luego , escribiría la prueba para loadd(4,6)
cual lo obligaría a escribir el código de producción que lo hace pasar sin romperseadd(2,3)
al mismo tiempo. Se podría acabar con elreturn x + y
, pero no sería empezar con él. En teoria. Naturalmente, a Martin (o tal vez fue otra persona, no recuerdo) le gusta proporcionar tales ejemplos para la educación, pero no espera que realmente escriba un código tan trivial de esa manera.Su prueba pasa pero no está equivocado. Creo que sucedió porque el código de producción no es TDD desde el principio.
Supongamos que TDD canónico (?). No hay código de producción, pero hay algunos casos de prueba (que por supuesto siempre fallan). Agregamos código de producción para pasar. Luego, deténgase aquí para agregar más casos de prueba fallida. Nuevamente agregue el código de producción para pasar.
En otras palabras, su prueba podría ser un tipo de prueba de funcionalidad, no una simple prueba de unidad TDD. Esos son siempre activos valiosos para la calidad del producto.
Personalmente no me gustan tales reglas totalitarias e inhumanas; (
fuente
En realidad, el mismo problema surgió en un dojo anoche.
Hice una investigación rápida al respecto. Esto es lo que se me ocurrió:
Básicamente no está prohibido explícitamente por las reglas TDD. Quizás se necesiten algunas pruebas adicionales para demostrar que una función funciona correctamente para una entrada generalizada. En este caso, la práctica de TDD se deja de lado por un momento. Tenga en cuenta que dejar la práctica de TDD en breve no es necesariamente romper las reglas de TDD siempre y cuando no se agregue ningún código de producción mientras tanto.
Se pueden escribir pruebas adicionales siempre que no sean redundantes. Una buena práctica sería hacer pruebas de particionamiento de clase de equivalencia. Eso significa que se prueban los casos límite y al menos un caso interno para cada clase de equivalencia.
Sin embargo, un problema que podría ocurrir con este enfoque es que si las pruebas pasan desde el principio, no se puede asegurar que no haya falsos positivos. Esto significa que podrían pasar pruebas porque las pruebas no se implementan correctamente y no porque el código de producción funciona correctamente. Para evitar esto, el código de producción debe cambiarse ligeramente para romper la prueba. Si esto hace que la prueba falle, lo más probable es que se implemente correctamente y el código de producción se puede volver a cambiar para que la prueba pase nuevamente.
Si solo desea practicar TDD estricto, es posible que no escriba ninguna prueba adicional que pase desde el principio. Por otro lado, en un entorno de desarrollo empresarial, uno debería abandonar la práctica de TDD si las pruebas adicionales parecen útiles.
fuente
Una prueba que pasa sin modificar el código de producción no es inherentemente mala, y a menudo es necesaria para describir un requisito adicional o un caso límite. Mientras su prueba "parezca que valga la pena", como usted dice que la suya lo hace, consérvela.
Donde te metes en problemas es cuando escribes una prueba que ya pasó como un reemplazo para entender realmente el espacio del problema.
Podemos imaginarnos en dos extremos: un programador que escribe una gran cantidad de pruebas "por si acaso" uno atrapa un error; y un segundo programador que analiza cuidadosamente el espacio del problema antes de escribir un número mínimo de pruebas. Digamos que ambos están tratando de implementar una función de valor absoluto.
El primer programador escribe:
El segundo programador escribe:
La implementación del primer programador podría resultar en:
La implementación del segundo programador podría resultar en:
Todas las pruebas pasan, pero el primer programador no solo ha escrito varias pruebas redundantes (ralentizando innecesariamente su ciclo de desarrollo), sino que tampoco ha podido probar un caso límite (
abs(0)
).Si se encuentra escribiendo pruebas que pasan sin modificar el código de producción, pregúntese si sus pruebas realmente están agregando valor o si necesita pasar más tiempo entendiendo el espacio del problema.
fuente
abs(n) = n*n
y aprobó.abs(-2)
. Como con todo, la moderación es la clave.