TDD, nuevas pruebas mientras que las antiguas aún no se implementaron

13

Estoy experimentando con el desarrollo basado en pruebas, y descubrí que a menudo llego a la siguiente situación:

  1. Escribo pruebas para alguna funcionalidad X. Esas pruebas fallan.
  2. Al intentar implementar X, veo que necesito implementar alguna característica Y en una capa inferior de mi código. Entonces...
  3. Escribo pruebas para Y. Ahora ambas pruebas para X e Y fallan.

Una vez que tenía 4 funciones en diferentes capas de código trabajando al mismo tiempo, y estaba perdiendo mi enfoque en lo que realmente estoy haciendo (demasiadas pruebas fallan al mismo tiempo).

Creo que podría resolver esto poniendo más esfuerzo en la planificación de mis tareas incluso antes de comenzar a escribir pruebas. Pero en algunos casos no sabía que tendría que profundizar más, porque, por ejemplo, no conocía muy bien la API de la capa inferior.

¿Qué debo hacer en tales casos? ¿TDD tiene alguna recomendación?

liori
fuente

Respuestas:

9

Lo bueno es que se da cuenta de que su código bajo prueba necesita asistencia. En lugar de implementarlo de inmediato, cree una interfaz y use simulacros para asegurarse de que sus pruebas tageing el código correcto. Después de pasar esas pruebas, puede pasar a implementar el código en el que se basa.

Michael Brown
fuente
Mis pruebas generalmente no tienen conocimiento sobre qué debe hacer internamente un método (por ejemplo, qué API de nivel inferior llamar). ¿Debo ajustar las pruebas para simular lo que necesito en el código probado?
liori
2
Del mismo modo, sus clases evaluadas no deberían preocuparse por lo que hacen las 'capas inferiores'. Use simulacros / talones en lugar de clases / objetos reales. Esto puede requerir un poco más de esfuerzo en el diseño, pero da como resultado un código menos acoplado y más fácil de reutilizar.
Mchl
1
¿Estás usando inyección de dependencia? Así es como puede separar fácilmente las preocupaciones de nivel inferior de las clases de nivel superior. Su clase bajo prueba tiene un constructor con parámetros para sus dependencias (como interfaces) en su prueba, crea simulacros para las interfaces. Básicamente, finges que ya has implementado los servicios de nivel inferior.
Michael Brown
@ Mike Brown, sí, lo hago. Sé que puedo crear objetos simulados. Pero luego, en mi prueba de función X, tengo que saber qué parte de las dependencias Xnecesito burlarme. Siento que esto es parte de los detalles de la implementación, que no deberían ser parte de las pruebas; de lo contrario, podría necesitar cambiar las pruebas mientras refactorizo ​​la implementación. ¿Debería preocuparme por eso?
liori
1
En absoluto ... las pruebas deben reflejar los supuestos del sistema bajo prueba. También le ayuda a exponer lo que necesita de los servicios en los que se basa el sistema. Solía ​​estar de acuerdo con usted en este asunto, pero lo comparo con cómo llegué a entender la programación recursiva. Primero escribe el código asumiendo que tiene una función que hace lo que quiere. Luego escribes el código que hace lo que quieres.
Michael Brown
4

Los stubs y los simulacros se pueden usar para simular la funcionalidad que aún no se está modificando / implementando. También pueden ayudarlo a resolver las dependencias que causan este tipo de 'reacción en cadena'.

Por otro lado, tal vez mantener solo una prueba (fallida) que impulse el próximo cambio es el mejor enfoque.

Otras pruebas que se dirigen al código que se basa en la nueva funcionalidad se pueden deshabilitar temporalmente, ya que no son realmente relevantes en este punto, es decir. en su caso, desactive las pruebas para X hasta que implemente Y, etc.

De esa manera, puedes concentrarte en el próximo cambio, que es lo que quieres, creo.

Ratkok
fuente
Ja, busqué una función para desactivar una prueba durante una ejecución de prueba dentro de mi IDE, y no he encontrado una. Ahora descubrí que Python unittestya tiene saltos de prueba. Esto podría ser suficiente para mí.
liori
Utilizamos el marco de prueba de Google C ++, y tiene una opción para deshabilitar las pruebas. Las pruebas deshabilitadas no se ejecutan sino que se compilan, en el momento en que las necesita, están listas para ejecutarse (además, puede 'forzar la ejecución' de las pruebas deshabilitadas - tipo de 'habilitación en tiempo de ejecución') - excelente característica ...
ratkok
3

Detener

Por casualidad parece que puede haber dos problemas separados aquí:

  1. olvidó algunas historias y escenarios de prueba, y no los descubrió hasta que comenzó a trabajar en un escenario de prueba en particular, y / o

  2. en realidad se está haciendo pruebas unitarias, y no TDD función de las pruebas

Para el n. ° 1, deténgase , regrese y actualice las historias y los escenarios de prueba, luego comience de nuevo con un escenario diferente.

Para el n. ° 2, deténgase y recuerde que está probando características, no unidades, por lo tanto, utilice simulacros para pasar por alto otras interfaces y / o implemente más código para que la prueba pase sin agregar nuevos escenarios de prueba. Esto supone que no le faltan escenarios de prueba, sino que, en cambio, esto es muy común, combina pruebas de unidad y TDD.

Steven A. Lowe
fuente
Realmente me gusta su respuesta, explica mejor lo que realmente está sucediendo.
maple_shaft
... Dicho esto, no conozco a un primer ministro en el mundo que no se vuelva completamente loco con la frase, "DETÉNGASE, tenemos que retroceder". Intentarán todo menos sacrificar a su primogénito en el altar para que el proyecto siga adelante, la deuda técnica y las pruebas unitarias incompletas serán condenadas. Supongo que no puedes culparlos cuando su única métrica en una organización es terminar el proyecto a tiempo. Algunas organizaciones simplemente valoran el tiempo por encima de la calidad y es por eso que probablemente nunca vi a TDD trabajar con éxito en este tipo de organizaciones, lo que desafortunadamente es la MAYORÍA de ellas IMO.
maple_shaft
@maple_shaft: la cantidad de tiempo que se detiene para reagruparse puede ser de unas pocas horas, a menos que su proceso esté muy alejado de la base, en cuyo caso, si se detiene durante unos días para volver a encaminarlo, será mucho más probable que El proyecto tendrá éxito. ¡No tiene sentido ir a toda velocidad por el camino equivocado!
Steven A. Lowe
0

Esta es una gran pregunta y una GRAN frustración para mí también con TDD. Siento que a TDD le falta en este escenario en el que simplemente no tiene forma de saber qué componentes o características de nivel inferior necesitará hasta que comience a desarrollar.

Personalmente, descubrí que TDD solo funciona si sabes exactamente lo que debes hacer y a qué debes llamar para realizar una función. Los desarrolladores no siempre saben todo antes de comenzar, así que he descubierto que la mejor manera de mitigar la situación que usted describe es:

Prototipo

Cuando hago prototipos de aplicaciones simples para explorar y descubrir métodos y enfoques para un problema técnico, descubro mucho del trabajo preliminar y elimino esa investigación antes de comenzar. Diseñar y estimar se vuelve mucho más fácil también.

Si el prototipo tiene que estar tan involucrado que se convierta en la aplicación, le insto a que no haga lo perezoso, sin embargo, y cree pruebas unitarias para su prototipo después del hecho.

Debería saber más sobre la API de nivel inferior en ese momento y ser capaz de burlarse con éxito de la API de nivel inferior en sus componentes de nivel superior.

árbol de arce
fuente
Por lo tanto, en realidad está sugiriendo obtener más información para la fase de planificación mediante la realización de una codificación exploratoria de manera informal (= sin seguir una metodología formalizada). Y luego suponga que dará suficiente información para planificar el código real. Estoy en lo cierto?
liori
¿Por qué supone que la creación de prototipos es un proceso informal? Cada estimación debe tener en cuenta la creación de prototipos y los cronogramas del proyecto deben tenerlo en cuenta, así como una tarea de desarrollo necesaria. Lo veo igual que Diseño o Revisión de código. En ese sentido, está formalizado y debe tenerse en cuenta, incluso más en tareas con muchas incógnitas. Sin la creación de prototipos y la capacidad de realizar una Prueba de concepto, luego de realizar TDD solo se supone que los desarrolladores saben TODO sobre CUALQUIER COSA con TODAS las características. El mundo real no funciona de esa manera y no me importa lo inteligente o experimentado que seas.
maple_shaft
Por "manera informal" no quise decir que el tiempo para la creación de prototipos no debe tenerse en cuenta, pero que si bien haces prototipos, no sigues TDD ni ninguna otra metodología de código.
liori
TDD es una metodología para pruebas y desarrollo de unidades. ¿Tendría sentido hacer TDD para la revisión de código? ¿TDD tiene sentido para el diseño, la escritura de especificaciones técnicas o la pizarra? La creación de prototipos es una tarea en sí misma, un tipo de desarrollo exploratorio para investigación, prueba de concepto y educación.
maple_shaft
1
TDD tiene mucho sentido para la creación de prototipos. Le permite exponer rápidamente las cosas de lo que sea (objeto, función, API, programa completo) en forma de un conjunto de requisitos repetibles y ejecutables. Hazte un favor y lee el software orientado a objetos en crecimiento guiado por pruebas ; te lleva paso a paso a través de la construcción de una aplicación completa (incluida la integración) en una primera prueba.
Frank Shearar
0

Depende de qué tipo de pruebas tu escritura mientras haces TDD.

El modelo clásico es escribir pruebas unitarias y hacer uso de simulacros o trozos para desacoplar la prueba de las otras "unidades" de código.

Hay muchos otros modelos alternativos, como ATDD, donde se prueba una pila completa o una prueba de pila casi completa. En este caso particular, sus pruebas de escritura que afirman el comportamiento del programa requerido no son una sola unidad de código, por lo que no escribiría otras pruebas. Obtendrá el implemento de ida y vuelta para satisfacer la prueba. Luego agrega otras pruebas para otras características / comportamientos.

dietbuddha
fuente