¿TDD realmente funciona para proyectos complejos?

52

Estoy haciendo esta pregunta con respecto a los problemas que he experimentado durante los proyectos de 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.

  • Probando GUI

Incluso con MVVM y la capacidad de probar GUI, se necesita mucho código para reproducir el escenario GUI.

  • Probando el negocio

Tengo experiencia en que TDD funciona bien si lo limita a una lógica de negocios simple. Sin embargo, la lógica de negocios 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 llevan a la 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, se podría esperar que se capturaran los requisitos en conflicto durante la creación de las 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?

    
pregunta Amir Rezaei 31.01.2011 - 12:26

14 respuestas

52
  

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.

Falso.

La prueba de la unidad no requiere datos "grandes" simulados. Requiere suficientes datos simulados para probar los escenarios y nada más.

Además, los programadores realmente perezosos piden a los expertos en la materia que creen hojas de cálculo simples de los distintos casos de prueba. Solo una simple hoja de cálculo.

Luego, el programador perezoso escribe una secuencia de comandos simple para transformar las filas de la hoja de cálculo en casos de prueba de unidad. 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.

  

Incluso con MVVM y la capacidad de probar la GUI, se necesita mucho código para reproducir el escenario de la GUI.

¿Qué? "Reproducir"?

El punto de TDD es diseñar cosas para probabilidad (Test Drive Development). Si la GUI es así de compleja, entonces debe ser rediseñada para que sea más simple y más comprobable. Más simple también significa más rápido, más fácil de mantener y más flexible. Pero en su mayoría más simple significará más verificable.

  

Tengo experiencia en que TDD funciona bien si lo limita a una lógica de negocios simple. Sin embargo, la lógica de negocios compleja es difícil de probar ya que el número de combinación de prueba (espacio de prueba) es muy grande.

Eso puede ser cierto.

Sin embargo, ayudar a los expertos en la materia a proporcionar los casos de prueba principales en una forma simple (como una hoja de cálculo) realmente ayuda.

Las hojas de cálculo pueden llegar a ser bastante grandes. Pero está bien, ya que utilicé un sencillo 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 iba a suceder. 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 más simple.

En lugar de escuchar a los expertos que intentan explicar un proceso de negocio súper complejo, los expertos tienen que producir ejemplos concretos del proceso.

  

TDD requiere que los requisitos sean 100% correctos. En tales casos, se podría esperar que se capturaran los requisitos en conflicto durante la creación de las pruebas. Pero el problema es que este no es el caso en un escenario complejo.

No usar TDD obliga absolutamente a que los requisitos sean 100% correctos. Algunos afirman que TDD puede tolerar requisitos incompletos y cambiantes, donde un enfoque no 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 anteriormente cuando el código pasa algunas pruebas y falla otras pruebas. De hecho, TDD le brinda a usted una prueba de una contradicción anterior en el proceso, mucho antes de la implementación (y los argumentos durante las pruebas de aceptación del usuario).

Tienes un código que pasa algunas pruebas y falla otras. Miras solo esas pruebas y encuentras la contradicción. Funciona realmente 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.

    
respondido por el S.Lott 31.01.2011 - 13:57
27

Mi primera exposición a TDD estaba trabajando 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 convirtieron en aproximadamente 9 gigabytes de código fuente para varios componentes de código abierto.

Se esperaba que todos los autores de componentes propusieran tanto una API como un conjunto de pruebas unitarias, y que un comité de pares las revisara en su diseño. Nadie esperaba la perfección en las pruebas, pero todas las funciones expuestas públicamente debían tener al menos una prueba, y una vez que un componente se sometía al control de la fuente, 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 la insistencia en que todas las pruebas de unidad siempre se aprueben, la versión 1.0 llegó temprano, sin presupuesto y con una estabilidad asombrosa.

Después de la versión 1.0, debido a que la empresa quería 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 pasaran. Fue sorprendente la rapidez con la que la calidad se fue al inodoro y luego el calendario lo siguió.

    
respondido por el Bob Murphy 01.02.2011 - 06:20
18

Argumentarí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 te obligará a escribir el código en trozos mucho más pequeños e independientes. Los beneficios clave son:

a) Obtienes una validación mucho más temprana de tu diseño porque tu ciclo de retroalimentación es mucho más estricto debido a las pruebas desde el principio.

b) Puedes cambiar los bits y las piezas y ver cómo reacciona el sistema porque has estado construyendo una colcha de cobertura de prueba todo el tiempo.

c) Como resultado, el código terminado será mucho mejor.

    
respondido por el Wyatt Barnett 31.01.2011 - 15:33
10

¿TDD funciona realmente para proyectos complejos?
Sí. No todos los proyectos me dicen que funciona bien con TDD, pero la mayoría de las aplicaciones empresariales están bien, y apuesto a que los que no funcionan bien cuando se escriben de forma TDD pura podrían escribirse de forma ATDD sin mayores problemas.

Generando y manteniendo datos simulados
Manténgalo pequeño y solo tenga lo que necesita y este no es el problema que parece. No me malinterpretes, es un dolor. Pero vale la pena.

Probando GUI
Pruebe la MVVM y asegúrese de que se pueda probar sin la vista. No he encontrado esto más difícil que probar cualquier otro bit de lógica empresarial. Al hacer la prueba en el código que no hago, todo lo que está probando, sin embargo, en este punto es una lógica vinculante, que se espera que se detecte rápidamente cuando se realiza una prueba manual rápida.

Probando el negocio
No se encontró que sea un problema. Un montón de pequeñas pruebas. Como dije anteriormente, algunos casos (los solucionadores de rompecabezas de 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. Debe 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 completos al 100%.

    
respondido por el mlk 31.01.2011 - 13:54
9

En primer lugar, creo que su problema es más sobre pruebas de unidad en general que TDD, ya que no veo nada realmente específico de TDD (prueba primero + ciclo de refactor rojo-verde) en lo que dice.

  

Es difícil y poco realista mantener   datos simulados de gran tamaño.

¿Qué quieres decir con datos simulados? Se supone, precisamente, que un simulacro contiene apenas datos, es decir, no hay campos que no sean los necesarios en la prueba, y no hay dependencias que no sean el sistema bajo prueba. La configuración de una expectativa simulada o un valor de retorno se puede hacer en una línea, por lo que no es nada terrible.

  

Es aún más difícil cuando la base de datos   La estructura sufre cambios.

Si quiere decir que la base de datos experimenta 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.

  

Incluso con MVVM y capacidad de prueba   GUI, se necesita mucho código para   reproducir el escenario GUI.

Tienes razón, la prueba unitaria de la GUI (Vista) no es fácil, y muchas personas lo están haciendo bien sin ella (además, la prueba de la GUI no es parte de TDD). En contraste, la prueba unitaria de su Controlador / Presentador / ViewModel / lo que sea la capa intermedia es altamente recomendada, en realidad es una de las principales razones por las que patrones como MVC o MVVM.

  

Tengo experiencia en que TDD funciona bien   si lo limitas a negocios simples   lógica. 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.

Si su lógica de negocios es compleja, es normal que las pruebas de su unidad sean difíciles de diseñar. Depende de usted hacerlos lo más atómicos posible, cada uno probando solo 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 infringirá las normas o los requisitos comerciales al realizar cambios en el código.

  

TDD requiere que los requisitos sean   100% correcto.

Absolutamente no. El software exitoso requiere que los requisitos sean 100% correctos;) las pruebas de unidad solo reflejan lo que actualmente es su visión de los requisitos; Si la visión es defectuosa, su código y su software también lo serán, pruebas de unidad o no ... Y ahí es donde brillan las pruebas de unidad: con los títulos de prueba suficientemente explícitos, sus decisiones de diseño e interpretación de los requisitos se vuelven transparentes, lo que hace que sea más fácil señalar lo que debe cambiarse la próxima vez que su cliente diga, "esta regla de negocios no es tan Me gustaría ".

    
respondido por el guillaume31 31.01.2011 - 18:54
6

Tengo que reírme 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. ¿Cuál es la alternativa? ¿Tienes monos de prueba golpeando en acres de teclados? ¿Que los usuarios sean los probadores? ¿Qué más? Por supuesto que es duro y complejo. ¿Crees que Intel no prueba sus chips hasta que se envían? ¿Cómo es eso de "cabeza en la arena"?

    
respondido por el SnoopDougieDoug 01.02.2011 - 05:30
4
> Does TDD really work for complex projects?

Desde mi experiencia: Sí para Unittests (prueba de módulos / funciones de forma aislada) porque estos En su mayoría no tiene los problemas que menciona: (Gui, Mvvm, Business-Modell). Nunca tuve mas que 3 simulacros / talones para completar una prueba de unidad (pero tal vez su dominio requiera más).

Sin embargo, no estoy seguro si TDD podría resolver los problemas que mencionaste sobre la integración o las pruebas de extremo a extremo con pruebas de estilo BDD.

Pero al menos algunos problemas pueden reducirse .

> However complex business logic is hard to test since the number 
> of combinations of tests (test space) is very large.

Esto es cierto si desea realizar una cobertura completa en el nivel de integración-prueba o prueba de extremo a extremo. Podría ser más fácil hacer la cobertura completa en un nivel de prueba de unidad.

Ejemplo: verificación de permisos de usuario complejos

Probando la función IsAllowedToEditCusterData() en un nivel de prueba de integración         requeriría preguntar diferente         objetos para información sobre usuario, dominio, cliente, entorno ...

burlándose de estas partes         Es bastante difícil. Esto es especialmente cierto si IsAllowedToEditCusterData() tiene que saber         estos diferentes objetos.

En un nivel Unittest tendría la función IsAllowedToEditCusterData() que toma, por ejemplo, 20 parámetros que contienen todo lo que la función necesita saber. Ya que IsAllowedToEditCusterData() no necesita saber qué campos un user , un domain , un customer , .... tiene esto es fácil de probar.

Cuando tuve que implementar IsAllowedToEditCusterData() tuve dos sobrecargas:

Una sobrecarga que no hace nada más que obtener esos 20 parámetros y luego llamar La sobrecarga con los 20 parámetros que hace la toma de decisiones.

(mi IsAllowedToEditCusterData() tenía solo 5 parámetros y necesitaba 32 combinaciones diferentes para probarlo por completo)

Ejemplo

// method used by businesslogic
// difficuilt to test because you have to construct
// many dependant objects for the test
public boolean IsAllowedToEditCusterData() {
    Employee employee = getCurrentEmployee();
    Department employeeDepartment = employee.getDepartment();
    Customer customer = getCustomer();
    Shop shop = customer.getShop();

    // many more objects where the permittions depend on

    return IsAllowedToEditCusterData(
            employee.getAge(),
            employeeDepartment.getName(),
            shop.getName(),
            ...
        );
}

// method used by junittests
// much more easy to test because only primitives
// and no internal state is needed
public static boolean IsAllowedToEditCusterData(
        int employeeAge,
        String employeeDepartmentName,
        String shopName,
        ... ) 
{
    boolean isAllowed; 
    // logic goes here

    return isAllowed;
}
    
respondido por el k3b 31.01.2011 - 18:54
3

Descubrí que la TDD (y las pruebas unitarias en general) son virtualmente 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 más que ejecutando mi código. Es demasiado complicado descifrarlo razonablemente a mano para cualquier cosa que no sean casos ridículamente triviales. Esto es especialmente cierto si el algoritmo incluye heurísticas, aproximaciones o no determinismo. Todavía intento probar la funcionalidad de nivel inferior de la que depende este código y el uso se valora en gran medida como controles de seguridad. Mi último método de prueba de recurso es escribir dos implementaciones diferentes, idealmente en dos idiomas diferentes utilizando dos conjuntos diferentes de bibliotecas y comparar los resultados.

    
respondido por el dsimcha 14.04.2011 - 03:53
2

¡La triste respuesta es que nada funciona realmente para grandes proyectos complejos!

TDD es tan bueno como cualquier otra cosa y mejor que la mayoría, pero TDD solo no garantiza el éxito en un proyecto grande. Sin embargo, aumentará sus posibilidades de éxito. Especialmente cuando se utiliza en combinación con otras disciplinas de gestión de proyectos (verificación de requisitos, casos de uso, matriz de capacidad de seguimiento de requisitos, tutoriales de código, etc.).

    
respondido por el James Anderson 25.05.2013 - 06:42
1

Recuerde que las pruebas unitarias son especificaciones forzadas . Esto es especialmente valioso en proyectos complejos. Si su antiguo código base no tiene ninguna prueba que lo respalde, nadie se atreverá a cambiar nada porque temerán romper algo.

"Wtf. ¿Por qué este código se ramifica incluso allí? No sé, tal vez alguien lo necesite, es mejor dejarlo allí para molestar a cualquiera ..." Con el tiempo, los proyectos complejos se convierten en un terreno de basura.

Con las pruebas, cualquiera puede decir con confianza: "He realizado cambios drásticos, pero todas las pruebas aún se están aprobando". 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 que las personas mantengan el COBOL es que las pruebas no fueron populares desde entonces: P

    
respondido por el kizzx2 31.01.2011 - 18:24
1

He visto un gran proyecto complejo que falla completamente cuando se usa TDD exclusivamente, es decir, sin al menos configurar en un depurador / IDE. Los datos y / o pruebas simulados resultaron insuficientes. Los datos reales de los clientes Beta eran confidenciales y no se podían copiar ni registrar. Por lo tanto, el equipo de desarrollo nunca pudo corregir los errores fatales que se manifestaron cuando apuntaban a datos reales, y todo el proyecto se desechó, todos dispararon, todo el proceso.

La forma de solucionar este problema hubiera sido activarlo en un depurador en el sitio del cliente, en vivo contra los datos reales, atravesar el código, con puntos de interrupción, ver variables, observar la memoria, etc. Sin embargo, este equipo, que pensaba que su código estaba en condiciones de adornar las mejores torres de marfil, durante un período de casi un año nunca había activado su aplicación. Eso me asombró.

Así, como todo, el equilibrio es la clave. TDD puede ser bueno, pero no confíe exclusivamente en él.

    
respondido por el SPA 31.01.2013 - 14:49
0

Creo que sí, vea Test Driven Development realmente funciona

  

En 2008, Nachiappan Nagappan, E. Michael Maximilien, Thirumalesh Bhat y Laurie Williams escribieron un artículo llamado " Realización de la mejora de la calidad a través del desarrollo basado en pruebas: resultados y experiencias de cuatro equipos industriales " (enlace PDF). El resumen:

     
    

El desarrollo dirigido por pruebas (TDD) es una práctica de desarrollo de software que se ha utilizado esporádicamente durante décadas. Con esta práctica, un ingeniero de software realiza un ciclo minuto a minuto entre escribir pruebas unitarias fallidas y escribir un código de implementación para aprobar esas pruebas. El desarrollo guiado por pruebas ha resurgido recientemente como una práctica habilitadora crítica de metodologías ágiles de desarrollo de software. Sin embargo, poca evidencia empírica apoya o refuta la utilidad de esta práctica en un contexto industrial. Se realizaron estudios de caso con tres equipos de desarrollo en Microsoft y uno en IBM que adoptaron TDD. Los resultados de los estudios de caso indican que la densidad de defectos de prelanzamiento de los cuatro productos disminuyó entre un 40% y un 90% en relación con proyectos similares que no utilizaron la práctica de TDD. Subjetivamente, los equipos experimentaron un aumento del 15 al 35% en el tiempo de desarrollo inicial después de adoptar TDD.

  
     

En 2012, las prácticas de desarrollo de Ruby on Rails asumen TDD. Personalmente confío en herramientas como rspec para escribir pruebas y simulacros, factory_girl para crear objetos, capybara para la automatización del navegador, simplecov para la cobertura de código y protección para automatizar estas pruebas.

     

Como resultado del uso de esta metodología y estas herramientas, tiendo a estar de acuerdo subjetivamente con Nagappan et al ...

    
respondido por el Hiltmon 26.01.2012 - 19:28
0

Si la combinación de presupuesto, requisitos y habilidades de equipo se encuentran en el cuadrante del espacio del proyecto "abandone la esperanza a todos los que ingresan aquí", entonces, por definición, es muy probable que el proyecto fracase.

Tal vez los requisitos son complejos y volátiles, la infraestructura inestable, el equipo junior y con una alta rotación, o el arquitecto es un idiota.

En un proyecto TDD, el síntoma de este fallo inminente es que las pruebas no se pueden escribir en el calendario; lo intentas, solo para descubrir 'eso va a demorar esto , y solo tenemos eso '.

Otros enfoques mostrarán diferentes síntomas cuando fallan; más comúnmente la entrega de un sistema que no funciona. La política y los contratos determinarán si eso es preferible.

    
respondido por el soru 06.03.2014 - 23:11
-1

TDD puede sonar como una molestia por adelantado, pero a largo plazo sería su mejor amigo, confíe en que TDD realmente hará que las aplicaciones sean mantenibles y seguras a largo plazo.

    
respondido por el Rachel 01.02.2011 - 19:42

Lea otras preguntas en las etiquetas