Pruebas de unidad: cómo empezar

14

Acabo de comenzar con las pruebas de unidad, pero no estoy seguro de si realmente entiendo el punto de todo esto. Leí tutoriales y libros sobre todo esto, pero solo tengo dos preguntas rápidas:

  1. Pensé que el propósito de las pruebas unitarias es probar el código que escribimos. Sin embargo, a mí me parece que para poder simplemente ejecutar la prueba, debemos modificar el código original, momento en el que no estamos probando realmente el código que escribimos, sino el código que escribimos para las pruebas.

  2. La mayoría de nuestros códigos se basan en fuentes externas. Sin embargo, al refactorizar nuestro código, incluso si se rompe el código original, nuestras pruebas todavía se ejecutarán bien, ya que las fuentes externas son simplemente basura dentro de nuestros casos de prueba. ¿No anula el propósito de las pruebas unitarias?

Perdón si parezco tonto aquí, pero pensé que alguien podría iluminarme un poco.

Gracias de antemano.

    
pregunta treecoder 21.11.2011 - 07:24

5 respuestas

7

Mi 0.02 $ ... esto es un poco subjetivo, así que tómalo con un grano de sal, pero espero que te ayude a pensar y / o provocar un diálogo:

  1. El propósito principal de las pruebas unitarias para mí es garantizar que el código que usted escribió cumple con los contratos y los casos de borde su código es destinado a cumplir. Con pruebas de unidad en su lugar, puede mejor asegúrese de que cuando usted (o alguien más en el futuro) refactorice su Código, cualquier consumidor externo de su código no debe verse afectado. Si tiene cobertura estatal adecuada. (Al menos en la medida en que usted pretender que no se vean afectados.

    En la mayoría de los casos, debería poder escribir código que pueda Ambos se envían a producción y son fácilmente verificables por unidad. Un bien lugar para comenzar puede ser mirar en los patrones de inyección de dependencia y marcos (O otras filosofías para su idioma / plataforma de elección).

  2. Es correcto que las implementaciones externas puedan afectar su código. Sin embargo, asegúrese de que su código funcione correctamente como parte de un El sistema es una función de integración probando. (Que también podría ser automatizado con diversos grados de esfuerzo).

    Lo ideal es que su código solo dependa de los contratos API de cualquier 3er. componentes del partido lo que significaría que, siempre y cuando sus simulacros cumplan La API correcta que tus pruebas de unidad todavía proporcionan valor.

    Dicho esto, admitiré fácilmente que hubo momentos en los que lo hice renuncie a las pruebas unitarias en favor de las pruebas de integración solo, pero eso Solo ha habido casos en los que mi código ha tenido que interactuar tan profusamente con Componentes de terceros con API mal documentadas. (es decir, la excepción en lugar de la regla).

respondido por el Charlie 21.11.2011 - 07:44
5
  1. Intenta escribir tus pruebas primero. De esa manera, tendrás una base sólida. por el comportamiento de su código y su prueba se convierte en un contrato para El comportamiento requerido de su código. Así, cambiando el código para pasar La prueba se convierte en "cambiar el código para cumplir con el contrato propuesto. por la prueba "en lugar de" cambiar el código para pasar la prueba ".
  2. Bueno, ten cuidado con la diferencia entre los talones y las burlas. Siendo no se ve afectado por ningún cambio en el código es el comportamiento característico de talones, pero no burlas. Vamos a empezar con la definición del simulacro:

      

    Un objeto simulado reemplaza un objeto real en condiciones de prueba y permite   Verificación de las llamadas (interacciones) contra sí misma como parte de un sistema.   o prueba de unidad.

         

    -El arte de las pruebas unitarias

Básicamente, sus simulacros deben verificar el comportamiento requerido de sus interacciones. Por lo tanto, si su interacción con la base de datos falla después de una refactorización, su prueba con el simulacro también debería fallar. Por supuesto, esto tiene limitaciones, pero con una planificación cuidadosa, sus simulacros harán mucho más que simplemente "sentarse allí" y no "anularán el propósito de las pruebas unitarias".

    
respondido por el ruhsuzbaykus 21.11.2011 - 10:16
1

Hacer una buena pregunta no es tonto de ninguna manera.

Voy a responder a sus preguntas.

  1. El propósito de la prueba de unidad no es probar el código que ya escribió . No tiene noción de tiempo. Solo en TDD se supone que debe realizar la prueba primero, pero eso no se aplica estrictamente a ningún tipo de prueba de unidad. El punto es poder probar automática y eficientemente su programa en el nivel de clase. Usted hace lo que necesita hacer para llegar allí, incluso si eso significa cambiar el código. Y déjame contarte un secreto: a menudo significa eso.
  2. Cuando escribe una prueba, tiene 2 opciones principales para asegurarse de que su prueba sea correcta:

    • Varíe las entradas para cada prueba
    • Escriba un caso de prueba que garantice que su programa funcione correctamente, y luego escriba un caso de prueba correspondiente que garantice que su programa no funcione como no debería

    Aquí hay un ejemplo:

    TEST(MyTest, TwoPlusTwoIsFour) {
        ASSERT_EQ(4, 2+2);
    }
    
    TEST(MyTest, TwoPlusThreeIsntFour) {
        ASSERT_NE(4, 2+3);
    }
    

    Además de eso, si está probando en unidad la lógica dentro de su (no las bibliotecas de terceros), está perfectamente bien que no lo haga No te preocupes por la ruptura del otro código, mientras que en ese contexto. Básicamente, está probando la forma en que su lógica se ajusta y utiliza las utilidades de terceros, que es un escenario de prueba clásico.

Una vez que haya terminado la prueba a nivel de clase, puede continuar probando la integración entre sus clases (los mediadores, según entiendo) y las bibliotecas de terceros. Estas pruebas se denominan pruebas de integración y no utilizan simulacros, sino implementaciones concretas de todas las clases. ¡Son un poco más lentos, pero siguen siendo muy importantes!

    
respondido por el Yam Marcovic 22.11.2011 - 09:17
1

Parece que tienes una aplicación monolítica que hace todo en void main() , desde el acceso a la base de datos hasta la generación de resultados. Hay varios pasos aquí antes de que pueda comenzar la prueba de unidad adecuada.

1) Encuentre un fragmento de código que haya sido escrito / copiado-pegado más de una vez. Incluso si es sólo string fullName = firstName + " " + lastName . Divida eso en un método, como:

private static string GetFullName (firstName, lastName)
{
    return firstName + " " + lastName;
}

Ahora tienes un código de unidad comprobable, por más trivial que sea. Escribe una prueba unitaria para ello. Enjuague y repita este proceso. Eventualmente, terminarás con una carga de métodos agrupados lógicamente y podrás extraer varias clases de él. La mayoría de estas clases serán verificables.

Como beneficio adicional, una vez que haya extraído varias clases, puede extraer interfaces de ellas y actualizar su programa para hablar con interfaces en lugar de con los objetos en sí. En ese momento, puedes utilizar un marco de burla / aplastamiento (o incluso tus propias falsificaciones hechas a mano) sin cambiar el programa en absoluto. Esto es muy útil una vez que ha extraído las consultas de la base de datos en una clase (o muchas) porque ahora puede falsificar los datos que la consulta debería devolver.

    
respondido por el Bryan Boettcher 22.11.2011 - 17:37
0

Un tipo inteligente dijo "Si es difícil de probar, es probablemente un código incorrecto". Es por eso que no es malo reescribir el código, para poder probarlo de manera unitaria. El código con dependencias externas es MUY DIFÍCIL de probar, representa un error del código y debe evitarse siempre que sea posible, y debe concentrarse en áreas específicas de integración de su código, fx. Clases tipo fachada / pasarela. Esto hará que un cambio en el componente externo sea mucho más fácil de manejar.

    
respondido por el Morten 25.11.2011 - 09:23

Lea otras preguntas en las etiquetas