¿Cuál es su opinión honesta sobre las pruebas unitarias?

En pocas palabras, con las pruebas unitarias la vida es mucho más fácil .

No hace mucho tiempo tuve la oportunidad de leer un artículo Los beneficios medibles de las pruebas unitarias . Es muy útil si desea medir si puede beneficiarse de las pruebas unitarias o no.

Ok, ¡comencemos con la definición! En la prueba de unidad de acceso directo es una prueba rápida de una unidad pequeña . Lo que es una unidad depende del desarrollador. Puede ser cualquier fragmento de código pequeño y comprobable, como un método o una clase.

Las pruebas unitarias son pruebas de bajo nivel . Forzan una pequeña aplicación para realizar alguna acción y verifican el resultado final. Esta acción es muy simple y los resultados son independientes de otras aplicaciones. La falla en una prueba unitaria muestra sin lugar a dudas qué parte del código no funciona.

Hay muchas ventajas de las pruebas unitarias a menudo citadas en la web, tales como:

  • las pruebas unitarias conducen a menos errores en el software,
  • los desarrolladores se sienten más seguros al implementar código que está cubierto por pruebas unitarias,
  • Los programadores que siguen el proceso de desarrollo basado en pruebas (TDD) afirman que las pruebas unitarias les ayudan a alcanzar sus objetivos más rápido, resolviendo problemas con menos código y una mejor arquitectura de código.

¡Debemos recordar que los proyectos de TI están cambiando constantemente! Desde la perspectiva de nuestro cliente, puede ser solo un pequeño cambio, pero para los desarrolladores puede tener enormes consecuencias. Un buen ingeniero siempre probará su trabajo. Pero un ingeniero superior verificará si no rompió nada más. Si tiene pruebas unitarias, las características anteriores se pueden probar casi al instante.

Además, la falta de pruebas unitarias dificulta la predicción del tiempo de prueba final . El desarrollador puede estimar cuánto tiempo pasará construyendo una nueva característica, pero nadie sabe cuántas iteraciones serán necesarias para las pruebas durante el desarrollo, o cuántos conflictos con las características anteriores se crearán. Un ingeniero puede decir fácilmente cuánto tiempo necesitan para crear nuevas pruebas unitarias.

Si desea saber si su proyecto requiere pruebas unitarias, tengo una prueba corta para usted. Trate de pensar en su proyecto y verifique si alguno de estos factores encaja:

  • tu proyecto crecerá a tiempo
  • tus características son complejas
  • los errores en su proyecto pueden costarle mucho dinero
  • El tiempo de comercialización predecible es crucial para su proyecto

Si su proyecto coincide con cualquiera de los anteriores, se beneficiará de las pruebas unitarias . Cuantos más factores encajen, más pruebas unitarias le ayudarán.

Cualquier comentario es más que bienvenido, así que siéntase libre de comentar!

Si te gusta mi respuesta, me alegraré si la votas.

He estado haciendo TDD durante 2 años, y la siguiente es mi experiencia:

– ¿Necesitamos TDD?

  • Ciertamente sí para la mayoría de los proyectos. Porque las pruebas sirven como cliente y exigen una cierta interfaz antes de escribir el código, ejerce presión sobre el diseño de su API, por lo tanto, TDD lo ayuda a organizar su arquitectura . Esto demuestra ser ágil y efectivo en la mayoría de los casos. En segundo lugar, si desea refactorizar, necesita cobertura de pruebas. De lo contrario, el riesgo de refactorización es demasiado alto, y el equipo simplemente no puede permitirse el lujo de hacerlo. Esto es malo ya que necesita una refactorización para eliminar la duplicación, evolucionar la arquitectura, etc.
  • No, si tiene proyectos … con un contexto pequeño que puede caber en su cabeza fácilmente. O proyectos que por alguna razón pueden permitirse actividades de alto riesgo mencionadas anteriormente sin pruebas. O el “proyecto de unicornio” con desarrolladores de estrellas que siempre tienen el diseño y la implementación correctos, por lo que generalmente es de bajo riesgo, incluso sin pruebas o refactorización.

– ¿Cómo hacerlo correctamente?

  • Probar la interfaz, no la implementación. El error más común que observo en la práctica de TDD es probar la implementación. Esto a menudo se produce escribiendo primero el código. Luego, la prueba simplemente cumple la función de asegurarse de que el código se mantenga como está. Esto tiene dos peligros: primero, no está diseñando primero su abstracción / API; vas directamente a la implementación. Esto es simplemente malo. En segundo lugar, para sus pruebas unitarias, su código no es como un cuadro negro. En otras palabras, cuando refactoriza, casi siempre tiene que cambiar sus pruebas. Esto conlleva esfuerzos adicionales y no tiene sentido. Las pruebas son como las especificaciones. Deben ser tan independientes de la implementación como sea posible.
  • Priorice la prueba de módulos estables (servicios, entidades, etc.), luego los inestables (controladores, UI, etc.). Probablemente hayas oído hablar de la pirámide de prueba, y este es el mismo principio. Los módulos estables tienden a tener API estables y limpias, por lo que el costo de escribir pruebas es bajo. Y dado que estos módulos también tienen muchos módulos superiores dependientes, el beneficio de asegurarse de que funcionen es alto. Para módulos inestables, especialmente la interfaz de usuario, el costo / beneficio es el inverso. Por lo tanto, es aconsejable poner a prueba los módulos estables en la parte superior de su lista de prioridades.

– TDD, la filosofía

  • Después de todo, TDD es un compromiso, no una verdad. Como profesionales, necesitamos medir qué tan bueno es nuestro código (es decir, ¿funciona?). No es suficiente, como profesional, simplemente afirmar que su código funciona. Tienes que demostrarlo. Hasta donde puedo imaginar, solo hay dos formas de “probarlo”. Usted tiene un diseño extremadamente riguroso y seguridad de tipo en su sistema, por lo que cuando uno lee su código, es difícil creer cómo no funciona. O tienes un montón de pruebas unitarias. TDD es el último enfoque, que es el compromiso con el anterior: después de todo, no prueba nada enumerando casos, lo demuestra por matemática.
  • Se aplica Shuhari (守 破 離) . Shuhari es un famoso concepto originario del arte marcial japonés. Básicamente dice que en el camino hacia la maestría, primero se debe obedecer ( shu ), luego desviarse ( ha ), y finalmente puede salir ( ri ) (como maestro). Puede aplicar lo mismo a la práctica de TDD. TDD no es la respuesta final (como se dijo anteriormente), pero le ayuda a llegar allí si primero lo obedece y practica el arte de la API. Después de cierto progreso, usted forma su propia comprensión sistemática de cómo funciona el código / computadora / algoritmo / diseño. Es decir, el momento de divagación. Cuando su sistema finalmente esté lo suficientemente pulido, puede dejar TDD y declararse un maestro del código.

No hay duda de que las pruebas unitarias son excelentes, pero hay una pregunta realmente importante que usted o su equipo deben responder.

¿Qué tan detallados debemos ser con nuestras pruebas?

¡Puede tener tres veces el código fácilmente en pruebas unitarias que en su proyecto principal! Para la mayoría de los proyectos esto no es práctico.

Por otro lado, si su proyecto no tiene pruebas unitarias, cada una que escriba es una mejora.

Cuando descubrí las pruebas unitarias, me encantó porque formalizó las cosas que estaba haciendo de todos modos. Todo desarrollador decente tiene que probar el código que escriben de una forma u otra. Las pruebas unitarias no solo lo hacen más fácil, sino que es un registro permanente al que puede volver y ejecutar nuevamente como una protección segura contra cambios importantes.

Lo único negativo real para las pruebas unitarias es cuando se excede y se cruza el punto de rendimientos decrecientes. Cuando pasa demasiado tiempo (= dinero) escribiendo pruebas que realmente no están garantizadas para su proyecto, las pruebas unitarias se vuelven gravosas en lugar de beneficiosas.

En lugar de abordar las pruebas unitarias con el objetivo de ejercer absolutamente todos los escenarios posibles, acéptelo con la idea de que cada prueba unitaria que escriba haga que su código sea mucho mejor y mucho más robusto. Encuentra el equilibrio para tu situación.

Debe probar su código de una forma u otra, también podría hacer lo que pueda en forma de pruebas unitarias.

Hablemos de cocinar primero. Supongamos que quieres hacer una tortilla.

(Fuente de la imagen: IHOP)

Un desayuno, nada lujoso. Sin embargo, necesita algunos ingredientes, como huevos, leche, tocino, queso, tomates, sal …

Y aquí hay algunas cosas que [probablemente] inspeccionaría , evaluaría , verificaría , etc.

  • ¿Cuántos huevos? ¿Son frescos?
  • Que tipo de leche ¿Cuánto cuesta? ¿Está malcriado?
  • ¿Está limpio su tazón (para revolver)?
  • ¿Su sartén está suficientemente caliente? Cuando pones tocino?
  • Y así..

Cada vez que verificas, inspeccionas, evalúas, saboreas … estás probando . Estás haciendo observaciones y juicios mientras estás en el proceso de creación del producto. Estás probando tu trabajo y las unidades que comprenderán el producto. Estás haciendo una prueba unitaria en este sentido.

Pero tenga en cuenta que no está probando el producto .

En teoría, uno puede tratar de cocinar sin prestar atención al proceso y a los componentes, y probar el producto final, la tortilla, después, una vez finalizado.

Pero hay implicaciones:

  • Ciertamente lleva más tiempo hasta que los resultados de la evaluación;
  • Será demasiado tarde para tomar medidas correctivas;
  • Tampoco podrás responder al cambio;
  • Ciertos problemas (como la leche en mal estado o el tazón sucio) no se manifestarán inmediatamente después de la degustación, pero pueden tener graves consecuencias para la salud.

Todo eso se traduce bien en el desarrollo de software. Si desea ser eficaz y eficiente, entonces es necesario realizar pruebas unitarias.


Por supuesto, incluso las excelentes pruebas unitarias no pueden mitigar la ausencia de pruebas funcionales o deficientes [caja negra] . El último es un enfoque listo para usar: ¿Qué es la prueba de caja negra?

Las pruebas de recuadro negro pueden ayudar a evitar fallas al plantear preguntas como …

¿Estamos cocinando el orden correcto? Tal vez el cliente quería esto, pero ocurrió una falta de comunicación.

(Fuente de la imagen: IHOP)


¡Gracias por leer!

  • Si te gustó esta respuesta, vota y sígueme
  • Si lo encuentra útil, por favor comparta con otros
  • ¿No estás de acuerdo o no te gustó? ¡Dispárame un comentario! Estoy seguro de que hay un margen de mejora.

No me gustan las pruebas unitarias. Me gusta Test Driven Development. Test Driven Development no se trata solo de agregar pruebas unitarias. Hay muchas respuestas geniales a continuación. Recomiendo leer toda la pregunta, incluidos los negativos. Solo al comprender los aspectos positivos y negativos obtenemos una imagen válida completa.

‘Pruebas unitarias’ no es un objetivo. Una idea común es asignar a un programador junior una tarea para crear pruebas unitarias. Francamente, esto está marcando una casilla de desarrollo en lugar de pruebas unitarias genuinas. El programador está demostrando que el código hace lo que hace en lugar de hacer lo que DEBE hacer. Esta distinción es muy importante.

He visto muchos planes de proyectos como este:

  • describe el código (divide la epopeya en historia, la historia en tareas).
  • componente funcional de código
  • Componente de control de calidad
  • Escribir pruebas unitarias.

Esto NO es desarrollo impulsado por pruebas. Las pruebas se escriben simultáneamente, por lo que forma parte del componente funcional de escritura. Dado que el Componente se ha enviado a QA, no se pueden hacer cambios para que el código principal sea comprobable porque significará que tenemos que rehacer QA para que no se realicen los cambios necesarios. Se agota el tiempo o el presupuesto, por lo que el elemento de prueba unitaria se elimina del proyecto y no se realiza. Finalmente, el beneficio de costo no se logra (más adelante).

Aplicar pruebas a una API no es Prueba unitaria. Debe eliminar las variables de sus pruebas unitarias para que sean robustas. Por ejemplo, tuve pruebas unitarias que fallaron antes de las 10 de la mañana del primer mes porque la prueba (no el código) no pudo manejar las zonas horarias correctamente. El uso de una fecha y hora conocidas eliminó este problema sin hacer que la prueba sea compleja, es parte de hacer que las pruebas sean predecibles.

Por lo tanto, el código y las pruebas unitarias deben escribirse al mismo tiempo. En teoría, puede diseñar la clase y escribir todas las pruebas. Mi preocupación aquí es que este es un proceso de mini cascada y, como se señaló en otra parte, impide el crecimiento orgánico del código a medida que lo desarrolla. Escribir simultáneamente conduce a un costo adicional de prueba de costo cero ahorra depuración, comprobada en otros estudios. Su código está casi libre de errores, ya que posiblemente pueda hacerlo antes de unirlo, lo que lleva a menos errores finales que tardan mucho en descubrir, incluso si el codificador los descubre. (El código de nota nunca está libre de errores, solo los errores se reducen significativamente)

En un sistema que ya está en funcionamiento, las pruebas unitarias cuestan dinero para crear con poco valor apreciable. Especialmente en uno que ya ha estado en vivo por algún tiempo sin incidentes. Está probando un código probado, por lo tanto, es poco probable que obtenga una falla válida. Incluso si encuentra una falla válida, puede que no valga la pena arriesgar la estabilidad del código al corregir el código. Un error corregido, dos introducidos es a veces un efecto secundario desafortunado.

En el código heredado cuando desea cambiar el código para corregir un error o agregar una función, este es el momento en que agrega las pruebas unitarias. Eres experto en esa área porque la estás cambiando. Se toma tiempo para comprender los matices del código, no la implementación. Implementa pruebas en las porciones de trabajo para asegurarse de no afectarlas. Implementa una prueba resaltando el código por error y luego implementa el código para eliminar el error. Usted prueba la prueba en efecto. De esta manera, deja un rastro de que el error no se reintroducirá cuando otros cambien el código.

La razón más importante. Mi código es mejor como resultado. Rompo mi código más lógicamente. Pienso en las consecuencias para el código, más para garantizar que el código maneja mejor los casos extremos. Está probado antes de atornillar. Cuando tengo una falla, puedo agregar una prueba y cambiar mi código para corregir la falla y no introducir más problemas como resultado.

Trabajé en un sistema durante 10 años. Hice mantenimiento anual en él. Miraba el código y decía “¿por qué lo escribí así?” Corregiría el código a una implementación más limpia y ejecutaría mis pruebas. Ellos fallaron. Entonces entendí (nuevamente) lo que he escrito y por qué, y revertí mis cambios, lo que me ahorró vergüenza.

Depende de la naturaleza del software.

Si está haciendo algo en el que un error matará a alguien o costará una tonelada de dinero, entonces la confiabilidad es primordial, y si la naturaleza del trabajo que se está haciendo no está vinculada a eventos aleatorios o en tiempo real, entonces creo que es muy poderoso técnica.

Pero si está haciendo algo donde un error es un inconveniente relativamente menor y / o está reaccionando a cosas en tiempo real o eventos aleatorios, entonces las pruebas unitarias ya no brindan la confianza que esperaría y el costo (generalmente elevado) de escribir y depurar todas esas pruebas puede duplicar fácilmente sus costos de software.

Por lo tanto, las pruebas unitarias casi nunca se usan para escribir videojuegos. Es demasiado costoso de hacer, y realmente no verifica las cosas que le interesan. Es mejor contratar a un equipo de personas de control de calidad y hacer que prueben el juego a medida que se desarrolla, haciendo pruebas de regresión cuando se lanzará una nueva versión pronto.

Pero si trabajara en la industria bancaria, o tal vez si estuviera construyendo algo que operara los frenos de un automóvil, sería mucho más probable que considerara las pruebas unitarias como un buen enfoque.

Por ejemplo, escribo software de gráficos para juegos y simulación. Tengo un software que representa el océano: olas, espuma, surf, etc.

¿Cómo escribiría una prueba unitaria para eso? Quizás tendría que volcar el contenido del búfer de pantalla para asegurarme de que funcionaba. Pero no estoy obligado a producir el conjunto exacto de píxeles cada vez; podría encontrar fácilmente algún tipo de mejora que haga que las cosas funcionen más rápido o que el océano se vea más realista, pero no pasaría la prueba de la unidad porque la imagen en La pantalla ha cambiado.

No hay una prueba razonable que pueda hacer que verifique si la salida de mi programa es “realista” o no.

Ahora, eso no quiere decir que no pueda probar unitariamente algunas partes más pequeñas de mi software, pero eso nunca será realmente una prueba útil.

Si, por otro lado, estaba escribiendo un módulo para calcular el interés de un préstamo para un banco, entonces, claro, tenemos una descripción técnica formal de lo que debería hacer para qué insumos, y podemos probar eso.

Otro problema con las pruebas unitarias es que una gran clase de error de software está malinterpretando la especificación. Pero si la especificación se malinterpreta tanto cuando se escribe el código Y cuando se escribe la prueba unitaria, no verá ningún beneficio.

Me encantan las pruebas unitarias. Incluso en mis proyectos de pasatiempo, escribo muchas pruebas unitarias.

Este es el por qué:

  1. Si vale la pena escribir, vale la pena hacerlo bien. Las pruebas unitarias son la mejor herramienta para garantizar la corrección.
  2. Las pruebas unitarias brindan muchas oportunidades para jugar con el código, cambiar cosas aquí y allá, experimentar con diferentes implementaciones, etc.
  3. Pensar en qué pruebas unitarias deben escribirse me ayuda a descubrir más sobre la naturaleza exacta del problema que estoy tratando de resolver.
  4. Si estoy aprendiendo un nuevo lenguaje o marco, las pruebas unitarias me dan la oportunidad de practicar más con el código.

En la universidad, uno de mis profesores favoritos usó la frase “construir un rascacielos en la playa”. El código sin pruebas unitarias se ajusta muy bien a esa descripción.

Por cierto, en mi libro Programación para principiantes, que es un enfoque basado en proyectos para aprender a codificar, dirigido a adultos y adolescentes, las pruebas unitarias son muy importantes porque le dan al alumno la oportunidad de comprender pequeños fragmentos de código y refactorizar y reescribir el código en un entorno seguro y controlado. (El libro usa Kotlin).

Tuve la suerte de trabajar principalmente en empresas donde las pruebas unitarias son muy valoradas. Nunca trabajaría para una empresa que no aceptara las pruebas unitarias.

Restringí las pruebas unitarias principalmente a la interfaz pública de mi código (sujeto a algunas advertencias). Tres importantes beneficios de esta práctica me han ahorrado enormes cantidades de tiempo en el camino:

  1. Refactorización con confianza : si tiene una buena cobertura de prueba de su API pública, puede saber con bastante rapidez cuando la refactorización rompió el “contrato” entre usted y el usuario final.
  2. Documentación por ejemplo : los usuarios pueden aprender mucho leyendo un código de prueba bien escrito. Algunas personas realmente toman ejemplos en lugar de comentarios narrativos y documentación.
  3. Evite la ingeniería excesiva: restringir las pruebas a la funcionalidad de cara al público y diseñar estas pruebas antes de que comience la codificación principal mantiene su diseño centrado en los requisitos y ayuda a definir “lo suficientemente bueno” y “hecho”.

Sin embargo, hay lugares donde he encontrado que las pruebas unitarias son más trabajo de lo que vale:

  • Detalles internos / de implementación : solo escribiré algunas afirmaciones en el código para verificar y luego desactivarlas, sin necesidad de todo el aparato de prueba de la unidad.
  • Objetos altamente dependientes / acoplados : si estoy diseñando un objeto que accede a una API externa, entonces mis pruebas dependen de que la API externa sea estable. Solo probaré una vez y luego monitorearé las interrupciones (o ejecutaré estas verificaciones de API con menos frecuencia para no generar toneladas de llamadas de red)
  • Interacciones de objeto a objeto : Honestamente, este es un mal uso de las pruebas unitarias de todos modos, pero es fácil pasar de las pruebas unitarias a las pruebas de nivel superior si no es consciente de esto: mantenga las cosas muy granulares.
  • Cualquier cosa que requiera un gran “arnés”, a menos que sea absolutamente crítico hacerlo bien. No crearía uno solo para poder mejorar mi “cobertura”.

De todos modos, estas son mis experiencias al tratar de implementar TDD en proyectos reales con plazos.

P: ¿Cuál es su opinión honesta sobre las pruebas unitarias?

Contestaré la pregunta desde una perspectiva ligeramente diferente, desde la perspectiva del entorno que generalmente se considera “imposible” para escribir pruebas unitarias. Específicamente, el modding de Minecraft, pero creo que se aplica en general al desarrollo de juegos. Ciertamente puedo ver su utilidad en un entorno más sano, pero el modding de Minecraft es con lo que trabajo principalmente (actualmente).

Generalmente escribo pruebas unitarias para asegurarme de que el código realmente haga lo que quiero sin muchos ciclos de modificación-> compilación-> ejecución->, o para evitar regresiones. En gran parte del código que escribo, escribo pruebas unitarias para el código que:

  • Es probable que se malinterprete fácilmente
  • Es muy probable que haya regresiones
  • Es difícil de depurar en un sistema en vivo, incluso cuando lo que hace parece simple
  • Es improbable que el usuario pueda detectar fácilmente un comportamiento incorrecto

Si alguno de estos es cierto, trato de escribir pruebas unitarias. Siempre implica mucho trabajo y crear algunas abstracciones normalmente innecesarias. Como resultado, no tengo muchas pruebas unitarias. ¿Es tan malo? No es tan malo como parece. La mayoría de las veces, cuando falla mi código, es obvio que falló.

En el código todavía estoy (re) escribiendo por quinta vez, estoy agregando pruebas unitarias solo para asegurarme de que el código funcione según lo diseñado, y cualquier falla es un problema con el diseño, no con la implementación. Que cuando algo no funciona, simplemente no lo pensé bien, no es que cometí un error estúpido en la implementación.

En general, recomendaría escribir pruebas unitarias siempre que no sean demasiado complicadas y que en realidad puedan ser útiles.

Trabajo en simulación donde muchos de los resultados son visuales.

Las estructuras y algoritmos centrales (como la conversión de cartesiano a WGS84 lat-long) se someten a pruebas unitarias para garantizar su precisión.

Pero las interacciones entre los diversos sistemas, así como dependiendo de los sistemas de Física de terceros, pueden hacer que las pruebas de Unidad sean muy difíciles (e inútiles en mi opinión) para una gran parte del proyecto.

Lo que funciona mejor es una prueba de integración bien planificada donde puede grabar y reproducir lógicamente una serie de pasos para replicar la entrada de un usuario.

Para cada acción simplemente registre la acción, el resultado esperado y el real.

No solo puede ver rápidamente si algo está roto, sino que puede hacer referencias cruzadas de múltiples pruebas para ver si los resultados difieren.

Creo que para las aplicaciones comerciales estándar, las pruebas unitarias son críticas, ya que muchos de los algoritmos y procesos deben ser correctos y son puramente lógicos.

Cuando escuché por primera vez sobre JUnit, justo después de que Kent Beck lo presentara, en 1997, pensé que era una idea fascinante.

Estaba trabajando en C ++ en ese momento, pero estaba jugando un poco en Java en ese momento, y le di una oportunidad a JUnit. Casi me resulta imposible escribir pruebas unitarias para todas las funciones, excepto para mi nivel más bajo.

Resulta que no puede hacer pruebas unitarias, en ningún sentido significativo, a menos que organice su código de una manera que lo haga comprobable. En ese momento, no tenía idea de cómo hacerlo.

Lo que hemos aprendido, a lo largo de los años, es que la parte crítica de escribir pruebas unitarias no es escribir las pruebas, es escribir el código que está probando de una manera que hace que las dependencias sean explícitas y fáciles de administrar.

Y eso tiene beneficios que van mucho más allá de las pruebas.

¿Qué necesitas para hacer pruebas unitarias?

  • Un marco de pruebas unitarias
  • Un contenedor de inyección de dependencia
  • Código que se basa en el contenedor para inyectar dependencias
  • Un marco burlón para facilitar la creación de módulos falsos para inyectar en los componentes durante las pruebas.

En ausencia de todo esto, las pruebas unitarias no son realmente factibles.

Sin embargo, comienza con la inyección de dependencia, no con las pruebas.

Me gusta para cosas que tienen definiciones directas de éxito. Un ejemplo que me viene a la mente son los primeros ejemplos de código en el archivo Léame Dapper. Esto me parece un muy buen uso de las pruebas unitarias. En mi propio trabajo, no llevo a cabo todo lo que debería en esto, pero escribir pruebas unitarias requiere un esfuerzo significativo, si las pruebas son buenas.

Sin embargo, no entiendo la filosofía TDD de escribir pruebas primero, porque me encuentro haciendo muchos prototipos, lluvia de ideas y generalmente pensando en voz alta sobre lo que necesito hacer. La idea de desarrollar pruebas primero supone que conozco el resultado deseado de todo de antemano. Tal vez lo hago por algunas cosas, pero no de manera general. Entonces, nunca escribo pruebas primero. Simplemente no puedo concebir cómo se vería eso con respecto a lo que hago: crear clases modelo seguidas de páginas web para presentarlas / interactuar con ellas.

Una cosa que * no * me gusta de TDD es la inyección de dependencia y las acrobacias relacionadas (es decir, burlarse) para hacer que el código sea comprobable. Entiendo el valor del acoplamiento suelto y tener capas distintas de una solución con dependencias que van en una dirección. Pero hay una diferencia entre el acoplamiento flojo y “tan flojo que ya no puedes seguirlo”. Estoy abierto a que cualquiera cambie de opinión sobre esto, pero aquí es donde estoy ahora.

He apoyado sistemas grandes y complejos durante años, con buenas y malas experiencias. Sé lo que es tener miedo de romper cosas cuando las cosas se vuelven complicadas y frágiles. En mi experiencia, lo que realmente dolió fue no tener pruebas de navegador automatizadas. La falta de pruebas unitarias realmente no fue un problema porque los problemas de calidad más importantes con los que lidié se relacionaron con molestias oscuras de JavaScript o problemas fundamentales con el diseño de la base de datos que las pruebas unitarias simplemente no habrían abordado.

Recientemente me he enamorado de las pruebas y el monitoreo automatizados de sitios web: Ghost Inspector para las pruebas del navegador del usuario final. Eso hubiera sido bueno tener hace un par de años.

Escribir y empujar código sin pruebas unitarias es como redactar su tesis sin revisar la ortografía o incluso leerla.

¿Cómo sabes que la funcionalidad que escribiste es correcta? ¿Cómo sabe que sus pruebas manuales no están simplemente pasando debido a una peculiaridad en el diseño del sistema?

Al mismo tiempo, un par de pruebas unitarias que simplemente pasan no son realmente pruebas; Es esponjoso decir “mi código funciona”.

Utilice las pruebas unitarias para romper sus funciones específicas. Asegúrese de que se generen excepciones cuando se espera, que el registro se registra correctamente.

Intente implementar TDD y, en realidad, hágalo, no solo “oh, voy a hacer algunas pruebas para que parezca que lo hice”.

No tema las pruebas fallidas: cada prueba fallida es un caso límite para el que no diseñó.

Mi experiencia con las pruebas unitarias es que me ayuda a trabajar más rápido con mayor confianza .

En mi vida profesional trabajando en grandes aplicaciones web de Python, cuento con un buen conjunto de pruebas unitarias y un flujo de trabajo de desarrollo que fomenta su mejora continua. Una de las primeras cosas que quiero saber sobre una nueva base de código es, ¿cómo ejecuto las pruebas?

Recientemente pasé un par de noches hackeando un proyecto personal mío. Es una aplicación web (dpaste.com), alrededor de 1600 líneas de Python con 81 pruebas. Esto es lo que estaba intentando, todo a la vez (es decir, todos en la misma rama de características):

  • pasar de Python 2 a Python 3
  • actualizar Django a la última versión (un salto de varias versiones)
  • actualizar todos los componentes de terceros que mi aplicación utiliza a la última versión (31 componentes cuando incluye las dependencias de los principales)
  • Un cambio en alguna lógica central que no ha sido tocada en tres años

Cada uno de esos es un cambio importante. Definitivamente un conjunto ambicioso de objetivos, y no estaba seguro de que fuera razonablemente alcanzable.

Pero lo que lo hizo simplemente ambicioso y no insensato fue mi conjunto de pruebas unitarias.

Con esas pruebas encontrando cada lugar donde los cambios anteriores causaron problemas, pude completar el trabajo anterior en dos noches agradables.

Las pruebas tardan unos dos segundos en ejecutarse, por lo que puedo ejecutarlas después de cada cambio que realizo. Cada prueba ejecutada con fallas o errores me señala algo que me complace solucionar antes de frustrar a mis usuarios. Cada ejecución que pasa es una confirmación de que mis cambios hasta ese momento no han dañado la aplicación. Eso es lo que hace que las pruebas automatizadas valgan la pena.

En teoría , hacer que un programador demuestre que el código funciona correctamente es una buena idea.

En la práctica , hay problemas:

  1. Juzgar a los desarrolladores por los números de cobertura del código crea un incentivo para escribir muchas pruebas que carecen de profundidad. El resultado final es una base de código que parece estar bien probada, pero con un montón de casos extremos no probados. Una bomba de tiempo básicamente.
  2. Los desarrolladores que escriben pruebas unitarias incorrectamente es otro problema. Debería poder ejecutar sus pruebas unitarias en paralelo. Si no puedo, no son pruebas unitarias (son pruebas funcionales, de componentes, de integración o lo que sea). Las pruebas unitarias no deberían depender de ningún estado global . He visto demasiadas “pruebas unitarias” llamando a la base de datos real, corriendo lento e interfiriendo entre sí por eso.
  3. Las pruebas unitarias tienen garantías débiles cuando se escriben con accesorios. El enfoque de “Documentación con el ejemplo” solo prueba que la función en cuestión funciona correctamente para una entrada específica. Eso no es lo suficientemente bueno para mí. Es por eso que uso técnicas del libro de jugadas de pruebas basadas en la propiedad . Específicamente, uso ScalaCheck. Si programa en Python, puede usar HypothesisWorks / hipótesis-python.
  4. Las pruebas unitarias no prueban que el sistema realmente funcione. Lo que los hace necesarios, pero insuficientes al probar su software.

Recomiendo adoptar pruebas basadas en propiedades. Te sorprenderá el tipo de errores que puedes encontrar.

Mi sincera opinión es que todos deberían escribir pruebas unitarias. Las pruebas unitarias deben considerarse parte de su esfuerzo de desarrollo y no deben verse como algo separado. Si no hay pruebas unitarias, significa que su código está incompleto.

Las pruebas unitarias son su primera línea de defensa contra errores y, a menos que tenga otras buenas razones para no escribirlo, siempre debe escribirlo.

  1. Idealmente, cuando diseñe su clase, debe escribir pruebas unitarias para todos los escenarios posibles, incluso antes de escribir el código. Si no lo está haciendo, al menos debe escribir todas las validaciones posibles para los métodos de esa clase y luego convertirlo en prueba.
  2. Las pruebas unitarias no solo ayudan en las pruebas, sino que también funcionan como documentación para la clase. Sus pruebas unitarias muestran que cuál es el comportamiento previsto de los diferentes componentes de la clase. Esto ayuda a las personas a realizar cambios futuros.
  3. Cuando tienes que escribir pruebas unitarias, tienes que diseñar tus clases de una manera agradable. Debe seguir buenos principios de diseño y en el proceso tendrá un código modular y bien factorizado.
  4. La prueba de unidad hace que la revisión de código también sea fácil. Si envía código para revisión con pruebas de unidad, el revisor comprende rápidamente el propósito de diferentes partes de sus cambios. Además, si en el futuro alguien necesita usar su código (o integrarlo con otra cosa), las pruebas unitarias lo ayudan a comprenderlo bien.
  5. Las pruebas unitarias ayudan a depurar, especialmente cuando está depurando el código de otra persona.
  6. Leí en otra respuesta que alguien dijo, si la persona que está codificando el componente está escribiendo un caso de prueba de unidad, entonces no es útil, pero no estoy de acuerdo con eso. Puede ser cierto para la prueba de integración, pero no para las pruebas unitarias. La persona que diseña y desarrolla una clase conoce más el propósito de la misma. Esa persona debe escribir casos para todos los escenarios posibles (entradas, salidas), si más tarde encuentra algo que se perdió, vuelva y agregue una prueba para eso también.
  7. He visto en mi experiencia personal que los proyectos en los que las personas escriben religiosamente pruebas unitarias, los ingenieros realizan cambios de código con más confianza.

Sé que puede haber lugares donde es imposible escribir pruebas unitarias, pero eso es una excepción y debería ser una parte muy pequeña de la base del código.

Si soy yo quien toma la decisión, nunca dejaré que la gente agregue código sin agregar pruebas unitarias.

Depende de la complejidad del proyecto.

Comencemos con el más básico de los proyectos … creando un tema de wordpress. No encontrará muchos desarrolladores que escriban pruebas unitarias aquí, y la mayoría de los errores son difíciles de probar. Por ejemplo, este CSS no representa lo mismo en IE 10.xx frente a Chrome.

Estoy seguro de que puede configurar pruebas para esto, tal vez no pruebas unitarias por definición, pero pocos proyectos de WordPress obtienen valor de esto.

¿Qué pasa con una aplicación web personalizada pequeña a mediana? Definitivamente ayuda tener pruebas, y TDD sería mejor. ¿Vale la pena el tiempo? Si ya es un desarrollador de TDD, probablemente sí, si no, o digamos que la mayoría de su equipo no lo es, no creo que necesariamente agregue mucho valor. Solo si el proyecto sigue cambiando, crece y se mantiene durante muchos años. No tenemos bolas de cristal, pero en mi experiencia la mayoría de las aplicaciones pequeñas a medianas duran de 3 a 5 años y luego las cosas cambian tanto que una reescritura a menudo es mejor.

¿Qué pasa con los proyectos grandes o pequeños con grandes ambiciones a largo plazo? Por ejemplo, ¿una startup que lo hace grande y desafía las probabilidades de fracaso? Entonces sí, las pruebas automatizadas y TDD parecen ser un claro ganador. A medida que el equipo crece, es imposible tener confianza en los cambios de código, es más costoso en este punto probar manualmente. TDD es genial, pero aún no lo es si solo un pequeño% sabe cómo hacerlo. Entonces obtendrá una falsa confianza en su código. En mi opinión, es mejor tener pruebas de integración que aseguren que la entrada conduzca a la salida deseada. Pero no tengo mucha experiencia con proyectos con muchos desarrolladores. Desde escuchar entrevistas con DHH (fundador de RoR), aunque parece aplicar un camino intermedio a la prueba, en comparación con Kent Beck, que hace TDD porque esa es su forma de pensar.

¿Mi opinión?

  1. El hecho de que su código haya pasado todas sus pruebas unitarias no significa que su código no tenga errores.
  2. Si el mismo desarrollador escribió el código y las pruebas unitarias , puede que no sirva para ese propósito. Si no pensó en casos extremos mientras escribía el código, lo más probable es que no haya pensado lo mismo al escribir pruebas unitarias.
  3. En las pruebas unitarias, verifique el estado antes de llamar al código y después de llamarlo . La mayoría de las personas pierden el control del estado previo. A veces, su estado posterior es correcto, pero no el estado anterior. Sucede.
  4. A veces, es difícil escribir pruebas unitarias para todo. Es posible que esté utilizando alguna tecnología que aún no es compatible con el marco de prueba que está utilizando.
  5. Escriba múltiples pruebas unitarias para la misma función. No se detenga con una sola prueba de unidad para cada función.
  6. No escriba pruebas unitarias por el simple hecho de hacerlo.
  7. Las pruebas unitarias hacen que sea mucho más fácil que probar el código manualmente. Puede no ser cierto en todos los escenarios. Pero lo he encontrado cierto de todos modos.

Es un trabajo ingrato. Cierto. Pero es su responsabilidad escribir el código correcto.

Y las pruebas unitarias son una forma de ayudar con eso.

Meh

De alguna manera, las pruebas pueden ser buenas. De otra manera, las pruebas pueden ser un sumidero de tiempo. Cruzo de ida y vuelta entre el mundo de inicio y el mundo de consultoría de alta gama.

Probablemente haya algo de valor en el mundo de la consultoría de gama alta si tiene un equipo grande con una aplicación realmente complicada. En mi vida de consultoría, nunca he encontrado un cliente que quiera pagarlo. Los que he tratado quieren ver el producto para probarlo. Estoy seguro de que las personas que tienen trabajos de consultoría de varios años trabajando en productos internos importantes querrían esto y tendría sentido

En el mundo de las startups, simplemente no tengo tiempo. Necesito crear un MVP, obtener un cambio, estar con clientes, vender, etc. No tengo mucho tiempo para probar.

Para aquellas personas que piensan que las pruebas deben integrarse en todo, no está sucediendo del todo, o aquellas que pueden ver los diferentes grados de necesidad en diferentes situaciones, estamos de acuerdo.

Eso es lo que veo.

Las pruebas unitarias siempre son increíbles para el propietario de la base de código (gestión de lectura y empresa).

Las pruebas unitarias son una pérdida de tiempo horrible cuando lo haces por el código de otra persona.

Las pruebas unitarias son razonables para su propio código de misión crítica. Es mucho mejor solucionar los problemas raros y no críticos cuando ocurren, en lugar de perder el tiempo con una cobertura del 100%. Sin embargo, pasaría tiempo de calidad en diseño y revisiones de código.

Los jugadores grandes tienden a invertir en exceso en las pruebas unitarias, donde las empresas emergentes usan sus recursos sabiamente para interrumpir a los jugadores grandes.

More Interesting

¿Cómo es ser rechazado por un trabajo después de trabajar en Google?

¿Puedo convertirme en un ingeniero de software empleable si soy un gran trabajador en lugar de talentoso?

Para los ingenieros de software que trabajan en empresas de prestigio, ¿qué tan hábil era para responder preguntas de estilo de entrevista antes de practicar?

¿Cuáles son buenos libros y tutoriales sobre técnicas de registro en ingeniería de software?

¿Cuáles son algunas buenas áreas de investigación en ingeniería de software?

¿Qué software debo aprender como ingeniero estructural: SAP eval 16 o STAAD pro?

¿Cuál es la diferencia entre un desarrollador, programador e ingeniero de software?

Soy un ingeniero de software que trabaja en una empresa de software basada en servicios. ¿Qué debo hacer para ser reclutado por grandes gigantes tecnológicos como Microsoft, VMware y Flipkart?

Si los ingenieros de software son más efectivos cuando trabajan solos, ¿cómo los manejan las compañías tecnológicas?

Cómo emigrar a Canadá como ingeniero de software

Como ingeniero de software, mi interés cambia después de aproximadamente un año, y quiero trabajar en cosas nuevas. ¿Es malo cambiar de equipo con tanta frecuencia?

¿Cuál es su opinión sobre el hecho de que un gran número de personas extremadamente inteligentes en el Valle están trabajando para tratar de hacer que más personas hagan clic en los enlaces?

¿Qué tan fuerte es la industria de software de Israel y las calificaciones profesionales de sus ingenieros de software?

¿Qué tan difícil es tener un piso de 3 BHK en cualquier área de Mumbai para un ingeniero de software con 20 LPA CTC?

¿Qué es más fácil, ser desarrollador web o ingeniero de software?