¿Cuál es la diferencia entre pruebas unitarias, funcionales, de aceptación y de integración? [cerrado]
¿Cuál es la diferencia entre pruebas unitarias, funcionales, de aceptación y de integración (y cualquier otro tipo de prueba que no mencioné)?
Dependiendo de dónde mires, obtendrás respuestas ligeramente diferentes. He leído mucho sobre el tema y aquí está mi destilación; Nuevamente, estos son ligeramente lanudos y otros pueden no estar de acuerdo.
Pruebas unitarias
Prueba la unidad más pequeña de funcionalidad, normalmente un método/función (por ejemplo, dada una clase con un estado particular, llamar al método x en la clase debería provocar que suceda y). Las pruebas unitarias deben centrarse en una característica particular (por ejemplo, llamar al método pop cuando la pila está vacía debería arrojar un 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 deberían:
- Llame a colaboradores (no triviales)
- Acceder a la red
- Golpear una base de datos
- Utilice el sistema de archivos
- Girar un hilo
- etc.
Cualquier tipo de dependencia que sea lenta / difícil de entender / inicializar / manipular debe eliminarse/burlarse/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 la reducción de factores externos), rápidas de ejecutar y ayudan a demostrar que los componentes más pequeños de su programa funcionan según lo previsto antes de ensamblarlos. 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. Puede tratarse de las entrañas de un sistema o de 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 utilizar y utilizarán subprocesos, accederán a la base de datos o harán lo que sea necesario para garantizar que todo el código y los diferentes cambios del entorno funcionen 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 esté cargando y guardando en el disco? Quizás olvidó vaciar y desechar los flujos de archivos. Tal vez los permisos de sus archivos sean incorrectos y haya probado las entrañas usando flujos de memoria. La única forma de saberlo con seguridad es probarlo "realmente" utilizando un entorno más cercano a la producción.
La principal ventaja es que encontrarán errores que las pruebas unitarias no pueden detectar, 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. Puede que al usuario no le importen los detalles internos de mis programas, ¡pero a mí sí!
Pruebas funcionales
Las pruebas funcionales verifican la corrección de una característica particular 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). Están escritos para probar parte de la especificación, como "llamar a la función Square(x) con el argumento 2 devuelve 4".
Prueba de aceptacion
Las pruebas de aceptación parecen dividirse en dos tipos:
Las pruebas de aceptación estándar implican realizar pruebas en todo el sistema (por ejemplo, usando su página web a través de un navegador web) para ver si la funcionalidad de la aplicación satisface la especificación. Por ejemplo, "hacer clic en un icono de zoom debería ampliar la vista del documento en un 25%". No existe una continuidad real de resultados, sólo un resultado de aprobación o fracaso.
La ventaja es que las pruebas se describen en un inglés sencillo y garantiza que el software, en su conjunto, tenga todas las funciones. La desventaja es que ha subido otro nivel en la pirámide de pruebas. Las pruebas de aceptación tocan montañas de código, por lo que rastrear una falla puede ser complicado.
Además, en el desarrollo ágil de software, las pruebas de aceptación del usuario implican la creación de pruebas que reflejen 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 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 de dominio que describe las pruebas en el lenguaje utilizado por los usuarios del sistema.
Conclusión
Todos son complementarios. A veces es ventajoso centrarse en un tipo o evitarlo por completo. La principal diferencia para mí es que algunas de las pruebas analizan las cosas desde la perspectiva de un programador, mientras que otras utilizan un enfoque de cliente/usuario final.
Lo importante es que sepas qué significan esos términos para tus compañeros. Los diferentes grupos tendrán definiciones ligeramente diferentes de lo que quieren decir cuando dicen pruebas "completas de extremo a extremo", por ejemplo.
Recientemente me encontré con el sistema de nombres de Google para sus pruebas y me gusta bastante: omiten los argumentos simplemente usando Pequeño, Mediano y Grande. Para decidir en qué categoría encaja una prueba, analizan algunos factores: cuánto tiempo tarda en ejecutarse, si accede a la red, a la base de datos, al sistema de archivos, a 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 podría variar respecto al de Google.
Sin embargo, no se trata sólo de alcance, sino de propósito. El punto de Mark sobre las diferentes perspectivas para las pruebas, por ejemplo, programador versus cliente/usuario final, es realmente importante.
http://martinfowler.com/articles/microservice-testing/
La publicación del blog de Martin Fowler habla sobre estrategias para probar código (especialmente en una arquitectura de microservicios), pero la mayor parte se aplica a cualquier aplicación.
Citaré su diapositiva de resumen:
- Pruebas unitarias: ejercite las piezas más pequeñas de software comprobable en la aplicación para determinar si se comportan como se esperaba.
- Pruebas de integración: verifique las rutas de comunicación y las interacciones entre componentes para detectar defectos en la interfaz.
- Pruebas de componentes: limite el alcance del software ejercido a una parte del sistema bajo prueba, manipulando el sistema a través de interfaces de código interno y usando dobles de prueba para aislar el código bajo prueba de otros componentes.
- Pruebas de contrato: verificar 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: verifica 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 el nombre, este método prueba a nivel de objeto. Los componentes de software individuales se prueban para detectar errores. Se necesita conocimiento del programa para esta prueba y los códigos de prueba se crean para verificar si el software se comporta como está previsto.
Pruebas funcionales : se llevan a cabo sin ningún conocimiento del funcionamiento interno del sistema. El evaluador intentará utilizar 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 de caja negra.
Prueba de aceptación : esta es la última prueba que se realiza antes de entregar el software al cliente. Se lleva a cabo para garantizar que el software desarrollado cumpla con todos los requisitos del cliente. Hay dos tipos de pruebas de aceptación: una que llevan a cabo los miembros del equipo de desarrollo, conocida como pruebas de aceptación internas (pruebas Alfa), y la otra que lleva a cabo el cliente o usuario final conocida como (pruebas Beta).
Pruebas de integración : los módulos individuales que ya están sujetos a pruebas unitarias se integran entre sí. Generalmente se siguen los dos enfoques:
1) De arriba hacia abajo
2) De abajo hacia arriba