Diferencia de tiempo entre el desarrollo con pruebas unitarias y ninguna prueba

130

Soy un desarrollador en solitario con un entorno de trabajo bastante limitado en el tiempo en el que el tiempo de desarrollo varía de 1 a 4 semanas por proyecto, según los requisitos, la urgencia o ambos. En un momento dado, manejo alrededor de 3-4 proyectos, algunos tienen líneas de tiempo que se superponen entre sí.

Como era de esperar, la calidad del código sufre. Tampoco tengo pruebas formales; Por lo general, se reduce a caminar a través del sistema hasta que se rompe un poco. Como resultado, una cantidad considerable de errores se escapan a la producción, que tengo que corregir y, a su vez, retrasa mis otros proyectos.

Aquí es donde entra en juego la prueba de la unidad. Cuando se hace correctamente, debe mantener los errores, y mucho menos los que escapan a la producción, al mínimo. Por otro lado, las pruebas de escritura pueden llevar una cantidad de tiempo considerable, lo que no suena bien con proyectos con limitaciones de tiempo como el mío.

La pregunta es, ¿cuánto de una diferencia de tiempo escribiría un código probado por unidad sobre un código no probado, y cómo se amplía esa diferencia de tiempo cuando se amplía el alcance del proyecto?

    
pregunta Revenant 15.06.2016 - 04:37
fuente

12 respuestas

143

Cuanto más tarde realice la prueba, más cuesta escribir las pruebas.

Cuanto más tiempo viva un error, más costoso es solucionarlo.

La ley de los rendimientos decrecientes garantiza que puedas ponerte a prueba y olvidarte de que no hay errores.

Buda enseñó la sabiduría del camino medio. Las pruebas son buenas. Hay tal cosa como algo demasiado bueno. La clave es saber cuándo está fuera de balance.

Cada línea de código que escriba sin pruebas tendrá costos significativamente mayores para agregar pruebas más tarde que si las hubiera escrito antes de escribir el código.

Cada línea de código sin pruebas será mucho más difícil de depurar o reescribir.

Cada prueba que escribas tomará tiempo.

Cada error llevará tiempo para solucionarlo.

Los fieles le dirán que no escriba una sola línea de código sin antes escribir una prueba fallida. La prueba asegura que está obteniendo el comportamiento que espera. Le permite cambiar el código rápidamente sin preocuparse por afectar el resto del sistema, ya que la prueba demuestra que el comportamiento es el mismo.

Debe comparar todo esto con el hecho de que las pruebas no agregan funciones. Código de producción añade características. Y las características son las que pagan las cuentas.

Hablando de manera pragmática, agrego todas las pruebas que puedo realizar. Ignoro los comentarios a favor de ver las pruebas. Ni siquiera confío en el código para hacer lo que creo que hace. Confío en las pruebas. Pero he sido conocido por tirar ocasionalmente el saludo y tener suerte.

Sin embargo, muchos codificadores exitosos no hacen TDD. Eso no significa que no prueben. Simplemente no insisten obsesivamente en que cada línea de código tenga una prueba automatizada contra ella. Incluso el tío Bob admite que no prueba su IU. También insiste en que muevas toda la lógica fuera de la interfaz de usuario.

Como metáfora del fútbol (que es el fútbol americano), TDD es un buen juego terrestre. Las pruebas manuales en las que escribes un montón de código y esperas que funcione es un juego de pases. Puedes ser bueno en cualquiera de los dos. Tu carrera no va a llegar a los playoffs a menos que puedas hacer ambas cosas. No hará la Superbowl hasta que aprendas cuándo elegir cada una. Pero si necesita un empujón en una dirección particular: las llamadas de los funcionarios van en contra de mí con más frecuencia cuando estoy pasando.

Si quieres probar TDD, te recomiendo que practiques antes de hacerlo en el trabajo. La TDD se realiza a medias, a medias y a medias es una razón importante por la que algunos no la respetan. Es como verter un vaso de agua en otro. Si no te comprometes y lo haces rápida y completamente, terminas regando agua por toda la mesa.

    
respondido por el candied_orange 15.06.2016 - 05:17
fuente
111

Estoy de acuerdo con el resto de las respuestas, pero para responder a la pregunta cuál es la diferencia horaria directamente.

Roy Osherove en su libro The Art of Unit Testing, Segunda Edición página 200 hizo un estudio de caso sobre la implementación de proyectos de tamaño similar con equipos similares (por lo que respecta a habilidades) para dos clientes diferentes donde un equipo realizó las pruebas mientras que el otro no lo hizo.

Sus resultados fueron así:

Entonces, al final de un proyecto, obtienes menos tiempo y menos errores. Por supuesto, esto depende de qué tan grande es un proyecto.

    
respondido por el Aki K 15.06.2016 - 11:11
fuente
30

Sólo hay un un estudio que estudié esto en un "entorno real": Realización de la mejora de la calidad a través del desarrollo basado en pruebas: resultados y experiencias de cuatro equipos industriales . Es costoso hacerlo de una manera sensata, ya que básicamente significa que necesitas desarrollar el mismo software dos veces (o idealmente incluso más a menudo) con equipos similares, y luego tirar todos menos uno.

Los resultados del estudio fueron un aumento en el tiempo de desarrollo entre el 15% y el 35% (que no se acerca a la cifra 2x que a menudo se cita por los críticos de TDD) y una disminución en la densidad de defectos previos al lanzamiento del 40% al 90%. % (!). Tenga en cuenta que todos los equipos no tenían experiencia previa con TDD, por lo que se podría suponer que el aumento en el tiempo puede atribuirse, al menos parcialmente, al aprendizaje y, por lo tanto, disminuiría aún más con el tiempo, pero el estudio no lo evaluó.

Tenga en cuenta que este estudio trata sobre TDD, y su pregunta es sobre pruebas de unidad, que son cosas muy diferentes, pero es lo más cercano que pude encontrar.

    
respondido por el Jörg W Mittag 15.06.2016 - 10:44
fuente
24

Hecho bien, el desarrollo con pruebas unitarias puede ser más rápido incluso sin tener en cuenta los beneficios de los errores adicionales que se detectan.

El hecho es que no soy un programador lo suficientemente bueno como para que mi código funcione tan pronto como se compile. Cuando escribo / modifico el código, tengo que ejecutar el código para asegurarme de que haga lo que pensé que hace. En un proyecto, esto tendió a parecer:

  1. Modificar código
  2. compilar la aplicación
  3. Ejecutar aplicación
  4. Iniciar sesión en la aplicación
  5. Abre una ventana
  6. Seleccione un elemento de esa ventana para abrir otra ventana
  7. Establezca algunos controles en esa ventana y haga clic en un botón

Y, por supuesto, después de todo eso, por lo general tomaba algunos viajes de ida y vuelta para hacerlo bien.

Ahora, ¿qué pasa si estoy usando pruebas unitarias? Entonces el proceso se parece más a:

  1. escribe una prueba
  2. Ejecutar pruebas, asegúrese de que falle de la forma esperada
  3. Escribir código
  4. Ejecutar pruebas nuevamente, ver que pasa

Esto es más fácil y más rápido que probar la aplicación manualmente. Todavía tengo que ejecutar la aplicación manualmente (así que no parezco tonto cuando entrego un trabajo que realmente no funciona en absoluto), pero en su mayor parte ya resolví los problemas, y simplemente Verificando en ese punto. En realidad, normalmente hago este bucle aún más fuerte usando un programa que automáticamente ejecuta mis pruebas cuando guardo.

Sin embargo, esto depende de trabajar en una base de código fácil de probar. Muchos proyectos, incluso aquellos con muchas pruebas, hacen que las pruebas de escritura sean difíciles. Pero si trabaja en ello, puede tener una base de código que sea más fácil de probar a través de pruebas automatizadas que con las pruebas manuales. Como beneficio adicional, puede mantener las pruebas automatizadas alrededor y continuar ejecutándolas para evitar regresiones.

    
respondido por el Winston Ewert 15.06.2016 - 06:17
fuente
19

A pesar de que ya hay muchas respuestas, son un tanto repetitivas y me gustaría tomar un rumbo diferente. Las pruebas unitarias son valiosas, si y solo si , aumentan el valor comercial . Las pruebas para determinar si hay pruebas (pruebas triviales o tautológicas), o para alcanzar una métrica arbitraria (como la cobertura del código), es una programación de culto a la carga.

Las pruebas son costosas, no solo en el tiempo que lleva escribirlas, sino también en el mantenimiento. Deben mantenerse sincronizados con el código que prueban o no valen nada. Sin mencionar el costo de tiempo de ejecutarlos en cada cambio. Eso no es un factor decisivo (o una excusa para no hacer las realmente necesarias), pero debe tenerse en cuenta para el análisis de costo-beneficio.

Entonces, la pregunta que debe hacerse al decidir si (o de qué tipo) probar una función / método, pregúntese '¿qué valor para el usuario final estoy creando / protegiendo con esta prueba?'. Si no puede responder a esa pregunta, fuera de su cabeza , entonces esa prueba probablemente no valga la pena el costo de escribir / mantener. (o no entiende el dominio del problema, que es un problema waaaay más grande que la falta de pruebas).

enlace

    
respondido por el Jared Smith 15.06.2016 - 17:24
fuente
9

Depende de la persona, así como de la complejidad y la forma del código con el que está trabajando.

Para mí, en la mayoría de los proyectos, escribir pruebas unitarias significa que hago el trabajo un 25% más rápido. Sí, incluso con el tiempo para escribir las pruebas.

Porque el hecho del asunto es que el software no está terminado cuando escribes el código. Se realiza cuando se lo envía al cliente y están contentos con él. Las pruebas unitarias son, con mucho, la forma más eficiente que conozco para detectar la mayoría de los errores, aislar la mayoría de los errores para la depuración y ganar confianza en que el código es bueno. Tienes que hacer esas cosas de todos modos , así que hazlo bien.

    
respondido por el Telastyn 15.06.2016 - 05:26
fuente
4
  

La pregunta es, ¿cuánto de una diferencia de tiempo escribiría un código probado por unidad sobre un código no probado, y cómo se amplía esa diferencia de tiempo cuando se amplía el alcance del proyecto?

El problema empeora a medida que aumenta la antigüedad del proyecto: porque cada vez que agrega una nueva funcionalidad y / o cuando refactoriza la implementación existente, debe volver a probar lo que se probó anteriormente para asegurarse de que aún funciona. Por lo tanto, para un proyecto de larga duración (de varios años), es posible que no solo tenga que probar la funcionalidad, sino que vuelva a realizar la prueba 100 veces y más. Por este motivo, podría beneficiarse de las pruebas automatizadas . Sin embargo, IMO es lo suficientemente bueno (o incluso mejor) si se trata de pruebas automatizadas del sistema, en lugar de pruebas unitarias automatizadas.

Un segundo problema es que los errores pueden ser más difíciles de encontrar y solucionar si no se detectan antes. Por ejemplo, si hay un error en el sistema y sé que funcionaba perfectamente antes de que hiciera su último cambio, entonces concentraré mi atención en su último cambio para ver cómo podría haber introducido el error. Pero si no sé que el sistema funcionaba antes de que hicieras tu último cambio (porque el sistema no se probó correctamente antes de tu último cambio), el error podría estar en cualquier lugar.

Lo anterior se aplica especialmente al código profundo, y menos al código superficial, por ejemplo. agregar nuevas páginas web donde es poco probable que las nuevas páginas afecten a las páginas existentes.

  

Como resultado, una cantidad considerable de errores se escapan a la producción, que tengo que corregir y, a su vez, retrasa mis otros proyectos.

En mi experiencia, eso sería inaceptable, por lo que estás haciendo la pregunta incorrecta. En lugar de preguntar si las pruebas harían que el desarrollo fuera más rápido, debería preguntar qué haría que el desarrollo fuera más libre de errores.

Una mejor pregunta podría ser:

  • ¿La prueba de unidad es el tipo correcto de prueba, que debe evitar la "cantidad considerable de errores" que ha estado produciendo?
  • ¿Hay otros mecanismos de control / mejora de la calidad (aparte de las pruebas unitarias) para recomendar también o en su lugar?

El aprendizaje es un proceso de dos etapas: aprende a hacerlo lo suficientemente bien, luego aprende a hacerlo más rápidamente.

    
respondido por el ChrisW 16.06.2016 - 15:40
fuente
3

Algunos aspectos a considerar, no mencionados en las otras respuestas.

  • Beneficio adicional / Costo adicional depende de la experiencia con la escritura de pruebas de unidad
    • con mi primer proyecto de prueba unitaria, los costos adicionales se triplicaron porque tuve que aprender mucho y cometí muchos errores.
    • después de 10 años de experiencia con tdd necesito un 25% más de tiempo de codificación para escribir las pruebas con anticipación.
  • con más tdd-moduls todavía es necesario realizar una prueba gui-manual y una prueba de integración
  • tdd solo funciona cuando se hace desde el principio.
    • aplicar tdd a un proyecto existente y en crecimiento es costoso / difícil. Pero puedes implementar pruebas de regresión en su lugar.
  • las pruebas automatizadas (pruebas de unidad y otro tipo de pruebas) requieren que el mantenimiento sea constante para que sigan funcionando.
    • haber creado la prueba a través de copiar y pegar puede hacer que el código de prueba-mantenimiento sea costoso.
    • con la creciente experiencia, testcode se vuelve más modular y más fácil de mantener.
  • con una experiencia cada vez mayor, tendrá la sensación de que vale la pena crear pruebas automatizadas y cuándo no.
    • ejemplo, no hay un gran beneficio para los probadores / envoltorios / envoltorios sencillos unittest
    • no escribo pruebas automatizadas a través de la interfaz gráfica de usuario
    • Cuido que el businesslayer pueda ser probado

Resumen

Al comenzar con tdd, es difícil alcanzar el estado de "más beneficio que costo" siempre que se encuentre en el "entorno de trabajo limitado por el tiempo". especialmente si hay "gerentes inteligentes" que le dicen que "deshacerse de las cosas de prueba caras e inútiles"

Nota: con "unidad de prueba" me refiero a "prueba de módulos en aislamiento".

Nota: con "prueba de regresión" quiero decir

  • escribe algún código que produzca un texto de salida.
  • escriba algún código de "prueba de regresión" que verifique que el resultado de la generación sigue siendo el mismo.
  • la prueba de regresión le permite saber cuándo cambia el resultado (lo que podría estar bien o un indicador de un nuevo error)
  • la idea de "prueba de regresión" es similar a approvaltests
    • ... tomando una instantánea de los resultados y confirmando que no han cambiado.
respondido por el k3b 15.06.2016 - 13:55
fuente
3

Los programadores, como las personas que se ocupan de la mayoría de las tareas, subestiman el tiempo que lleva completarla. Teniendo esto en cuenta, pasar 10 minutos para escribir una prueba se puede ver como el tiempo que uno podría haber pasado escribiendo toneladas de código cuando en realidad, habría pasado ese tiempo con el mismo nombre de función y los mismos parámetros que durante la prueba. . Este es un escenario TDD.

No escribir exámenes, es muy parecido a tener una tarjeta de crédito; Tendemos a gastar más o escribir más código. Más código tiene más errores.

En lugar de decidir tener una cobertura total de código o ninguna, sugiero que se centre en la parte crítica y complicada de su aplicación y realice pruebas allí. En una aplicación bancaria, ese podría ser el cálculo de intereses. Una herramienta de diagnóstico del motor puede tener complejos protocolos de calibración. Si ha estado trabajando en un proyecto, probablemente sepa qué es y dónde están los errores.

Comience despacio. Construye un poco de fluidez antes de juzgar. Siempre puedes parar.

    
respondido por el JeffO 15.06.2016 - 14:09
fuente
3

Ha habido una larga historia de programadores que promueven TDD y otras metodologías de prueba, no recordaré sus argumentos ni estaré de acuerdo con ellos, pero aquí hay cosas adicionales a considerar que deberían matizar un poco:

  • Las pruebas no son tan convenientes y eficientes según el contexto. Desarrollo software web, dime si tienes un programa para probar toda la interfaz de usuario ... ahora mismo estoy programando macros de excel, ¿debería realmente desarrollar un módulo de prueba en VBA?
  • Escribir y mantener el software de prueba es un trabajo real que cuenta en el corto plazo (vale la pena en un plazo más largo). Escribir pruebas relevantes también es una experiencia para obtener
  • Trabajar en equipo y trabajar solo, no tiene los mismos requisitos de prueba porque en equipo necesita validar, comprender y comunicar el código que no escribió.

Yo diría que las pruebas son buenas, pero asegúrate de hacer las primeras pruebas y de dónde está la ganancia.

    
respondido por el Arthur Havlicek 16.06.2016 - 13:51
fuente
1

Un beneficio a menudo pasado por alto de TDD es que las pruebas actúan como una garantía para asegurarse de que no está introduciendo nuevos errores cuando realiza un cambio.

El enfoque de TDD indudablemente requiere más tiempo inicialmente, pero el punto clave es que escribirá menos código , lo que significa que hay menos cosas que salen mal. Todas esas campanas y silbidos que a menudo incluyes como una cuestión de curso no se incluirán en la base del código.

En la película Swordfish hay una escena en la que, si la memoria no funciona, un pirata informático tiene que trabajar con una pistola en la cabeza y ser erm ... de lo contrario, distraído. El punto es que es mucho más fácil trabajar cuando su espacio de cabeza está en el código y usted tiene tiempo de su lado en lugar de meses después con un cliente que le grita y que le aprietan otras prioridades.

Los desarrolladores entienden que corregir errores más tarde es más costoso, pero dale la vuelta a esto. Si pudiera recibir un pago de $ 500 por día para codificar cómo codifica ahora o $ 1000 si escribió de manera TDD, le quitaría la mano a la persona que le hizo la segunda oferta. Cuanto antes deje de ver las pruebas como una tarea y lo vea como un ahorro de dinero, mejor estará.

    
respondido por el Robbie Dee 15.06.2016 - 12:26
fuente
0

Puedo relacionarme con su experiencia: nuestra base de código casi no tenía pruebas y casi no se podía probar. Le tomó literalmente años desarrollar algo y arreglar errores de producción tomó un tiempo precioso de nuevas características.

Para una reescritura parcial, me comprometí a escribir pruebas para todas las funciones básicas. Al principio, tomó mucho más tiempo y mi productividad sufrió notablemente, pero luego mi productividad fue mejor que nunca.

Parte de esa mejora fue que tuve menos errores de producción, lo que a su vez condujo a menos interrupciones - > Tuve un mejor enfoque en un momento dado.

Además, la capacidad para probar Y depurar el código de forma aislada realmente paga: un conjunto de pruebas es muy superior a un sistema que no se puede depurar excepto con la configuración manual, e. sol. inicie su aplicación y navegue a la pantalla y haga algo ... quizás unas docenas de veces

Pero note que hay una caída en la productividad al principio, así que empiece a aprender sobre pruebas en algún proyecto donde la presión del tiempo no es una locura. Además, intente iniciarlo en un proyecto greenfield, la prueba de unidades del código heredado es muy difícil, y ayuda cuando sabe cómo se ve un buen conjunto de pruebas.

    
respondido por el Christian Sauer 18.06.2016 - 17:41
fuente

Lea otras preguntas en las etiquetas