Pregunta

Cuando me presentaron originalmente Mocks, sentí que el propósito principal era simular objetos que provienen de fuentes externas de datos.De esta manera no tenía que mantener una base de datos de pruebas unitarias automatizada, simplemente podía falsificarla.

Pero ahora estoy empezando a pensar en ello de otra manera.Me pregunto si los simulacros son más efectivos para aislar completamente el método probado de cualquier cosa externa a él.La imagen que me viene a la mente es el fondo que utilizas al pintar.Quieres evitar que la pintura se manche por todas partes.Sólo estoy probando ese método y sólo quiero saber cómo reacciona a estos factores externos falsos.

Parece increíblemente tedioso hacerlo de esta manera pero la ventaja que estoy viendo es que cuando la prueba falla es porque está jodida y no 16 capas hacia abajo.Pero ahora tengo que realizar 16 pruebas para obtener la misma cobertura de prueba porque cada pieza se probaría de forma aislada.Además, cada prueba se vuelve más complicada y más profundamente ligada al método que se está probando.

Me parece bien, pero también me parece brutal, así que quiero saber qué piensan los demás.

¿Fue útil?

Solución

Te recomiendo que eches un vistazo al artículo de Martin Fowler. Los simulacros no son talones para un tratamiento más autorizado de Mocks del que puedo darle.

El propósito de las simulaciones es realizar pruebas unitarias de su código de forma aislada de las dependencias para que realmente pueda probar un fragmento de código en el nivel de "unidad".El código bajo prueba es real, y cualquier otro fragmento de código en el que se basa (a través de parámetros o inyección de dependencia, etc.) es una "simulacro" (una implementación vacía que siempre devuelve valores esperados cuando se llama a uno de sus métodos).

Los simulacros pueden parecer tediosos al principio, pero hacen que las pruebas unitarias sean mucho más fáciles y sólidas una vez que aprendes a usarlos.La mayoría de los lenguajes tienen bibliotecas simuladas que hacen que la burla sea relativamente trivial.Si estás usando Java, te recomendaré mi favorito personal: Fácil Mock.

Permítanme terminar con este pensamiento:también necesita pruebas de integración, pero tener un buen volumen de pruebas unitarias le ayuda a descubrir qué componente contiene un error, cuando existe.

Otros consejos

No sigas el camino oscuro, Maestro Luke.:) No te burles de todo.Podrías pero no deberías...este es el por qué.

  • Si continúa probando cada método de forma aislada, tendrá sorpresas y trabajo por delante cuando los reúna todos desde el principio. BIG BANG.Construimos objetos para que puedan trabajar juntos para resolver un problema mayor.Por sí solos son insignificantes.Tú Necesito saber si todos los colaboradores están trabajando como se esperaba..
  • se burla hacer que las pruebas sean frágiles introduciendo duplicaciones. Sí, ya sé que suena alarmante.Por cada simulación simulada que configure, hay n lugares donde existe la firma de su método.El código real y sus expectativas simuladas (en múltiples pruebas).Cambiar el código real es más fácil...Actualizar todas las expectativas simuladas es tedioso.
  • Su La prueba ahora tiene acceso a información interna de implementación..Entonces su prueba depende de cómo eligió implementar la solución...malo.Las pruebas deben ser una especificación independiente que puedan cumplir múltiples soluciones.Debería tener la libertad de simplemente presionar eliminar en un bloque de código y volver a implementarlo. sin tener que reescribir el conjunto de pruebas.Porque los requisitos siguen siendo los mismos.

Para terminar, diré "Si grazna como un pato, camina como un pato, entonces probablemente sea un pato". Si se siente mal...probablemente lo sea.*Utilice simulaciones para abstraer problemas secundarios como operaciones IO, bases de datos, componentes de terceros y similares.Al igual que la sal, un poco es necesaria.demasiado y :x *
Esta es la guerra santa entre las pruebas basadas en el estado y las basadas en la iteración.Buscar en Google le dará una visión más profunda.

Aclaración:Estoy encontrando cierta resistencia.pruebas de integración aquí :) Entonces, para aclarar mi posición ...

  • Los simulacros no figuran en el ámbito de 'Pruebas de aceptación'/Integración.Solo los encontrarás en el mundo de Unit Testing.y ese es mi enfoque aquí.
  • Las pruebas de aceptación son diferentes y son mucho necesarios, sin menospreciarlos.Pero las pruebas unitarias y las pruebas de aceptación son diferentes y deben mantenerse diferentes.
  • No es necesario aislar a todos los colaboradores dentro de un componente o paquete entre sí.Como la microoptimización, eso es excesivo.Existen para resolver un problema. juntos..cohesión.

Sí estoy de acuerdo.Veo la burla como a veces dolorosa, pero muchas veces necesaria, para que tus pruebas se conviertan verdaderamente en unidad pruebas, es decirsólo se está probando la unidad más pequeña con la que puede realizar la prueba.Esto le permite eliminar cualquier otro factor que pueda afectar el resultado de la prueba.Terminas con muchas más pruebas pequeñas, pero se vuelve mucho más fácil determinar dónde está el problema con tu código.

Mi filosofía es que debes escribir código comprobable que se ajuste a las pruebas,
No escribir pruebas que se ajusten al código.

En cuanto a la complejidad, mi opinión es que las pruebas deberían ser fáciles de escribir, simplemente porque se escriben más pruebas si lo son.

Podría estar de acuerdo en que podría ser una buena idea si las clases de las que te estás burlando no tienen un conjunto de pruebas, porque si tuvieran un conjunto de pruebas adecuado, sabrías dónde está el problema sin aislamiento.

La mayoría de las veces que he usado objetos simulados es cuando el código para el que estoy escribiendo pruebas está tan estrechamente acoplado (lea:mal diseño), que tengo que escribir objetos simulados cuando las clases de las que dependen no están disponibles.Seguro que hay usos válidos para objetos simulados, pero si tu código requiere su uso, echaría otro vistazo al diseño.

Sí, esa es la desventaja de realizar pruebas con simulacros.Hay mucho trabajo que debes hacer y se siente brutal.Pero esa es la esencia de las pruebas unitarias.¿Cómo puedes probar algo de forma aislada si no te burlas de los recursos externos?

Por otro lado, te estás burlando de la funcionalidad lenta (como bases de datos y operaciones de E/S).Si las pruebas se ejecutan más rápido, eso mantendrá contentos a los programadores.No hay nada mucho más doloroso que esperar pruebas realmente lentas, que tardan más de 10 segundos en terminar de ejecutarse, mientras intentas implementar una característica.

Si cada desarrollador de su proyecto dedicara tiempo a escribir pruebas unitarias, entonces esas 16 capas (de direccionamiento indirecto) no serían un gran problema.Ojalá deberías tener esa cobertura de prueba desde el principio, ¿verdad?:)

Además, no olvide escribir una prueba de función/integración entre objetos en colaboración.De lo contrario, podría perderse algo.No será necesario realizar estas pruebas con frecuencia, pero siguen siendo importantes.

En una escala, sí, los simulacros están destinados a simular fuentes de datos externas, como una base de datos o un servicio web.Sin embargo, en una escala más detallada, si está diseñando código débilmente acoplado, puede dibujar líneas a lo largo de su código casi arbitrariamente en cuanto a lo que en cualquier momento podría ser un "sistema externo".Tome un proyecto en el que estoy trabajando actualmente:

Cuando alguien intenta registrarse, el CheckInUi envía un Información de registro objetar a un CheckInMediador objeto que lo valida mediante un CheckInValidador, luego, si está bien, llena un objeto de dominio llamado Transacción con Información de registro usando CheckInInfoAdapter luego pasa el Transacción a una instancia de ITransactionDao.SaveTransaction() por la persistencia.

Ahora mismo estoy escribiendo algo automatizado. pruebas de integracion y obviamente el CheckInUi y ITransactionDao son ventanas a sistemas externos y son de ellos de los que hay que burlarse.Sin embargo, ¿quién puede decir que en algún momento? CheckInValidador ¿No harás una llamada a un servicio web?Por eso cuando escribes pruebas unitarias asumes que todo lo que no sea la funcionalidad específica de tu clase es un sistema externo.Por lo tanto en mi prueba unitaria de CheckInMediador Me burlo de todos los objetos con los que habla.

EDITAR: Gishu es técnicamente correcto, no es necesario burlarse de todo, yo, por ejemplo, no me burlo. Información de registro ya que es simplemente un contenedor de datos.Sin embargo, cualquier cosa que pueda verse como un servicio externo (y es casi cualquier cosa que transforme datos o tenga efectos secundarios) debe ser objeto de burla.

Una analogía que me gusta es pensar en un diseño adecuadamente acoplado libremente como un campo con gente parada a su alrededor jugando a atrapar.Cuando a alguien se le pasa la pelota, puede lanzar una pelota completamente diferente a la siguiente persona, incluso puede lanzar varias pelotas en sucesión a diferentes personas o lanzar una pelota y esperar a recibirla antes de tirársela a otra persona.Es un juego extraño.

Ahora, como su entrenador y manager, por supuesto quieres comprobar cómo funciona tu equipo en conjunto para poder practicar en equipo (pruebas de integración), pero también puedes hacer que cada jugador practique por su cuenta contra los respaldos y las máquinas de lanzamiento de pelotas (pruebas unitarias con burlas).La única pieza que falta en esta imagen son las expectativas simuladas, por lo que tenemos nuestras bolas untadas con alquitrán negro para que manchen el respaldo cuando lo golpean.Cada respaldo tiene un "área objetivo" a la que apunta la persona y si al final de una carrera de práctica no hay ninguna marca negra dentro del área objetivo, sabrá que algo anda mal y que la persona necesita afinar su técnica.

Realmente tómate el tiempo para aprenderlo correctamente, el día que entendí Mocks fue un gran momento.Combínelo con una inversión del contenedor de control y nunca volveré atrás.

Como nota al margen, uno de nuestro personal de TI acaba de llegar y me regaló una computadora portátil.

Como alguien dijo antes, si se burla de todo para aislar una clase más granular que la que está probando, dejará de imponer la cohesión en el código que está bajo prueba.

Hay que tener en cuenta que burlarse tiene una ventaja fundamental, la verificación de la conducta.Esto es algo que los resguardos no proporcionan y es la otra razón que hace que la prueba sea más frágil (pero puede mejorar la cobertura del código).

Los simulacros se inventaron en parte para responde la pregunta:¿Cómo realizarías pruebas unitarias de objetos si no tuvieran captadores ni definidores?

Estos días, recomendado La práctica es burlarse de roles, no de objetos.Utilice Mocks como herramienta de diseño para hablar sobre colaboración y separación de responsabilidades, y no como "talones inteligentes".

Los objetos simulados 1) se utilizan a menudo como un medio para aislar el código bajo prueba, PERO 2) como ya señaló Keithb, son importantes para "Centrarse en las relaciones entre objetos que colaboran.".Este artículo brinda algunas ideas e historia relacionadas con el tema: Diseño impulsado por la responsabilidad con objetos simulados.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top