unitarias tipos software sistema pruebas las integracion funcionales ejemplo desventajas c# asp.net visual-studio unit-testing

c# - tipos - ¿Por qué debería hacer una prueba unitaria y una prueba web(en lugar de solo una prueba web)?



tipos de pruebas de software (12)

Mi posición actual es esta: si pruebo completamente mis aplicaciones ASP.NET usando pruebas web (en mi caso a través de las herramientas de prueba VS.NET''08 y WatiN, tal vez) con cobertura de código y un amplio espectro de datos, no debería tener ninguna Necesito escribir pruebas unitarias individuales, porque mi código será probado junto con la UI a través de todas las capas. La cobertura del código asegurará que estoy accediendo a cada parte funcional del código (o revelando el código no utilizado) y puedo proporcionar datos que cubrirán todas las condiciones razonablemente esperadas.

Sin embargo, si tiene una opinión diferente, me gustaría saber:

  1. Qué beneficio adicional proporciona la prueba unitaria que justifica el esfuerzo de incluirlo en un proyecto (tenga en cuenta que estoy haciendo las pruebas web de todos modos, por lo que en muchos casos, las pruebas unitarias cubrirían el código que las pruebas web ya cubren).

  2. ¿Puedes explicar tus razones en detalle con los ejemplos de concete? Demasiado a menudo veo respuestas como "eso no es para lo que está destinado" o "promueve una mayor calidad", lo que realmente no aborda la cuestión práctica que tengo que enfrentar, que es, cómo puedo justificar, con resultados tangibles, gastar más pruebas de tiempo?


La cobertura del código asegurará que estoy alcanzando cada pieza funcional de código

"Hit" no significa "Prueba"

El problema con solo hacer pruebas web es que solo garantiza que aciertes el código y que parece ser correcto en un nivel alto.

Solo porque cargó la página y no se colgó, no significa que realmente funcione correctamente. Aquí hay algunas cosas que he encontrado donde ''pruebas web'' cubrieron el 100% del código, pero pasaron por alto algunos errores muy serios que las pruebas unitarias no tendrían.

  1. La página se cargó correctamente desde un caché, pero la base de datos real se rompió
  2. La página cargaba cada elemento de la base de datos, pero solo mostraba el primero: parecía estar bien, aunque falló completamente en la producción porque tardaba demasiado.
  3. La página mostraba un número de aspecto válido, que en realidad era incorrecto, pero no fue recogido porque 1000000 es fácil de confundir con 100000
  4. La página muestra un número válido por coincidencia: 10x50 es lo mismo que 25x20, pero uno está INCORRECTO
  5. Se suponía que la página debía agregar una entrada de registro a la base de datos, pero eso no era visible para el usuario, por lo que no se veía.
  6. Se omitió la autenticación para que las pruebas web realmente funcionen, por lo que fallamos un error flagrante en el código de autenticación.

Es fácil encontrar cientos de ejemplos más de cosas como esta.

Necesita ambas pruebas unitarias para asegurarse de que su código realmente hace lo que se supone que debe hacer en un nivel bajo, y luego prueba / integración (que llama web) prueba además de eso, para probar que realmente funciona cuando todas esas pequeñas piezas probadas por unidades están encadenadas juntas.


Casi como lo expresó Dijkstra: las pruebas unitarias solo podían usarse para mostrar que el software tiene defectos, no para demostrar que está libre de defectos. Por lo tanto, en general, tocar cada ruta de código una vez (y obtener una cobertura del 100%) no tiene nada que ver con las pruebas, simplemente ayuda a eliminar el bitrot.

Si lo juegas por el libro, todos los errores serios deberían eliminarse solo después de que haya una prueba unitaria escrita que active ese error. Casualmente, arreglar el error significa que esta unidad de prueba en particular ya no está fallando. En el futuro, esta prueba unitaria verifica que este error en particular permanezca fijo.

Es mucho más fácil escribir una prueba unitaria que desencadena un error en particular que escribir una prueba de extremo a extremo (web) que SÓLO hace eso y no ejecuta montones de código completamente irrelevante en el camino (que también podría fallar y ensuciar) con análisis de causa raíz).


Cuando escriba pruebas unitarias, se verá obligado a escribir su código de una mejor manera. Más débilmente acoplado y más orientado a objetos. Eso conducirá a una mejor arquitectura y un sistema más flexible.

Si escribe pruebas unitarias en un estilo TDD, probablemente no haga tanto código innecesario porque se centrará en pequeños pasos y solo hará lo necesario.

Tendrá más confianza al hacer la refactorización para mejorar su código y aumentar el mantenimiento y reducir el olor del código.

Y la prueba de la unidad en sí misma servirá como documentación exilio de lo que el sistema hace y lo que no hace.

Esos son solo algunos ejemplos de beneficios que noté al aplicar TDD a mi trabajo.


Depende de cómo la arquitectura de la aplicación ASP.NET. Si las páginas web simplemente conectan una capa de lógica de negocios subyacente o una capa de acceso a datos, las pruebas unitarias que funcionan independientemente del modelo de estado ASP.NET son más rápidas para el desarrollador y ejecutadas que las pruebas WaitiN similares.

Recientemente desarrollé un área de una aplicación heredada de ASP.NET, en Visual Studio 2003, con NUnit como marco de prueba. Mientras que las pruebas previas implicaron el trabajo a través de pruebas UI para asegurar que la funcionalidad se implementara correctamente, el 90% de las pruebas ocurrieron sin requerir interacción UI.

El único problema que tuve fue el cálculo del tiempo: una de las tareas se planeó en Trac, ya que demoraba 1 día para la lógica de acceso / lógica de datos, y 2 días para la creación y prueba de UI. Con NUnit corriendo por el acceso a datos / lógica de negocios, el tiempo para esa parte del desarrollo pasó de 1 día a 2 días. El desarrollo de UI se redujo a un solo 1/2 día.

Esto continuó con otras tareas dentro del nuevo módulo que se agrega a la aplicación. Las pruebas de la unidad descubrieron errores más rápido, y de una manera menos dolorosa (para mí) y tengo más confianza en que la aplicación funcionará como se espera. Aún mejor, las pruebas unitarias son muy repetibles, ya que no dependen de ningún rediseño de la IU, por lo que tienden a ser menos frágiles ya que los cambios en el diseño fallan en la compilación, no en el tiempo de ejecución.


Es probable que las pruebas unitarias sean significativamente más rápidas a la vuelta que las pruebas web. Esto es cierto no solo en términos de tiempo de desarrollo (donde puedes probar un método de forma aislada mucho más fácilmente si puedes acceder directamente que si tienes que construir una consulta particular que eventualmente lo afectará, varias capas más adelante) sino también en tiempo de ejecución (ejecutar miles de solicitudes en secuencia llevará más tiempo que ejecutar métodos cortos miles de veces).

Las pruebas unitarias probarán pequeñas unidades de funcionalidad, por lo que cuando fallen, usted debería poder aislar el problema de manera muy fácil.

Además, es mucho más fácil burlar las dependencias con pruebas unitarias que cuando alcanzas la parte frontal completa, a menos que me haya perdido algo realmente genial. (Hace unos años, observé cómo se podían integrar las pruebas de burla y web, y en ese momento no había nada apropiado).


Las pruebas unitarias generalmente no prueban que un determinado conjunto de funcionalidades funcione, al menos no se supone que lo haga. Demuestra que su contrato de clase funciona como espera.

Las pruebas de aceptación están más orientadas según los requisitos del cliente. Todos los requisitos deben tener una prueba de aceptación, pero realmente no existe ningún requisito entre las pruebas de aceptación y las pruebas unitarias, es posible que ni siquiera estén en el mismo marco.

Las pruebas unitarias se pueden usar para impulsar el desarrollo del código, y la velocidad de las nuevas pruebas es un factor importante. Al realizar la prueba, a menudo se eliminan las partes de las que se basa la clase bajo prueba para realizar la prueba de forma aislada.

La aceptación prueba el sistema tal como lo entregaría, desde la GUI a la base de datos. A veces tardan horas o días (o semanas) en ejecutarse.

Si comienzas a pensar en dos bestias completamente diferentes, serás un probador mucho más efectivo.


Las pruebas unitarias le dan velocidad y, sobre todo, la precisión del punto de inserción de donde se ha introducido una falla o error. Le permite probar cada componente, aislado de cualquier otro componente y tener la seguridad de que funciona como debería.

Por ejemplo, si tuvo una prueba web, eso envió una solicitud Ajax a un servicio en el servidor que luego golpeó una base de datos, que luego falla. ¿Fue el Javascript, el servicio, la lógica comercial o la base de datos lo que causó el problema?

Si como unidad prueba cada uno de los servicios por sí mismo, cortando / burlando la base de datos, o cada unidad de lógica de negocios, entonces es más probable que sepa exactamente dónde está el error. Las pruebas unitarias son menos sobre la cobertura (aunque importante) y más sobre el aislamiento.


Las pruebas unitarias le permiten enfocarse en la lógica de obtener datos, aplicar reglas y validar procesos comerciales antes de agregar las complejidades de una interfaz. Para cuando las pruebas unitarias han sido escritas y conducidas, sé que la infraestructura de la aplicación soportará los tipos de datos que paso y vuelta entre procesos, que mis transacciones funcionen adecuadamente, etc.

En otras palabras, los posibles puntos de falla están mejor aislados para el momento en que comienza su prueba de aceptación porque ya ha analizado los posibles errores en su código con las pruebas unitarias. Con el historial de las pruebas unitarias, sabrá que solo ciertos módulos arrojarán ciertos errores. Esto hace que rastrear el código culpable sea mucho más fácil.


Las pruebas unitarias permiten pruebas de rendimiento más rigurosas y hacen que sea mucho más fácil determinar dónde se producen los cuellos de botella. Para aplicaciones grandes, el rendimiento se convierte en un problema importante cuando 10.000 usuarios utilizan un método al mismo tiempo si ese método tarda 1 / 100th de segundo en ejecutarse, quizás debido a una consulta de base de datos mal escrita, porque ahora algunos de los usuarios tienen que espere hasta 10 segundos para que se cargue la página. Sé que personalmente no esperaré tanto para que las páginas se carguen, y me moveré a otro lugar.


Las pruebas unitarias prueban que cada componente funciona. Estos son extremadamente útiles para encontrar defectos cerca del momento en que se crean, lo que reduce drásticamente el costo de corregir defectos y reduce drásticamente la cantidad de defectos que terminan en su versión. Además, las buenas pruebas unitarias hacen que la refactorización sea mucho más fácil y sólida.

Las pruebas de integración (o pruebas "web" en este caso) también son muy importantes, pero son una línea de defensa posterior a las pruebas unitarias. Una sola prueba de integración cubre una franja tan grande de código que, cuando falla, requiere mucha investigación para determinar el defecto (o posiblemente el grupo de defectos) que causó la falla. Esto es costoso, especialmente cuando intentas probar una compilación de lanzamiento para salir por la puerta. Esto es incluso más costoso dado que la posibilidad de introducir un error con el parche tiende a ser bastante alta en promedio y la posibilidad de que el fallo bloquee las pruebas adicionales del lanzamiento (que es extremadamente costoso para el ciclo de desarrollo).

Por el contrario, cuando una prueba de unidad falla, usted sabe exactamente dónde está el código defectuoso y generalmente sabe exactamente qué está haciendo mal el código. Además, una falla en la prueba de la unidad solo debe afectar a un desarrollador a la vez y corregirse antes de que se registre el código.

Siempre es más costoso arreglar errores más tarde que antes. Siempre.

Considera construir un automóvil. ¿Esperaría hasta que todo el vehículo salga de la línea de montaje para probar que cada componente funciona? En ese momento, si descubre que el reproductor de CD o el motor o el aire acondicionado o el control de crucero no funcionan, debe sacar todo el vehículo de la línea, solucionar el problema y luego volver a probar todo (lo que afortunadamente no funciona). revelar cualquier defecto nuevo). Obviamente, esta es la forma incorrecta de hacerlo, así como obviamente es incorrecto intentar liberar el software mientras se prueba solo si funciona al final del proceso en lugar de hacerlo en cada paso importante de la línea desde cero.


Los tests de unidad buenos y enfocados hacen que sea mucho más rápido encontrar y solucionar problemas cuando surgen. Cuando una prueba unitaria bien escrita se rompe, usted sabe más o menos lo que significa la falla y qué la causó.

Además, por lo general, son más rápidos de ejecutar, lo que significa que es mucho más probable que los ejecutes durante el desarrollo como parte de tu ciclo de compilación de compilación de edición (en lugar de solo cuando estás a punto de realizar el check-in).


Un aspecto más: perdona el entorno un tanto ideal en el que se encuentra:

Supongamos que tiene 3 componentes que finalmente tienen que funcionar juntos. Cada uno puede ser probado individualmente por completo (lo que sea que eso signifique) con 5 pruebas unitarias. Esto hace 5 + 5 + 5 = 15 pruebas unitarias para una cobertura completa.

Ahora, si tienes tu prueba de integración / web / combinada que prueba todos los componentes, necesitarías (recuerda el mundo ideal para este escenario abstracto) 5 * 5 * 5 = 125 pruebas que prueban todas las permutaciones para darte el mismo resultado que los 15 casos de prueba anteriores (dado que incluso se pueden activar todas las permutaciones, de lo contrario habría un comportamiento no comprobado / no especificado que podría morderlo más tarde cuando extienda sus componentes).

Además, los 125 casos de prueba tendrían una configuración significativamente más complicada, un tiempo de respuesta más alto y una capacidad de mantenimiento mucho menor si la función cambiara alguna vez. Prefiero optar por 15 pruebas unitarias más algunas pruebas web básicas que aseguran que los componentes estén cableados de forma correcta.