Pruebas unitarias automatizadas, pruebas de integración o pruebas de aceptación [cerrado]

29

TDD y las pruebas unitarias parecen ser el gran delirio en este momento. ¿Pero es realmente tan útil en comparación con otras formas de pruebas automatizadas?

Intuitivamente, supongo que las pruebas de integración automatizadas son mucho más útiles que las pruebas unitarias. En mi experiencia, la mayoría de los errores parecen estar en la interacción entre los módulos, y no tanto en la lógica real (generalmente limitada) de cada unidad. También las regresiones a menudo ocurrieron debido a las interfaces cambiantes entre los módulos (y las condiciones previas y posteriores modificadas).

¿Estoy malinterpretando algo, o por qué las pruebas unitarias reciben tanta atención en comparación con las pruebas de integración? ¿Es simplemente porque se supone que las pruebas de integración son algo que usted tiene, y las pruebas unitarias son lo siguiente que debemos aprender a aplicar como desarrolladores?

¿O tal vez las pruebas unitarias simplemente producen la mayor ganancia en comparación con la complejidad de la automatización?

¿Qué experiencia tiene con las pruebas unitarias automatizadas, las pruebas de integración automatizadas y las pruebas de aceptación automatizadas, y en su experiencia, qué ha producido el ROI más alto? ¿y por qué?

Si tuviera que elegir solo una forma de prueba para automatizar en su próximo proyecto, ¿cuál sería?

Gracias por adelantado.

Bjarke Freund-Hansen
fuente
Solo me gustaría agregar un enlace tardío a las Pruebas de integración de JB Rainsberger son una estafa . Destaca muchas de las razones por las que las pruebas de integración son una economía falsa.
Tim
66
¡Este es otro ejemplo más de cerrar una pregunta que estaba perfectamente bien en este sitio cuando se hizo hace tres años! ¡Es realmente molesto contribuir a una comunidad donde las reglas cambian y simplemente tiras todas las cosas viejas!
Bjarke Freund-Hansen

Respuestas:

34

Un factor importante que hace que las pruebas unitarias sean extremadamente útiles es la retroalimentación rápida .

Considere lo que sucede cuando tiene su aplicación completamente cubierta con pruebas de integración / sistema / funcional (que ya es una situación ideal, lejos de la realidad en la mayoría de las tiendas de desarrollo). Estos a menudo son dirigidos por un equipo de pruebas dedicado.

  • Confirmas un cambio en el repositorio de SCM,
  • en algún momento (posiblemente días) más tarde, los chicos de prueba obtienen una nueva versión interna y comienzan a probarla
  • encuentran un error y presentan un informe de error,
  • (en el caso ideal) alguien le asigna el informe de error.

Todo esto puede llevar días o incluso semanas. En este momento ya ha estado trabajando en otras tareas, por lo que no tiene los detalles minuciosos del código escritos anteriormente en su mente. Además, por lo general, ni siquiera tiene una prueba directa de dónde está realmente el error, por lo que lleva mucho tiempo encontrarlo y solucionarlo.

Mientras que en pruebas unitarias (TDD)

  • escribes una prueba,
  • escribes un código para satisfacer la prueba,
  • la prueba aún falla,
  • miras el código y normalmente tienes una experiencia de "¡Uy!" en unos segundos (como "¡Uy, olvidé comprobar esa condición!"), luego
  • corrige el error de inmediato.

Todo esto sucede en cuestión de minutos .

Esto no quiere decir que las pruebas de integración / sistema no sean útiles; solo sirven para diferentes propósitos. Con pruebas unitarias bien escritas, puede detectar una gran proporción de los errores en el código antes de que lleguen a la fase de integración, donde ya es considerablemente más costoso encontrarlos y solucionarlos. Tiene razón en que las pruebas de integración son necesarias para detectar los tipos de errores que son difíciles o imposibles de detectar con las pruebas unitarias. Sin embargo, en mi experiencia, esos son del tipo más raro; La mayoría de los errores que he visto son causados ​​por alguna omisión simple o incluso trivial en algún lugar dentro de un método.

Sin mencionar que las pruebas unitarias también prueban las interfaces de usabilidad / seguridad, etc., lo que le brinda comentarios de vital importancia para mejorar su diseño y API. En mi humilde opinión, puede reducir considerablemente las posibilidades de errores de integración de módulo / sistema de sistema: cuanto más fácil y limpia sea una API, menos posibilidades de malentendido u omisión.

¿Qué experiencia tiene con las pruebas unitarias automatizadas, las pruebas de integración automatizadas y las pruebas de aceptación automatizadas, y en su experiencia, qué ha producido el ROI más alto? ¿y por qué?

El ROI depende de muchos factores, probablemente el principal de ellos es si su proyecto es totalmente nuevo o heredado. Con el desarrollo greenfield, mi consejo (y experiencia hasta ahora) es hacer pruebas de unidad al estilo TDD desde el principio. Estoy seguro de que este es el método más rentable en este caso.

Sin embargo, en un proyecto heredado, construir una cobertura suficiente de pruebas unitarias es una tarea enorme que será muy lenta para obtener beneficios. Es más eficiente tratar de cubrir la funcionalidad más importante con el sistema / pruebas funcionales a través de la interfaz de usuario si es posible. (Las aplicaciones GUI de escritorio pueden ser difíciles de probar automáticamente a través de la GUI, aunque las herramientas de soporte de prueba automatizadas están mejorando gradualmente ...). Esto le proporciona una red de seguridad gruesa pero efectiva rápidamente. Luego, puede comenzar a construir gradualmente pruebas unitarias en torno a las partes más críticas de la aplicación.

Si tuviera que elegir solo una forma de prueba para automatizar en su próximo proyecto, ¿cuál sería?

Esa es una pregunta teórica y me parece inútil. Todos los tipos de pruebas tienen su uso en la caja de herramientas de un buen ingeniero de SW, y todos estos tienen escenarios en los que son insustituibles.

Péter Török
fuente
2
+1 para "retroalimentación rápida" para pruebas unitarias. Además, es muy útil para ejecutarse como post-commit en un servidor de integración continua.
Frank Shearar
1
"Todo tipo de pruebas tienen su uso en la caja de herramientas de un buen ingeniero de software, y todas ellas tienen escenarios en los que son insustituibles". - ¡Ojalá pudiera votar varias veces solo por eso! Las personas que piensan que pueden encontrar una herramienta / método de prueba ideal y aplicarlo en todas partes me están desgastando.
ptyx
8

Todos los tipos de pruebas son muy importantes y garantizan que los diferentes aspectos del sistema cumplan con las especificaciones. Entonces, para trabajar hacia atrás, "si tuviera que elegir un tipo de prueba ..." no lo haría. Las pruebas unitarias me proporcionan diferentes comentarios que las pruebas de integración o las pruebas interactivas de una persona.

Este es el tipo / beneficio de las pruebas que hacemos:

  • Prueba de unidad: garantiza que las unidades realicen el trabajo como esperamos que lo hagan Probamos los contratos de proveedores y consumidores para cada interfaz, y esto es bastante fácil de automatizar. También verificamos nuestras condiciones de contorno, etc.
  • Pruebas de integración: garantiza que las unidades trabajen juntas en concierto. Esto es principalmente para probar nuestro diseño. Si algo se rompe aquí, tenemos que ajustar nuestras pruebas unitarias para asegurarnos de que no vuelva a suceder.
  • Prueba del sistema: garantiza que el sistema cumpla con los requisitos / especificaciones. Por lo general, las personas hacen este tipo de pruebas.
  • Prueba de aceptación: el cliente hace esto para verificar que el producto final haga lo que se anuncia.

Pruebas opcionales pero recomendadas:

  • Pruebas de experiencia del usuario: si bien recibimos comentarios decentes de las pruebas del sistema, hacer que la gente del cliente obtenga una vista previa de ciertos prelanzamientos realmente puede ayudar a determinar si necesitamos cambiar las cosas antes de que sea demasiado tarde.

Solo para comprender por qué las pruebas unitarias tienen una ventaja sobre las pruebas de integración, debe comprender los órdenes de magnitud de las pruebas adicionales que necesitaría para ser exhaustivo. Para cada resultado posible para la unidad A, debe haber una prueba. Lo mismo para la unidad B. Ahora, si ambos trabajan juntos para una solución más completa, el número de pruebas es combinatorio. En resumen, para probar cada permutación de interacción entre la unidad A y la unidad B, necesita pruebas A * B. Agregue la unidad C, y el número de pruebas para el trío sería A * B * C.

Aquí es donde el concepto de interfaces y límites de objetos se vuelve muy importante. Las interfaces representan un cierto contrato. Un implementador de una interfaz acepta que se comportará de cierta manera. Del mismo modo, el consumidor de una interfaz acepta que utilizará la implementación de cierta manera. Al escribir una prueba que recopila cada clase que implementa una interfaz, puede probar fácilmente que cada implementación observa los contratos de interfaz. Esa es la mitad de la ecuación. La otra mitad es probar el lado del consumidor, que es donde entran en juego los objetos simulados. El simulacro está configurado para garantizar que las interacciones siempre estén en las especificaciones. En este punto, todo lo que se necesita son algunas pruebas de integración para asegurarnos de que tenemos los contratos del implementador / consumidor correctos.

Berin Loritsch
fuente
"Pruebas del sistema: garantiza que el sistema cumple los requisitos / especificaciones. Por lo general, las personas realizan este tipo de pruebas". Las pruebas de integración System / aka funcional / aka "end-to-end" / aka de alto nivel también son buenas para la automatización.
MiFreidgeim SO-deja de ser malvado
3

Estas son diferentes herramientas con diferentes objetivos:

  • Las pruebas unitarias son una herramienta de diseño (TDD), y un requisito casi previo para la refactorización.

  • Las pruebas de integración son excelentes para visualizar el progreso del proyecto y también para evitar errores de regresión.

El punto a recordar es que realmente no puede diseñar con pruebas de integración, y no encontrará regresiones con pruebas unitarias.

Javier
fuente
@ Realmente no puede diseñar con pruebas de integración, y no encontrará regresiones con pruebas unitarias. ¡Exactamente!
Chankey Pathak
Las pruebas unitarias pueden encontrar regresiones causadas por refactorización, por ejemplo, un método auxiliar compartido modificado. Sin embargo, las pruebas de integración son mucho mejores para ello.
StuperUser
El segundo punto sobre las pruebas de integración incluye pruebas de "sistema / funcional" (también conocido como "de extremo a extremo")
MiFreidgeim SO-deja de ser malo
Totalmente de acuerdo; Steve Sanderson hizo un comentario similar hace unos años. Consulte la tabla "Objetivo: técnica más fuerte" en su publicación de blog de 2009 en blog.stevensanderson.com/2009/08/24/… para obtener ideas complementarias a las suyas aquí.
Mark A. Fitzgerald
1

He usado Selenium ampliamente para controles de cordura.

En una gran empresa de publicación web, cuando se realizó un nuevo lanzamiento, generalmente se necesitaron alrededor de 3 evaluadores alrededor de una o dos horas para visitar todas las familias de sitios y asegurarse de que todo estuviera bien, según el guión de prueba. Con Selenium, pudimos automatizar las pruebas y distribuirlas en múltiples máquinas y navegadores. Actualmente, cuando se ejecutan los scripts de prueba, a las PC les lleva unos 10 minutos hacer lo mismo automáticamente Y escupir un bonito informe.

Lo mejor del selenio es que puedes vincularlo con marcos de pruebas unitarias como XUnit, TestNG o MSTest.

En mi experiencia, ha sido extremadamente valioso, sin embargo, la configuración de algo así realmente depende de su proyecto y su equipo, por lo que el ROI definitivamente variará.

Ryan Hayes
fuente
1

El mejor ROI suele ser la prueba más temprana que puede encontrar ese tipo de error.

Las pruebas unitarias deberían encontrar la mayoría de los errores que se encuentran en un solo método, o quizás en un componente. Encuentra errores que generalmente se pueden solucionar en minutos, con tiempos de respuesta totales de menos de una hora. ¡Pruebas MUY baratas, errores MUY baratos para encontrar y arreglar! Si esos errores se convirtieron en pruebas de integración, el cambio podría ser más como un día (las ejecuciones de prueba a menudo ocurren todas las noches), suponiendo que el error no esté ocluido por otro error; Además, es probable que se introduzcan más errores ya que se escribió otro código contra el código de error inicial; Además, cualquier rediseño afectará a más piezas de código. Además, dejar pasar más errores significa tener que hacer muchas más pruebas antes de que se puedan completar las pruebas de integración. Las malas pruebas unitarias a menudo son el núcleo de un proceso largo, oneroso y costoso.prueba de ciclos de integración. Omitir las pruebas unitarias puede reducir a la mitad el tiempo de desarrollo, pero las pruebas demorarán de 3 a 4 veces al menos, todo el proyecto duplicará su duración y aún tendrá una calidad inferior a la que tendría si probara la unidad IME.

Las pruebas de integración suelen ser las primeras pruebas reales que pueden encontrar errores de integración (aunque los procesos de revisión pueden encontrar algunos errores antes de que se escriba el software o antes de que el código se pruebe). Desea encontrar esos errores antes de comenzar a mostrar el software al usuario o al lanzamiento, ya que corregir los errores en el último momento (¡o corregirlos en caliente!) Es muy costoso. No puede encontrar esos errores antes, cuando serían más baratos de solucionar, porque necesita múltiples componentes de trabajo para integrarse (por definición). Las pruebas de integración se ralentizan cuando los errores que no tienen nada que ver con piezas interactivas (como errores tipográficos menores) deben resolverse primero antes de que las pruebas más interesantes puedan comenzar.

Las pruebas de aceptación del usuario se aseguran de que el software haga lo que el cliente desea (aunque es de esperar que el cliente haya estado involucrado todo el tiempo, para reducir el riesgo de encontrar una gran brecha entre las expectativas y el software real justo al final del proyecto, MUY costoso !). Para cuando llegue a esta etapa de prueba, realmente debería creer que la mayoría de los errores en su producto, en comparación con las especificaciones al menos, ya se han encontrado. Las pruebas de aceptación del usuario consisten más en asegurarse de que el producto se ajuste a las necesidades del cliente que en asegurarse de que no haya errores en comparación con las especificaciones.

Si solo fuera a automatizar un tipo de prueba, sería una prueba unitaria. Las pruebas de integración pueden hacerse manualmente y así fueron realizadas por muchas compañías importantes durante años. Lleva más tiempo hacer manualmente el trabajo que podría realizar una computadora una y otra vez, y es mucho más costoso para la mayoría de los proyectos, sin mencionar que es aburrido y propenso a errores, pero se puede hacer. Las pruebas de aceptación del usuario son a menudo manuales, ya que los usuarios a menudo no saben cómo automatizar sus pruebas mientras siguen probando lo que les importa. Las pruebas unitarias DEBEN ser automatizadas. Debe poder ejecutar todas las pruebas unitarias en unos pocos segundos a pedido con la frecuencia que cada pocos minutos. Los humanos simplemente no pueden acercarse con las pruebas manuales. Sin mencionar que las pruebas unitarias están en el código y no se pueden ejecutar sin llamarlas a través del código, es decir, automatizarlas.

Una cosa a tener en cuenta es que este es un foro principalmente para desarrolladores, no para evaluadores. Las pruebas de integración son implementadas principalmente por probadores. Las pruebas unitarias son implementadas por los desarrolladores. Naturalmente, los desarrolladores hablan más sobre las pruebas unitarias que otros tipos de pruebas. Esto no significa que no piensen que otras pruebas son importantes. Simplemente significa que en realidad no lo hacen (o lo hacen con menos frecuencia).

Ethel Evans
fuente
Gracias especialmente por ese último párrafo, no pensé en eso.
Bjarke Freund-Hansen
Para su información, actualicé la respuesta desde que la leyó, me di cuenta de que no leí la pregunta original con suficiente
atención
@EthelEvans, sus razones sobre las prioridades de las pruebas unitarias son correctas para nuevos proyectos. Para proyectos heredados, que se escribieron sin tener en cuenta la cobertura de pruebas automatizada, las pruebas de integración de alto nivel del sistema / aka funcional / aka son las más importantes. Consulte la última parte de la respuesta programmers.stackexchange.com/a/39370/31574 .
MiFreidgeim SO-deja de ser malvado
@MichaelFreidgeim, en última instancia, depende de qué tan estables sean las interfaces. La automatización de pruebas de alto nivel puede incurrir rápidamente en costos de mantenimiento prohibitivos si se desactualizan rápidamente. En este caso, automatice más bajo para ayudar a construir estabilidad y use pruebas exploratorias (posiblemente basadas en sesiones o listas de verificación) para E2E y pruebas de integración para evitar incurrir en costos de mantenimiento de automatización desagradables. Sin embargo, no todos los proyectos heredados tienen interfaces estables, especialmente si están siendo refactorizados o rediseñados de manera agresiva.
Ethel Evans
1

Siento que las pruebas de aceptación son el rey en este escenario.

Si un commit rompe las pruebas de aceptación, debe resolverse.

Las pruebas de aceptación le dicen dónde está su software, las pruebas unitarias no.

Por lo tanto, las pruebas unitarias pueden proporcionar una falsa sensación de seguridad.

godelfiend
fuente
0

La pregunta no es tanto qué es más importante, sino qué se puede automatizar y ejecutar rápidamente.

Las pruebas unitarias muestran si un componente pequeño es apto para un propósito de una manera particular y, por lo general, es pequeño y rápido de ejecutar. Al ser pequeños, generalmente son bastante fáciles de automatizar.

Las pruebas de integración muestran si los componentes funcionan juntos. Por lo general, son mucho más grandes y pueden no ser fáciles de automatizar. Pueden tomar más tiempo para correr. Es valioso poder ejecutarlos automáticamente, pero es una tarea más grande y de todos modos no se ejecutarán con tanta frecuencia.

Las pruebas de aceptación muestran si un proyecto es aceptable o no. Normalmente, esto es imposible de automatizar por completo (aunque las pruebas automatizadas pueden desempeñar un papel), ya que normalmente es imposible precisar los requisitos exactos y completos en un asunto formal que es menos complicado que el código fuente en sí. Las pruebas de aceptación generalmente incluyen usuarios potenciales que hacen cosas con el sistema y observan que los resultados son satisfactorios en todos los aspectos, lo que normalmente es parcialmente subjetivo. Dado que las pruebas de aceptación generalmente se ejecutan una vez (los diferentes clientes normalmente querrán hacer sus propias pruebas de aceptación por separado) realmente no vale la pena automatizar.

David Thornley
fuente