Estoy haciendo esta pregunta con respecto a los problemas que he experimentado durante los proyectos TDD. He notado los siguientes desafíos al crear pruebas unitarias.
- Generando y manteniendo datos simulados
Es difícil y poco realista mantener grandes datos simulados. Es aún más difícil cuando la estructura de la base de datos sufre cambios.
- Prueba de GUI
Incluso con MVVM y la capacidad de probar la GUI, se necesita mucho código para reproducir el escenario de la GUI.
- Probar el negocio
Tengo experiencia de que TDD funciona bien si lo limita a una lógica comercial simple. Sin embargo, la lógica empresarial compleja es difícil de probar ya que el número de combinaciones de pruebas (espacio de prueba) es muy grande.
- Contradicción en los requisitos
En realidad, es difícil capturar todos los requisitos bajo análisis y diseño. Muchas veces los requisitos de una nota conducen a una contradicción porque el proyecto es complejo. La contradicción se encuentra tarde en la fase de implementación. TDD requiere que los requisitos sean 100% correctos. En tales casos, uno podría esperar que se capturaran requisitos en conflicto durante la creación de pruebas. Pero el problema es que este no es el caso en escenarios complejos.
He leído esta pregunta: ¿Por qué funciona TDD?
¿TDD realmente funciona para proyectos empresariales complejos, o está prácticamente limitado al tipo de proyecto?
Respuestas:
Falso.
Las pruebas unitarias no requieren datos simulados "grandes". Requiere suficientes datos simulados para probar los escenarios y nada más.
Además, los programadores verdaderamente perezosos piden a los expertos en la materia que creen hojas de cálculo simples de los diversos casos de prueba. Solo una simple hoja de cálculo.
Luego, el programador perezoso escribe un script simple para transformar las filas de la hoja de cálculo en casos de prueba unitaria. Es bastante simple, de verdad.
Cuando el producto evoluciona, las hojas de cálculo de los casos de prueba se actualizan y se generan nuevas pruebas unitarias. Hazlo todo el tiempo. Realmente funciona.
¿Qué? "Reproducir"?
El objetivo de TDD es diseñar cosas para Testability (Test Drive Development). Si la GUI es tan compleja, debe ser rediseñada para que sea más simple y comprobable. Más simple también significa más rápido, más fácil de mantener y más flexible. Pero sobre todo más simple significará más comprobable.
Eso puede ser verdad.
Sin embargo, pedirles a los expertos en la materia que proporcionen los casos de prueba básicos en una forma simple (como una hoja de cálculo) realmente ayuda.
Las hojas de cálculo pueden volverse bastante grandes. Pero está bien, ya que usé un simple script de Python para convertir las hojas de cálculo en casos de prueba.
Y. Tuve que escribir algunos casos de prueba manualmente porque las hojas de cálculo estaban incompletas.
Sin embargo. Cuando los usuarios informaron "errores", simplemente pregunté qué caso de prueba en la hoja de cálculo era incorrecto.
En ese momento, los expertos en la materia corregirían la hoja de cálculo o agregarían ejemplos para explicar lo que se suponía que sucedería. Los informes de errores pueden, en muchos casos, definirse claramente como un problema de caso de prueba. De hecho, desde mi experiencia, definir el error como un caso de prueba roto hace que la discusión sea mucho, mucho más simple.
En lugar de escuchar a los expertos tratar de explicar un proceso comercial súper complejo, los expertos tienen que producir ejemplos concretos del proceso.
No usar TDD exige absolutamente que los requisitos sean 100% correctos. Algunos afirman que TDD puede tolerar requisitos incompletos y cambiantes, donde un enfoque que no sea TDD no puede funcionar con requisitos incompletos.
Si no usa TDD, la contradicción se encuentra tarde en la fase de implementación.
Si usa TDD, la contradicción se encuentra antes cuando el código pasa algunas pruebas y falla otras pruebas. De hecho, TDD le proporciona pruebas de una contradicción al principio del proceso, mucho antes de la implementación (y argumentos durante las pruebas de aceptación del usuario).
Tiene un código que pasa algunas pruebas y falla otras. Nos fijamos en sólo esas pruebas y que encuentre la contradicción. Funciona muy, muy bien en la práctica porque ahora los usuarios tienen que discutir sobre la contradicción y producir ejemplos consistentes y concretos del comportamiento deseado.
fuente
si
Mi primera exposición a TDD fue trabajar en los componentes de middleware para un teléfono celular basado en Linux. Eso finalmente terminó siendo millones de líneas de código fuente, que a su vez se tradujeron en aproximadamente 9 gigabytes de código fuente para varios componentes de código abierto.
Se esperaba que todos los autores de los componentes propusieran tanto un API como un conjunto de pruebas unitarias, y que un comité de pares revisara su diseño. Nadie esperaba la perfección en las pruebas, pero todas las funciones expuestas públicamente tenían que tener al menos una prueba, y una vez que un componente se sometía al control de origen, todas las pruebas unitarias tenían que pasar siempre (incluso si lo hacían porque el componente informaba falsamente funcionó bien).
Sin duda, debido al menos en parte a TDD y a la insistencia de que todas las pruebas unitarias siempre pasan, la versión 1.0 llegó temprano, por debajo del presupuesto y con una estabilidad asombrosa.
Después de la versión 1.0, debido a que las corporaciones querían poder cambiar rápidamente el alcance debido a las demandas de los clientes, nos dijeron que dejáramos de hacer TDD y eliminaron el requisito de que las pruebas unitarias pasen. Fue sorprendente lo rápido que la calidad bajó al baño, y luego el cronograma lo siguió.
fuente
removed the requirement that unit tests pass. It was astonishing how quickly quality went down the toilet, and then the schedule followed it.
- Es como decirle a tu piloto de F1 que no se le permite Pit Stops porque lleva demasiado tiempo ... Idiota.Yo diría que cuanto más complejo sea el proyecto, más beneficios obtendrá de TDD. Los principales beneficios son los efectos secundarios de cómo TDD lo obligará a escribir el código en fragmentos mucho más pequeños y mucho más independientes. Los beneficios clave son:
a) Obtiene una validación mucho, mucho más temprana de su diseño porque su ciclo de retroalimentación es mucho más estricto debido a las pruebas desde el principio.
b) Puede cambiar partes y piezas y ver cómo reacciona el sistema porque ha estado construyendo una colcha de cobertura de prueba todo el tiempo.
c) El código terminado será mucho mejor como resultado.
fuente
¿TDD realmente funciona para proyectos complejos?
Si. No todos los proyectos, por lo que me han dicho, funcionan bien con TDD, pero la mayoría de las aplicaciones comerciales están bien, y apuesto a que las que no funcionan bien cuando están escritas de manera puramente TDD podrían escribirse de manera ATDD sin mayores problemas.
Generación y mantenimiento de datos simulados.
Manténgalo pequeño y solo tenga lo que necesita y este no es el problema aterrador que parece. No me malinterpretes, es un dolor. Pero vale la pena.
Prueba de la GUI
Pruebe el MVVM y asegúrese de que se pueda probar sin la vista. No he encontrado esto más difícil que probar cualquier otro poco de lógica empresarial. Probar la vista en el código que no hago, todo lo que está probando, sin embargo, en este punto es una lógica vinculante, que uno espera que se detecte rápidamente cuando realiza una prueba manual rápida.
Probar el negocio
No se ha encontrado que sea un problema. Muchas pequeñas pruebas. Como dije anteriormente, algunos casos (los solucionadores de rompecabezas Sudoku parecen ser populares) son aparentemente difíciles de hacer TDD.
TDD requiere que los requisitos sean 100% correctos
No, no lo hace. ¿De dónde sacaste esta idea? Todas las prácticas ágiles aceptan que los requisitos cambien. Necesita saber lo que está haciendo antes de hacerlo, pero eso no es lo mismo que exigir que los requisitos sean del 100%. TDD es una práctica común en Scrum, donde los requisitos (Historias de usuarios), por definición, no están 100% completos.
fuente
En primer lugar, creo que su problema es más sobre las pruebas unitarias en general que TDD, ya que no veo nada realmente específico de TDD (prueba-primero + ciclo rojo-verde-refactor) en lo que usted dice.
¿Qué quieres decir con datos simulados? Se supone que un simulacro contiene precisamente casi ningún dato, es decir, ningún campo que no sea uno o dos necesarios en la prueba, y ninguna dependencia que no sea el sistema bajo prueba. Configurar una expectativa simulada o un valor de retorno se puede hacer en una línea, por lo que nada terrible.
Si quiere decir que la base de datos sufre cambios sin que se hayan realizado las modificaciones adecuadas en el modelo de objetos, las pruebas de unidad de pozo están precisamente aquí para advertirlo. De lo contrario, los cambios en el modelo deben reflejarse en las pruebas unitarias obviamente, pero con indicaciones de compilación es algo fácil de hacer.
Tienes razón, la unidad de prueba de la GUI (Ver) no es fácil, y muchas personas lo están haciendo bien sin ella (además, probar la GUI no es parte de TDD). Por el contrario, la unidad que prueba su Controlador / Presentador / ViewModel / cualquier capa intermedia es muy recomendable, en realidad es una de las principales razones por las que los patrones como MVC o MVVM son.
Si su lógica de negocios es compleja, es normal que sus pruebas unitarias sean difíciles de diseñar. Depende de usted hacerlos lo más atómicos posible, cada uno de los cuales solo prueba una responsabilidad del objeto bajo prueba. Las pruebas unitarias son aún más necesarias en un entorno complejo, ya que proporcionan una red de seguridad que garantiza que no se rompen las reglas o requisitos comerciales al realizar cambios en el código.
Absolutamente no. El software exitoso requiere que los requisitos sean 100% correctos;) Las pruebas unitarias solo reflejan cuál es su visión de los requisitos actualmente; si la visión es defectuosa, su código y su software también lo serán, pruebas unitarias o no ... Y ahí es donde brillan las pruebas unitarias: con títulos de prueba suficientemente explícitos, sus decisiones de diseño e interpretación de requisitos se vuelven transparentes, lo que hace que sea más fácil señalar preste atención a lo que debe cambiarse la próxima vez que su cliente diga: "esta regla comercial no es exactamente como me gustaría".
fuente
Tengo que reír cuando escucho a alguien quejarse de que la razón por la que no pueden usar TDD para probar su aplicación es porque su aplicación es muy complicada. Cual es la alternativa? ¿Tienes monos de prueba golpeando acres de teclados? ¿Dejar que los usuarios sean los probadores? ¿Qué más? Por supuesto que es difícil y complejo. ¿Crees que Intel no prueba sus chips hasta que se envían? ¿Qué tan "cabeza en la arena" es eso?
fuente
He descubierto que TDD (y las pruebas unitarias en general) son prácticamente imposibles por una razón relacionada: Algoritmos complejos, novedosos y / o difusos. El problema que más me encuentro en los prototipos de investigación que escribo es que no tengo idea de cuál es la respuesta correcta que no sea ejecutar mi código. Es demasiado complicado resolver razonablemente a mano cualquier cosa que no sean casos ridículamente triviales. Esto es especialmente cierto si el algoritmo involucra heurística, aproximaciones o no determinismo. Todavía trato de probar la funcionalidad de nivel inferior de la que depende este código y utilizo afirmaciones en gran medida como controles de cordura. Mi método de prueba de último recurso es escribir dos implementaciones diferentes, idealmente en dos idiomas diferentes usando dos conjuntos diferentes de bibliotecas y comparar los resultados.
fuente
Desde mi experiencia: Sí para Unittests (prueba de módulos / características de forma aislada) porque en su mayoría no tienen los problemas que menciona: (Gui, Mvvm, Business-Modell). Nunca tuve más de 3 simulacros / stubs para completar una prueba de unidad (pero tal vez su dominio requiere más).
Sin embargo, no estoy seguro si TDD podría resolver los problemas que mencionó en la integración o las pruebas de extremo a extremo con las pruebas de estilo BDD.
Pero al menos algunos problemas pueden reducirse .
Esto es cierto si desea hacer una cobertura completa en el nivel de prueba de integración o prueba de extremo a extremo. Puede ser más fácil hacer la cobertura completa en un nivel de prueba de unidad.
Ejemplo: comprobación de permisos de usuario complejos
Probar la función
IsAllowedToEditCusterData()
en un nivel de prueba de integración requeriría pedir a diferentes objetos información sobre el usuario, dominio, cliente, entorno ...Burlarse de estas partes es bastante difícil. Esto es especialmente cierto si
IsAllowedToEditCusterData()
tiene que conocer estos diferentes objetos.En un nivel de prueba de unidad, tendría una función
IsAllowedToEditCusterData()
que toma, por ejemplo, 20 parámetros que contienen todo lo que la función necesita saber. DadoIsAllowedToEditCusterData()
que no necesita saber qué campos tiene auser
, adomain
, acustomer
, ...., esto es fácil de probar.Cuando tuve que implementar
IsAllowedToEditCusterData()
tuve dos sobrecargas:Una sobrecarga que no hace más que obtener esos 20 parámetros y luego llamar a la sobrecarga con los 20 parámetros que toman decisiones.
(Mi
IsAllowedToEditCusterData()
tenía solo 5 parámetros y necesitaba 32 combinaciones diferentes para probarlo por completo)Ejemplo
fuente
¡La triste respuesta es que nada realmente funciona para grandes proyectos complejos!
TDD es tan bueno como cualquier otra cosa y mejor que la mayoría, pero TDD por sí solo no garantizará el éxito en un proyecto grande. Sin embargo, aumentará sus posibilidades de éxito. Especialmente cuando se usa en combinación con otras disciplinas de gestión de proyectos (verificación de requisitos, casos de uso, matriz de trazabilidad de requisitos, tutoriales de código, etc., etc.).
fuente
Recuerde que las pruebas unitarias son especificaciones forzadas . Esto es especialmente valioso en proyectos complejos. Si su antigua base de código no tiene ninguna prueba que lo respalde, nadie se atreverá a cambiar nada porque tendrá miedo de romper algo.
"Wtf. ¿Por qué está esta rama de código incluso allí? No sé, tal vez alguien lo necesite, mejor dejarlo allí que molestar a alguien ..." Con el tiempo, los proyectos complejos se convierten en una tierra de basura.
Con las pruebas, cualquiera puede decir con confianza "He hecho cambios drásticos, pero todas las pruebas aún están aprobadas". Por definición, no ha roto nada. Esto lleva a proyectos más ágiles que pueden evolucionar. Quizás una de las razones por las que todavía necesitamos personas para mantener COBOL es porque las pruebas no fueron populares desde entonces: P
fuente
He visto un gran proyecto complejo fallar por completo cuando TDD se usó exclusivamente, es decir, sin al menos configurarse en un depurador / IDE. Los datos y / o pruebas simulados resultaron insuficientes Los datos reales de los clientes Beta eran confidenciales y no podían copiarse ni registrarse. Por lo tanto, el equipo de desarrollo nunca pudo solucionar los errores fatales que se manifestaron cuando se apuntaron a datos reales, y todo el proyecto se descartó, todos fueron despedidos, todo.
La forma de solucionar este problema habría sido activarlo en un depurador en el sitio del cliente, vivir con los datos reales, avanzar por el código, con puntos de interrupción, variables de observación, memoria de observación, etc. Sin embargo, este equipo, quienes pensaron que su código era adecuado para adornar las mejores torres de marfil, durante un período de casi un año, nunca habían activado su aplicación. Eso me voló la cabeza.
Entonces, como todo, el equilibrio es la clave. TDD puede ser bueno, pero no confíes exclusivamente en él.
fuente
Creo que sí, ver Test Driven Development realmente funciona
fuente
Si la combinación del presupuesto, los requisitos y las habilidades de equipo se encuentran en el cuadrante del espacio del proyecto denominado "abandone la esperanza a todos los que ingresen aquí", entonces, por definición, es muy probable que el proyecto fracase.
Quizás los requisitos son complejos y volátiles, la infraestructura inestable, el equipo junior y con alta rotación, o el arquitecto es un idiota.
En un proyecto TDD, el síntoma de esta falla inminente es que las pruebas no se pueden escribir a tiempo; intenta, sólo para descubrir 'que va a tomar este tiempo, y sólo tenemos que '.
Otros enfoques mostrarán diferentes síntomas cuando fallan; más comúnmente entrega de un sistema que no funciona. La política y los contratos determinarán si eso es preferible.
fuente
TDD
puede sonar como un dolor inicial, pero a largo plazo sería tu mejor amigo, confía en míTDD
realmente hará que la aplicación sea mantenible y segura a largo plazo.fuente