¿Cuál es la diferencia entre integración y pruebas unitarias?
Conozco la llamada definición de libro de texto de pruebas unitarias y pruebas de integración. Lo que tengo curiosidad es cuando llegue el momento de escribir pruebas unitarias... Las escribiré para cubrir tantos conjuntos de clases como sea posible.
Por ejemplo, si tengo una Word
clase, escribiré algunas pruebas unitarias para la Word
clase. Luego, empiezo a escribir mi Sentence
clase, y cuando necesita interactuar con la Word
clase, a menudo escribo mis pruebas unitarias de modo que prueben ambos Sentence
y Word
... al menos en los lugares donde interactúan.
¿Estas pruebas se han convertido esencialmente en pruebas de integración porque ahora prueban la integración de estas 2 clases, o es solo una prueba unitaria que abarca 2 clases?
En general, debido a esta línea incierta, rara vez escribo pruebas de integración... o uso el producto terminado para ver si todas las piezas funcionan correctamente en las pruebas de integración reales, a pesar de que son manuales y rara vez se repiten más allá del alcance. de cada característica individual?
¿Estoy entendiendo mal las pruebas de integración o realmente hay muy poca diferencia entre las pruebas de integración y unitarias?
Para mí, la diferencia clave es que las pruebas de integración revelan si una característica funciona o no funciona, ya que enfatizan el código en un escenario cercano a la realidad. Invocan uno o más métodos o características de software y prueban si actúan como se espera.
Por el contrario, una prueba unitaria que prueba un solo método se basa en la suposición (a menudo errónea) de que el resto del software está funcionando correctamente, porque se burla explícitamente de cada dependencia.
Por lo tanto, cuando una prueba unitaria para un método que implementa alguna característica está en verde, no significa que la característica esté funcionando.
Digamos que tienes un método en algún lugar como este:
public SomeResults DoSomething(someInput) {
var someResult = [Do your job with someInput];
Log.TrackTheFactYouDidYourJob();
return someResults;
}
DoSomething
es muy importante para su cliente: es una característica, lo único que importa. Es por eso que normalmente escribes una especificación de Cucumber afirmando que deseas verificar y comunicar que la característica funciona o no.
Feature: To be able to do something
In order to do something
As someone
I want the system to do this thing
Scenario: A sample one
Given this situation
When I do something
Then what I get is what I was expecting for
No hay duda: si la prueba pasa, puede afirmar que está entregando una función que funciona. Esto es lo que se puede llamar Valor Empresarial .
Si desea escribir una prueba unitaria, DoSomething
debe fingir (usando algunos simulacros) que el resto de las clases y métodos están funcionando (es decir, que todas las dependencias que utiliza el método están funcionando correctamente) y afirmar que su método está funcionando.
En la práctica, haces algo como:
public SomeResults DoSomething(someInput) {
var someResult = [Do your job with someInput];
FakeAlwaysWorkingLog.TrackTheFactYouDidYourJob(); // Using a mock Log
return someResults;
}
Puede hacer esto con Inyección de dependencia, algún método de fábrica o cualquier marco simulado o simplemente extendiendo la clase bajo prueba.
Supongamos que hay un error en Log.DoSomething()
. Afortunadamente, la especificación Gherkin lo encontrará y sus pruebas de un extremo a otro fallarán.
La función no funcionará porque Log
está rota, no porque [Do your job with someInput]
no esté haciendo su trabajo. Y, por cierto, [Do your job with someInput]
es responsabilidad exclusiva de ese método.
Además, supongamos Log
que se usa en otras 100 funciones, en otros 100 métodos de otras 100 clases.
Sí, 100 funciones fallarán. Pero, afortunadamente, 100 pruebas de un extremo a otro también están fallando y revelando el problema. Y sí: están diciendo la verdad .
Es una información muy útil: sé que tengo un producto roto. También es una información muy confusa: no me dice nada sobre dónde está el problema. Me comunica el síntoma, no la causa raíz.
Sin embargo, DoSomething
la prueba unitaria de es verde, porque utiliza una versión falsa Log
, construida para nunca romperse. Y sí: está claramente mintiendo . Está comunicando que una característica rota está funcionando. ¿Cómo puede ser útil?
(Si DoSomething()
la prueba unitaria de ' falla, asegúrese de que [Do your job with someInput]
tenga algunos errores).
Supongamos que este es un sistema con una clase rota:
Un solo error dañará varias funciones y varias pruebas de integración fallarán.
Por otro lado, el mismo error interrumpirá solo una prueba unitaria.
Ahora, compare los dos escenarios.
El mismo error interrumpirá solo una prueba unitaria.
- Todas tus funciones usando el roto
Log
son rojas. - Todas sus pruebas unitarias son verdes, solo la prueba unitaria
Log
es roja
En realidad, las pruebas unitarias para todos los módulos que usan una característica rota son verdes porque, al usar simulaciones, eliminaron las dependencias. En otras palabras, transcurren en un mundo ideal y completamente ficticio. Y ésta es la única manera de aislar errores y buscarlos. Las pruebas unitarias significan burlarse. Si no te estás burlando, no estás realizando pruebas unitarias.
La diferencia
Las pruebas de integración indican qué no funciona. Pero no sirven para adivinar dónde podría estar el problema.
Las pruebas unitarias son las únicas pruebas que le indican dónde está exactamente el error. Para obtener esta información, deben ejecutar el método en un entorno simulado, donde se supone que todas las demás dependencias funcionan correctamente.
Por eso creo que su frase "¿O es sólo una prueba unitaria que abarca 2 clases" está de alguna manera desplazada? Una prueba unitaria nunca debe abarcar 2 clases.
Esta respuesta es básicamente un resumen de lo que escribí aquí: Las pruebas unitarias mienten, por eso las amo .
En la prueba unitaria se prueba cada parte aislada:
En la prueba de integración pruebas muchos módulos de tu sistema:
y esto sucede cuando solo usas pruebas unitarias (generalmente ambas ventanas funcionan, desafortunadamente no juntas):
Fuentes: fuente1 fuente2