¿Cuál es la ventaja decisiva de las pruebas unitarias frente a las pruebas de integración?
Eso es una falsa dicotomía.
La prueba de unidad y la prueba de integración tienen dos propósitos similares, pero diferentes. El propósito de las pruebas unitarias es asegurarse de que sus métodos funcionen. En términos prácticos, las pruebas unitarias aseguran que el código cumpla con el contrato descrito en las pruebas unitarias. Esto es evidente en la forma en que se diseñan las pruebas unitarias: establecen específicamente qué se supone que hace el código. y afirma que el código hace eso.
Las pruebas de integración son diferentes. Las pruebas de integración ejercitan la interacción entre los componentes del software. Puede tener componentes de software que pasen todas sus pruebas y aún así no pasen las pruebas de integración porque no interactúan correctamente.
Sin embargo, si las pruebas unitarias tienen una ventaja decisiva, es esta: las pruebas unitarias son mucho más fáciles de configurar y requieren mucho menos tiempo y esfuerzo que las pruebas de integración. Cuando se usan correctamente, las pruebas unitarias fomentan el desarrollo de un código "verificable", lo que significa que el resultado final será más confiable, más fácil de entender y más fácil de mantener. El código verificable tiene ciertas características, como una API coherente, un comportamiento repetible y proporciona resultados que son fáciles de afirmar.
Las pruebas de integración son más difíciles y más costosas, ya que a menudo se necesitan burlas complicadas, configuraciones complejas y afirmaciones difíciles. En el nivel más alto de integración del sistema, imagine que intenta simular la interacción humana en una interfaz de usuario. Sistemas de software completos están dedicados a ese tipo de automatización. Y lo que buscamos es la automatización; las pruebas en humanos no son repetibles, y no se escalan como las pruebas automáticas.
Finalmente, las pruebas de integración no ofrecen garantías sobre la cobertura del código. ¿Cuántas combinaciones de bucles de código, condiciones y ramas está probando con sus pruebas de integración? ¿Realmente sabes? Existen herramientas que puede usar con las pruebas unitarias y los métodos bajo prueba que le indicarán cuánta cobertura de código tiene, y cuál es la complejidad ciclomática de su código. Pero solo funcionan realmente bien en el nivel de método, donde se realizan las pruebas unitarias.
Si sus pruebas cambian cada vez que refactoriza, ese es un problema diferente. Se supone que las pruebas unitarias consisten en documentar lo que hace su software, probar que lo hace y luego demostrar que lo hace de nuevo cuando refactoriza la implementación subyacente. Si su API cambia, o si necesita que sus métodos cambien de acuerdo con un cambio en el diseño del sistema, eso es lo que debe suceder. Si está ocurriendo mucho, considera escribir primero tus pruebas, antes de escribir código. Esto te obligará a pensar en la arquitectura general y te permitirá escribir código con la API ya establecida.
Si pasas mucho tiempo escribiendo pruebas unitarias para códigos triviales como
public string SomeProperty { get; set; }
entonces deberías reexaminar tu enfoque. Se supone que la prueba de unidad prueba el comportamiento de , y no hay ningún comportamiento en la línea de código anterior. Sin embargo, ha creado una dependencia en su código en alguna parte, ya que es casi seguro que esa propiedad será mencionada en otra parte de su código. En lugar de hacerlo, considere la posibilidad de escribir métodos que acepten la propiedad necesaria como un parámetro:
public string SomeMethod(string someProperty);
Ahora su método no tiene ninguna dependencia de algo fuera de sí mismo, y ahora es más comprobable, ya que es completamente autónomo. Por supuesto, no siempre podrás hacer esto, pero mueve tu código en la dirección de ser más comprobable, y esta vez estás escribiendo una prueba de unidad para el comportamiento real .