La diferencia clave, para mí, es que las pruebas de integración revelan si una característica está funcionando o está rota, 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 esperaba.
Por el contrario, una prueba unitaria que prueba un único método se basa en la suposición (a menudo incorrecta) de que el resto del software funciona correctamente, ya que explícitamente se burla de cada dependencia.
Por lo tanto, cuando una prueba unitaria para un método que implementa alguna característica es verde, no significa que la característica esté funcionando.
Digamos que tiene 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 generalmente escribe una especificación de Pepino afirmando: desea verificar y comunicar que la función 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
Sin duda: si la prueba pasa, puede afirmar que está entregando una función de trabajo. Esto es lo que puede llamar valor comercial .
Si desea escribir una prueba unitaria para DoSomething
usted, debe fingir (usando algunas simulaciones) que el resto de las clases y métodos están funcionando (es decir, que todas las dependencias que el método está usando funcionan 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 la Inyección de dependencia, o con 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 de Gherkin lo encontrará y sus pruebas de punta a punta 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 la única responsabilidad de ese método.
Además, suponga que Log
se usa en otras 100 características, en otros 100 métodos de otras 100 clases.
Sí, 100 funciones fallarán. Pero, afortunadamente, 100 pruebas de extremo a extremo también fallan y revelan el problema. Y sí: dicen la verdad .
Es información muy útil: sé que tengo un producto roto. También es 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 de la unidad es verde, porque está usando un falso Log
, construido para nunca romperse. Y sí: claramente está mintiendo . Está comunicando que una característica rota funciona. ¿Cómo puede ser útil?
(Si DoSomething()
la prueba de la unidad falla, asegúrese de [Do your job with someInput]
tener algunos errores).
Supongamos que este es un sistema con una clase rota:
Un solo error romperá varias características y varias pruebas de integración fallarán.
Por otro lado, el mismo error romperá solo una prueba de unidad.
Ahora, compara los dos escenarios.
El mismo error romperá solo una prueba de unidad.
- Todas tus características que usan el roto
Log
son rojas
- Todas las pruebas unitarias son verdes, solo la prueba unitaria
Log
es roja
En realidad, las pruebas unitarias para todos los módulos que usan una función rota son verdes porque, al usar simulacros, eliminaron las dependencias. En otras palabras, corren en un mundo ideal, completamente ficticio. Y esta es la única forma de aislar errores y buscarlos. Prueba de unidad significa burlarse. Si no te estás burlando, no estás haciendo pruebas unitarias.
La diferencia
Las pruebas de integración indican lo que no funciona. Pero no sirven para adivinar dónde podría estar el problema.
Las pruebas unitarias son las únicas pruebas que le dicen dónde está exactamente el error. Para extraer esta información, deben ejecutar el método en un entorno simulado, donde se supone que todas las demás dependencias funcionan correctamente.
Es por eso que creo que su oración "¿O es solo 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 .
Cuando escribo pruebas unitarias, limito el alcance del código que se está probando a la clase que estoy escribiendo actualmente burlándose de las dependencias. Si estoy escribiendo una clase de Oración, y la Oración depende de Word, usaré una Palabra simulada. Al burlarme de Word, puedo concentrarme solo en su interfaz y probar los diversos comportamientos de mi clase de oración mientras interactúa con la interfaz de Word. De esta manera solo estoy probando el comportamiento y la implementación de Sentence y no al mismo tiempo probando la implementación de Word.
Una vez que he escrito las pruebas unitarias para asegurar que Sentence se comporta correctamente cuando interactúa con Word basado en la interfaz de Word, entonces escribo la prueba de integración para asegurarme de que mis suposiciones sobre las interacciones eran correctas. Para esto proporciono los objetos reales y escribo una prueba que ejercita una característica que terminará usando tanto Oración como Palabra.
fuente
Mis 10 bits: D
Siempre me dijeron que Unit Tests es la prueba de un componente individual , que debe ejercerse al máximo. Ahora, esto tiende a tener muchos niveles, ya que la mayoría de los componentes están hechos de partes más pequeñas. Para mí, una unidad es una parte funcional del sistema. Por lo tanto, tiene que proporcionar algo de valor (es decir, no un método para analizar cadenas, sino un HtmlSanitizer ).
Las Pruebas de integración son el siguiente paso: tomar uno o más componentes y asegurarse de que funcionen juntos como deberían. Entonces está por encima de las complejidades de la preocupación sobre cómo funcionan los componentes individualmente, pero cuando ingresa html en su HtmlEditControl , de alguna manera sabe mágicamente si es válido o no ...
Sin embargo, es una línea móvil real ... Prefiero centrarme más en hacer que el maldito código funcione por completo ^ _ ^
fuente
Las pruebas unitarias usan simulacros
De lo que estás hablando es de pruebas de integración que realmente prueban toda la integración de tu sistema. Pero cuando realiza pruebas unitarias, debe probar cada unidad por separado. Todo lo demás debe ser burlado. Entonces, en su caso de
Sentence
clase, si usaWord
clase, entonces suWord
clase debe ser burlada. De esta manera, solo probará laSentence
funcionalidad de su clase.fuente
Creo que cuando empiezas a pensar en las pruebas de integración, estás hablando más de un cruce entre capas físicas en lugar de capas lógicas.
Por ejemplo, si sus pruebas se preocupan por generar contenido, es una prueba unitaria: si su prueba se refiere solo a escribir en el disco, sigue siendo una prueba unitaria, pero una vez que prueba tanto la E / S como el contenido del archivo, entonces tienes una prueba de integración. Cuando prueba la salida de una función dentro de un servicio, es una prueba unitaria, pero una vez que realiza una llamada de servicio y ve si el resultado de la función es el mismo, entonces es una prueba de integración.
Técnicamente, de todos modos, no puede probar la unidad solo una clase. ¿Qué pasa si su clase está compuesta con varias otras clases? ¿Eso lo convierte automáticamente en una prueba de integración? No lo creo.
fuente
usando el diseño de responsabilidad individual, es blanco y negro. Más de 1 responsabilidad, es una prueba de integración.
Según la prueba del pato (apariencia, graznidos, waddles, es un pato), es solo una prueba unitaria con más de 1 objeto nuevo.
Cuando ingresa a mvc y lo prueba, las pruebas del controlador son siempre de integración, porque el controlador contiene tanto una unidad modelo como una unidad de vista. Probando la lógica en ese modelo, llamaría una prueba unitaria.
fuente
La naturaleza de tus pruebas
Una prueba unitaria del módulo X es una prueba que espera (y busca) problemas solo en el módulo X.
Una prueba de integración de muchos módulos es una prueba que espera problemas que surjan de la cooperación entre los módulos, de modo que estos problemas serían difíciles de encontrar usando solo pruebas unitarias.
Piense en la naturaleza de sus pruebas en los siguientes términos:
Recuerde que una prueba de integración aún puede eliminar algunas de sus dependencias. Esto proporciona mucho terreno intermedio entre las pruebas unitarias y las pruebas del sistema (las pruebas de integración más completas, que prueban todo el sistema).
Enfoque pragmático para usar ambos
Por lo tanto, un enfoque pragmático sería: confiar de manera flexible en las pruebas de integración tanto como sea posible y usar pruebas unitarias donde esto sería demasiado arriesgado o inconveniente. Esta forma de pensar puede ser más útil que alguna discriminación dogmática de las pruebas unitarias y las pruebas de integración.
fuente
En la prueba unitaria, prueba cada parte aislada:
en la prueba de integración, prueba muchos módulos de su sistema:
y esto es lo que sucede cuando solo usas pruebas unitarias (generalmente ambas ventanas funcionan, desafortunadamente no juntas):
Fuentes: Source1 source2
fuente
En mi opinión, la respuesta es "¿Por qué es importante?"
¿Es porque las pruebas unitarias son algo que haces y las pruebas de integración son algo que no haces? ¿O viceversa? Por supuesto que no, debes intentar hacer ambas cosas.
¿Es porque las pruebas unitarias deben ser rápidas, aisladas, repetibles, autovalidables y oportunas y las pruebas de integración no deberían? Por supuesto que no, todas las pruebas deberían ser estas.
¿Es porque usas simulacros en pruebas unitarias pero no los usas en pruebas de integración? Por supuesto no. Esto implicaría que si tengo una prueba de integración útil, no tengo permitido agregar un simulacro por alguna parte, por temor a tener que cambiar el nombre de mi prueba a "prueba unitaria" o entregarla a otro programador para que trabaje.
¿Es porque las pruebas unitarias prueban una unidad y las pruebas de integración prueban varias unidades? Por supuesto no. ¿De qué importancia práctica es eso? La discusión teórica sobre el alcance de las pruebas se rompe en la práctica de todos modos porque el término "unidad" depende completamente del contexto. A nivel de clase, una unidad puede ser un método. A nivel de ensamblaje, una unidad podría ser una clase, y en el nivel de servicio, una unidad podría ser un componente. E incluso las clases usan otras clases, entonces, ¿cuál es la unidad?
No tiene importancia.
Las pruebas son importantes, PRIMERO es importante, dividir los pelos sobre las definiciones es una pérdida de tiempo que solo confunde a los recién llegados a las pruebas.
fuente
Creo que todavía llamaría a un par de clases interactuantes una prueba unitaria siempre que las pruebas unitarias para la clase1 estén probando las características de la clase1, y las pruebas unitarias para la clase2 estén probando sus características, y también que no estén llegando a la base de datos.
Llamo a una prueba una prueba de integración cuando se ejecuta en la mayor parte de mi pila e incluso llega a la base de datos.
Realmente me gusta esta pregunta, porque la discusión TDD a veces me parece demasiado purista, y es bueno para mí ver algunos ejemplos concretos.
fuente
Hago lo mismo: las llamo todas las pruebas unitarias, pero en algún momento tengo una "prueba unitaria" que cubre tanto que a menudo lo renombro como ".. Prueba de integración", solo un cambio de nombre, nada más cambia.
Creo que hay una continuación de las "pruebas atómicas" (prueba de una clase pequeña o un método) a las pruebas unitarias (nivel de clase) y las pruebas de integración, y luego la prueba funcional (que normalmente cubre muchas más cosas de arriba hacia abajo) - No parece haber un corte limpio.
Si su prueba configura datos, y tal vez carga una base de datos / archivo, etc., entonces tal vez sea más una prueba de integración (las pruebas de integración que encuentro usan menos simulacros y más clases reales, pero eso no significa que no pueda burlarse de algunos del sistema).
fuente
Las pruebas unitarias son un método de prueba que verifica que las unidades individuales del código fuente funcionan correctamente.
La Prueba de integración es la fase de prueba de software en la que los módulos de software individuales se combinan y prueban como un grupo.
Wikipedia define una unidad como la parte comprobable más pequeña de una aplicación, que en Java / C # es un método. Pero en su ejemplo de la clase de palabras y oraciones, probablemente solo escribiría las pruebas para la oración, ya que probablemente me resultaría excesivo usar una clase de palabras simuladas para probar la clase de oraciones. Entonces, la oración sería mi unidad y la palabra es un detalle de implementación de esa unidad.
fuente
Pruebas de integración: se prueba la persistencia de la base de datos.
Pruebas unitarias: se burla el acceso a la base de datos. Los métodos de código son probados.
fuente
Las pruebas unitarias son pruebas contra una unidad de trabajo o un bloque de código si lo desea. Generalmente realizado por un solo desarrollador.
Las pruebas de integración se refieren a la prueba que se realiza, preferiblemente en un servidor de integración, cuando un desarrollador confirma su código en un repositorio de control de origen. Las pruebas de integración pueden ser realizadas por utilidades como Cruise Control.
Entonces, realiza la prueba de la unidad para validar que la unidad de trabajo que ha creado funciona y luego la prueba de integración valida que lo que haya agregado al repositorio no haya roto otra cosa.
fuente
Llamo pruebas unitarias a esas pruebas que la caja blanca prueba una clase. Cualquier dependencia que requiera la clase se reemplaza por una falsa (simulacro).
Las pruebas de integración son aquellas donde se prueban varias clases y sus interacciones al mismo tiempo. Solo algunas dependencias en estos casos son falsificadas / burladas.
No llamaría a las pruebas de integración de Controller a menos que una de sus dependencias sea real (es decir, no falsa) (por ejemplo, Autenticación IForms).
Separar los dos tipos de pruebas es útil para probar el sistema en diferentes niveles. Además, las pruebas de integración tienden a ser de larga duración, y se supone que las pruebas unitarias son rápidas. La distinción de velocidad de ejecución significa que se ejecutan de manera diferente. En nuestros procesos de desarrollo, las pruebas unitarias se ejecutan en el check-in (lo cual está bien porque son súper rápidas), y las pruebas de integración se ejecutan una / dos veces por día. Intento ejecutar las pruebas de integración tan a menudo como sea posible, pero generalmente golpeo la base de datos / escribo en los archivos / hago que los rpc / etc sean más lentos.
Eso plantea otro punto importante, las pruebas unitarias deben evitar golpear IO (por ejemplo, disco, red, base de datos). De lo contrario, se ralentizan mucho. Se necesita un poco de esfuerzo para diseñar estas dependencias de E / S: no puedo admitir que he sido fiel a la regla de "las pruebas unitarias deben ser rápidas", pero si lo es, los beneficios en un sistema mucho más grande se hacen evidentes muy rápidamente. .
fuente
Explicación simple con analogías
Los ejemplos anteriores funcionan muy bien y no necesito repetirlos. Así que me enfocaré en usar ejemplos para ayudarlo a comprender.
Pruebas de integración
Las pruebas de integración verifican si todo funciona en conjunto. Imagine una serie de engranajes trabajando juntos en un reloj. Una prueba de integración sería: ¿el reloj indica la hora correcta? ¿Sigue diciendo la hora correcta en 3 días?
Todo lo que te dice es si la pieza en general está funcionando. Si falla: no te dice exactamente dónde está fallando.
Pruebas unitarias
Estos son tipos de prueba realmente específicos. Te dicen si una cosa específica está funcionando o no. La clave de este tipo de prueba es que solo prueba una cosa específica mientras se supone que todo lo demás está funcionando bien. Ese es el punto clave.
Ejemplo: desarrollemos este punto usando un ejemplo:
Usando trozos
Suponga que la prueba de integración de su auto falla. No conduce con éxito a Echuca. ¿Dónde está el problema?
Ahora supongamos que su motor utiliza un sistema especial de inyección de combustible y que esta prueba de la unidad del motor también ha fallado. En otras palabras, tanto la prueba de integración como la prueba de la unidad del motor han fallado. ¿Dónde está entonces el problema? (Tómese 10 segundos para obtener la respuesta).
¿Es el problema con el motor o con el sistema de inyección de combustible?
¿Ves el problema aquí? No sabes exactamente qué está fallando. Si usa diferentes dependencias externas, entonces cada una de esas 10 podría haber causado el problema, y no sabrá por dónde empezar. Es por eso que las pruebas unitarias usan talones para suponer que todo lo demás está funcionando bien.
fuente
Un poco académico esta pregunta, ¿no? ;-) Mi punto de vista: para mí, una prueba de integración es la prueba de toda la parte, no si dos de cada diez van juntas. Nuestra prueba de integración muestra si la compilación maestra (que contiene 40 proyectos) tendrá éxito. Para los proyectos tenemos toneladas de pruebas unitarias. Lo más importante con respecto a las pruebas unitarias para mí es que una prueba unitaria no debe depender de otra prueba unitaria. Entonces, para mí, ambas pruebas que describe arriba son pruebas unitarias, si son independientes. Para las pruebas de integración esto no necesita ser importante.
fuente
Pienso que sí y sí. Su prueba de unidad que abarca 2 clases se convirtió en una prueba de integración.
Puede evitarlo probando la clase Sentence con implementación simulada: clase MockWord, que es importante cuando esas partes del sistema son lo suficientemente grandes como para ser implementadas por diferentes desarrolladores. En ese caso, Word se prueba solo en unidad, Sentence se prueba en unidad con la ayuda de MockWord y luego Sentence se prueba en integración con Word.
Se puede seguir un ejemplo de diferencia real 1) La matriz de 1,000,000 de elementos se prueba fácilmente en unidades y funciona bien. 2) BubbleSort se prueba fácilmente en unidades en una matriz simulada de 10 elementos y también funciona bien 3) Las pruebas de integración muestran que algo no está tan bien.
Si estas partes son desarrolladas por una sola persona, lo más probable es que se encuentren problemas al probar BubbleSoft solo porque el desarrollador ya tiene una matriz real y no necesita una implementación simulada.
fuente
Además, es importante recordar que tanto las pruebas unitarias como las pruebas de integración se pueden automatizar y escribir utilizando, por ejemplo, JUnit. En las pruebas de integración JUnit, se puede usar la
org.junit.Assume
clase para probar la disponibilidad de elementos del entorno (por ejemplo, conexión de base de datos) u otras condiciones.fuente
Si eres un purista de TDD, escribes las pruebas antes de escribir el código de producción. Por supuesto, las pruebas no se compilarán, por lo que primero debe compilar las pruebas, luego hacer que las pruebas pasen.
Puede hacer esto con pruebas unitarias, pero no puede hacerlo con pruebas de integración o aceptación. Si intentara con una prueba de integración, ¡nada se compilaría hasta que haya terminado!
fuente