testing - tipos - tecnicas de pruebas de software
¿Cuál es la diferencia entre las pruebas de unidad, funcionales, de aceptación y de integración? (8)
¿Cuál es la diferencia entre las pruebas de unidad, funcionales, de aceptación y de integración (y cualquier otro tipo de pruebas que no mencioné)?
Algunas ideas (relativamente) recientes contra la burla excesiva y la prueba de unidad pura:
- https://www.simple-talk.com/dotnet/.net-framework/are-unit-tests-overused/
- http://googletesting.blogspot.com/2013/05/testing-on-toilet-dont-overuse-mocks.html
- http://codebetter.com/iancooper/2011/10/06/avoid-testing-implementation-details-test-behaviours/
- http://cdunn2001.blogspot.com/2014/04/the-evil-unit-test.html
- http://www.jacopretorius.net/2012/01/test-behavior-not-implementation.html
- ¿Por qué la mayoría de las pruebas unitarias son residuos?
Dependiendo de dónde mires, obtendrás respuestas ligeramente diferentes. He leído mucho sobre el tema, y aquí está mi destilación; de nuevo, estos son ligeramente lanudos y otros pueden estar en desacuerdo.
Pruebas unitarias
Prueba la unidad de funcionalidad más pequeña, generalmente un método / función (por ejemplo, dada una clase con un estado particular, llamar al método x en la clase debería hacer que ocurra y). Las pruebas unitarias deben centrarse en una característica particular (por ejemplo, llamar al método emergente cuando la pila está vacía debería lanzar una InvalidOperationException
). Todo lo que toca debe hacerse en la memoria; esto significa que el código de prueba y el código bajo prueba no deben:
- Llamar a colaboradores (no triviales)
- Acceder a la red
- Golpear una base de datos
- Usar el sistema de archivos
- Girar un hilo
- etc.
Cualquier tipo de dependencia que sea lenta / difícil de entender / inicializar / manipular debe ser modificada / burlada / lo que sea usando las técnicas apropiadas para que pueda concentrarse en lo que hace la unidad de código, no en lo que hacen sus dependencias.
En resumen, las pruebas unitarias son lo más simples posible, fáciles de depurar, confiables (debido a factores externos reducidos), rápidas de ejecutar y ayudan a demostrar que los bloques de construcción más pequeños de su programa funcionan según lo previsto antes de que se armen. La advertencia es que, aunque se puede demostrar que funcionan perfectamente de forma aislada, las unidades de código pueden explotar cuando se combinan, lo que nos lleva a ...
Pruebas de integración
Las pruebas de integración se basan en pruebas unitarias combinando las unidades de código y probando que la combinación resultante funciona correctamente. Esto puede ser el interior de un sistema, o la combinación de varios sistemas para hacer algo útil. Además, otra cosa que diferencia las pruebas de integración de las pruebas unitarias es el entorno. Las pruebas de integración pueden y usarán hilos, acceder a la base de datos o hacer lo que sea necesario para garantizar que todo el código y los diferentes cambios de entorno funcionarán correctamente.
Si ha creado algún código de serialización y la unidad ha probado sus entrañas sin tocar el disco, ¿cómo sabe que funcionará cuando cargue y guarde en el disco? Tal vez se le olvidó tirar y desechar secuencias de archivos. Tal vez sus permisos de archivo son incorrectos y ha probado las entrañas usando flujos de memoria. La única forma de averiguarlo con seguridad es probarlo "de verdad" utilizando un entorno que sea el más cercano a la producción.
La principal ventaja es que encontrarán errores que las pruebas unitarias no pueden hacer, como errores de cableado (por ejemplo, una instancia de clase A recibe inesperadamente una instancia nula de B) y errores de entorno (funciona bien en mi máquina con una sola CPU, pero mi la máquina de 4 núcleos de un colega no puede pasar las pruebas). La principal desventaja es que las pruebas de integración tocan más código, son menos confiables, las fallas son más difíciles de diagnosticar y las pruebas son más difíciles de mantener.
Además, las pruebas de integración no necesariamente prueban que una característica completa funcione. Es posible que el usuario no se preocupe por los detalles internos de mis programas, ¡pero yo sí!
Pruebas funcionales
Las pruebas funcionales verifican que una característica particular esté correcta comparando los resultados de una entrada determinada con la especificación. Las pruebas funcionales no se preocupan por los resultados intermedios o los efectos secundarios, solo el resultado (no les importa que después de hacer x, el objeto y tenga el estado z). Se escriben para probar parte de la especificación, como "llamando a la función Cuadrado (x) con el argumento de 2 devuelve 4".
Prueba de aceptacion
Las pruebas de aceptación parecen estar divididas en dos tipos:
Las pruebas de aceptación estándar implican realizar pruebas en todo el sistema (por ejemplo, usar su página web a través de un navegador web) para ver si la funcionalidad de la aplicación cumple con las especificaciones. Por ejemplo, "hacer clic en el icono de un zoom debería ampliar la vista del documento en un 25%". No hay una continuidad real de resultados, solo un resultado de aprobación o falla.
La ventaja es que las pruebas se describen en inglés simple y aseguran que el software, en su totalidad, esté completo. La desventaja es que has subido otro nivel en la pirámide de prueba. Las pruebas de aceptación tocan montañas de código, por lo que rastrear un fallo puede ser complicado.
Además, en el desarrollo ágil de software, las pruebas de aceptación del usuario implican la creación de pruebas para reflejar las historias de usuario creadas por / para el cliente del software durante el desarrollo. Si las pruebas pasan, significa que el software debe cumplir con los requisitos del cliente y que las historias pueden considerarse completas. Un conjunto de pruebas de aceptación es básicamente una especificación ejecutable escrita en un lenguaje específico del dominio que describe las pruebas en el idioma utilizado por los usuarios del sistema.
Conclusión
Todos son complementarios. A veces es ventajoso enfocarse en un tipo o evitarlos por completo. La principal diferencia para mí es que algunas de las pruebas miran las cosas desde la perspectiva de un programador, mientras que otras utilizan el enfoque del cliente / usuario final.
Esto es muy simple.
Prueba de unidad: esta es la prueba que realmente realizan los desarrolladores que tienen conocimientos de codificación. Esta prueba se realiza en la fase de codificación y es parte de la prueba de caja blanca. Cuando un software viene para el desarrollo, se desarrolla en el fragmento de código o segmentos de código conocido como unidad. Y las pruebas individuales de estas unidades denominadas pruebas unitarias realizadas por los desarrolladores para descubrir algún tipo de errores humanos, como la falta de cobertura de declaraciones, etc.
Prueba funcional: esta prueba se realiza en la fase de prueba (QA) y es parte de la prueba de caja negra. La ejecución real de los casos de prueba previamente escritos. Esta prueba la realizan realmente los evaluadores, encuentran el resultado real de cualquier funcionalidad en el sitio y comparan este resultado con el resultado esperado. Si encontraron alguna disparidad, entonces esto es un error.
Pruebas de aceptación: se conocen como UAT. Y esto, en realidad, lo realizan tanto el probador como los desarrolladores, el equipo de administración, el autor, los escritores y todos los involucrados en este proyecto. Para asegurar que el proyecto esté finalmente listo para ser entregado sin errores.
Pruebas de integración: las unidades de código (explicadas en el punto 1) se integran entre sí para completar el proyecto. Estas unidades de códigos pueden estar escritas en una tecnología de codificación diferente o pueden tener una versión diferente, por lo que los desarrolladores realizan estas pruebas para garantizar que todas las unidades del código sean compatibles con otras y no haya ningún problema de integración.
Lo importante es que sabes lo que esos términos significan para tus colegas. Los diferentes grupos tendrán definiciones ligeramente diferentes de lo que significan cuando dicen "pruebas completas", por ejemplo.
Me encontré con el sistema de nombres de Google para sus pruebas recientemente, y me gusta bastante, ya que ignoran los argumentos utilizando solo Small, Medium y Large. Para decidir en qué categoría encaja una prueba, analizan algunos factores: cuánto tiempo lleva ejecutarse, accede a la red, la base de datos, el sistema de archivos, los sistemas externos, etc.
http://googletesting.blogspot.com/2010/12/test-sizes.html
Me imagino que la diferencia entre Pequeño, Mediano y Grande para su lugar de trabajo actual puede variar de la de Google.
Sin embargo, no se trata solo del alcance, sino del propósito. El punto de Mark sobre las diferentes perspectivas para las pruebas, por ejemplo, programador vs cliente / usuario final, es realmente importante.
Te explicaré esto con un ejemplo práctico y nada de teoría:
Un desarrollador escribe el código. Aún no se ha implementado ninguna GUI. Las pruebas en este nivel verifican que las funciones funcionan correctamente y que los tipos de datos son correctos. Esta fase de prueba se llama prueba de unidad.
Cuando se desarrolla una GUI y la aplicación se asigna a un probador, él verifica los requisitos comerciales con un cliente y ejecuta los diferentes escenarios. Esto se llama prueba funcional. Aquí estamos mapeando los requisitos del cliente con flujos de aplicaciones.
Pruebas de integración: digamos que nuestra aplicación tiene dos módulos: recursos humanos y finanzas. El módulo de recursos humanos fue entregado y probado previamente. Ahora Finanzas está desarrollado y está disponible para probar. Las funciones interdependientes también están disponibles ahora, por lo que en esta fase, probará los puntos de comunicación entre los dos y verificará que funcionan según lo requerido en los requisitos.
La prueba de regresión es otra fase importante, que se realiza después de cualquier nuevo desarrollo o corrección de errores. Su objetivo es verificar las funciones previamente trabajadas.
prueba de unidad: se sabe que la prueba de un módulo individual o componente independiente en una aplicación es una prueba de unidad, la prueba de la unidad la realizará el desarrollador.
prueba de integración: combinando todos los módulos y probando la aplicación para verificar que la comunicación y el flujo de datos entre los módulos estén funcionando correctamente o no, esta prueba también la realizan los desarrolladores.
La prueba funcional que comprueba la funcionalidad individual de una aplicación es una prueba funcional.
las pruebas de aceptación se realizan por el usuario final o el cliente si la aplicación de compilación está de acuerdo con los requisitos del cliente, y las especificaciones del cliente son pruebas de aceptación.
http://martinfowler.com/articles/microservice-testing/
La publicación del blog de Martin Fowler habla sobre estrategias para probar el código (especialmente en una arquitectura de microservicios), pero la mayoría se aplica a cualquier aplicación.
Citaré de su resumen de la diapositiva:
- Pruebas unitarias: ejercite las piezas más pequeñas de software comprobable en la aplicación para determinar si se comportan como se espera.
- Pruebas de integración: verifique las rutas de comunicación y las interacciones entre los componentes para detectar defectos en la interfaz.
- Pruebas de componentes: limitan el alcance del software ejercitado a una parte del sistema que se está probando, manipulando el sistema a través de interfaces de código internas y utilizando pruebas dobles para aislar el código de otros componentes.
- Pruebas de contrato: verifique las interacciones en el límite de un servicio externo, afirmando que cumple con el contrato esperado por un servicio consumidor.
- Pruebas de extremo a extremo: verifique que un sistema cumpla con los requisitos externos y alcance sus objetivos, probando todo el sistema, de un extremo a otro.
Pruebas unitarias : como sugiere su nombre, este método realiza pruebas en el nivel del objeto. Los componentes de software individuales se prueban para detectar cualquier error. El conocimiento del programa es necesario para esta prueba y los códigos de prueba se crean para verificar si el software se comporta como se pretende.
Pruebas funcionales : se llevan a cabo sin ningún conocimiento del funcionamiento interno del sistema. El probador intentará usar el sistema simplemente siguiendo los requisitos, proporcionando diferentes entradas y probando las salidas generadas. Esta prueba también se conoce como prueba de caja cerrada o caja negra.
Prueba de aceptación : esta es la última prueba que se realiza antes de que el software se entregue al cliente. Se lleva a cabo para garantizar que el software desarrollado cumpla con todos los requisitos del cliente. Existen dos tipos de pruebas de aceptación: una realizada por los miembros del equipo de desarrollo, conocida como prueba de aceptación interna (prueba Alpha), y la otra realizada por el cliente o usuario final conocida como (Prueba Beta)
Pruebas de integración : los módulos individuales que ya están sujetos a pruebas unitarias se integran entre sí. En general, se siguen los dos enfoques:
1) de arriba abajo
2) de abajo hacia arriba