¿Cómo escribir una prueba de unidad?

135

Tengo una clase de Java. ¿Cómo puedo probarlo ?


En mi caso, tengo clase hace una suma binaria. Toma dos byte[]matrices, las suma y devuelve una nueva matriz binaria.

Tsundoku
fuente
77
Puede utilizar una herramienta como jUnit y escribir casos de prueba (métodos de prueba) para su clase java. Luego invoque las pruebas de jUnit como parte del proceso de compilación (ant / maven). Usar jUnit no es nada difícil, lo difícil es crear tantos escenarios de prueba en los que puedas pensar para que puedas detectar los errores temprano y con frecuencia.
CoolBeans

Respuestas:

133
  1. Defina la salida esperada y deseada para un caso normal, con la entrada correcta.

  2. Ahora, implemente la prueba declarando una clase, asígnele un nombre (por lo general, algo así como TestAddingModule) y agregue el método testAdd (es decir, como el siguiente):

    • Escriba un método y, encima, agregue la anotación @Test.
    • En el método, ejecuta tu suma binaria y assertEquals(expectedVal,calculatedVal).
    • Pruebe su método ejecutándolo (en Eclipse, haga clic derecho, seleccione Ejecutar como → Prueba JUnit).

      //for normal addition 
      @Test
      public void testAdd1Plus1() 
      {
          int x  = 1 ; int y = 1;
          assertEquals(2, myClass.add(x,y));
      }
  3. Agregue otros casos como lo desee.

    • Pruebe que su suma binaria no arroje una excepción inesperada si hay un desbordamiento de enteros.
    • Pruebe que su método maneje las entradas nulas correctamente (ejemplo a continuación).

      //if you are using 0 as default for null, make sure your class works in that case.
      @Test
      public void testAdd1Plus1() 
      {
          int y = 1;
          assertEquals(0, myClass.add(null,y));
      }
jayunit100
fuente
1. ¿Se requiere la notación @Test? 2. ¿por qué no probar la entrada nula con asirNotNulo? 3. ¿Dónde se capturan los resultados de las pruebas unitarias? ¿Cómo se indican los resultados al usuario?
user137717
10
Sí, @Testse requiere notación. Esto se hace para indicar al corredor de prueba de unidad que este método representa una prueba de unidad y debe ejecutarse. Los métodos que no están anotados no @Testson ejecutados por el corredor de prueba.
Ali Shah Ahmed
para la segunda prueba, ¿no debería agregar un solo nullpara ydarle y?
Adjunto
¡Gracias! Quiero saber por qué no hay necesidad de agregar statical modificador del método de prueba.
Liang Zhang
104

Proporciono esta publicación para IntelliJ y Eclipse .

Eclipse:

Para realizar una prueba unitaria para su proyecto, siga estos pasos (estoy usando Eclipse para escribir esta prueba):

1- Haga clic en Nuevo -> Proyecto Java.

Crear proyecto

2- Escriba el nombre de su proyecto y haga clic en finalizar.

Crear proyecto

3- Haz clic derecho en tu proyecto. Luego, haga clic en Nuevo -> Clase.

Crear clase

4- Escriba el nombre de su clase y haga clic en finalizar.

Crear clase

Luego, completa la clase así:

public class Math {
    int a, b;
    Math(int a, int b) {
        this.a = a;
        this.b = b;
    }
    public int add() {
        return a + b;
    }
}

5- Haga clic en Archivo -> Nuevo -> Caso de prueba JUnit.

Crear prueba JUnite

6- Verifique la configuración () y haga clic en finalizar. SetUp () será el lugar donde inicializará su prueba.

Comprobar configuración ()

7- Haz clic en Aceptar.

Añadir JUnit

8- Aquí, simplemente agrego 7 y 10. Entonces, espero que la respuesta sea 17. Complete su clase de prueba de esta manera:

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
public class MathTest {
    Math math;
    @Before
    public void setUp() throws Exception {
        math = new Math(7, 10);
    }
    @Test
    public void testAdd() {
        Assert.assertEquals(17, math.add());
    }
}

9- Escribe haz clic en tu clase de prueba en el explorador de paquetes y haz clic en Ejecutar como -> Prueba JUnit.

Ejecute la prueba JUnit

10- Este es el resultado de la prueba.

Resultado de la prueba

IntelliJ: Tenga en cuenta que utilicé IntelliJ IDEA community 2020.1 para las capturas de pantalla. Además, debe configurar su jre antes de estos pasos. Estoy usando JDK 11.0.4.

1- Haz clic derecho en la carpeta principal de tu proyecto-> nuevo -> directorio. Deberías llamar a esto 'prueba'. ingrese la descripción de la imagen aquí 2- Haz clic derecho en la carpeta de prueba y crea el paquete adecuado. Sugiero crear los mismos nombres de empaque que la clase original. Luego, haga clic derecho en el directorio de prueba -> marque el directorio como -> raíz de fuentes de prueba. ingrese la descripción de la imagen aquí 3- En el paquete correcto en el directorio de prueba, debe crear una clase Java (sugiero usar Test.java). ingrese la descripción de la imagen aquí 4- En la clase creada, escriba '@Test'. Luego, entre las opciones que le ofrece IntelliJ, seleccione Agregar 'JUnitx' a classpath. 5- Escribe tu método de prueba en tu clase de prueba. La firma del método es como:ingrese la descripción de la imagen aquí ingrese la descripción de la imagen aquí

@Test
public void test<name of original method>(){
...
}

Puedes hacer tus afirmaciones como a continuación:

Assertions.assertTrue(f.flipEquiv(node1_1, node2_1));

Estas son las importaciones que agregué:

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

ingrese la descripción de la imagen aquí

Esta es la prueba que escribí: ingrese la descripción de la imagen aquí

Puede verificar sus métodos como a continuación:

Assertions.assertEquals(<Expected>,<actual>);
Assertions.assertTrue(<actual>);
...

Para ejecutar sus pruebas unitarias, haga clic derecho en la prueba y haga clic en Ejecutar. ingrese la descripción de la imagen aquí

Si su prueba pasa, el resultado será el siguiente: ingrese la descripción de la imagen aquí

Espero que ayude. Puede ver la estructura del proyecto en GitHub https://github.com/m-vahidalizadeh/problem_solving_project .

Mohammad
fuente
12
Me encanta tu respuesta, ¡es el mejor "cómo hacerlo"!
alisa
44
Me alegra que mi respuesta haya sido útil. Gracias por tu comentario.
Mohammad
1
Así es como deberían verse los tutoriales; limpio, conciso, ejemplo completo. Muy bien.
Jack Of Blades
1
Muchas gracias Jack. Me alegra que lo hayas encontrado útil.
Mohammad
18

Esta es una pregunta muy genérica y hay muchas formas de responderla.

Si desea usar JUnit para crear las pruebas, debe crear su clase de prueba, luego crear métodos de prueba individuales que prueben la funcionalidad específica de su clase / módulo bajo pruebas (las clases de prueba individuales generalmente están asociadas con una sola clase de "producción" que está siendo probado) y dentro de estos métodos ejecutan varias operaciones y comparan los resultados con lo que sería correcto. Es especialmente importante tratar de cubrir tantos casos de esquina como sea posible.

En su ejemplo específico, por ejemplo, podría probar lo siguiente:

  1. Una simple suma entre dos números positivos. Agréguelos, luego verifique que el resultado sea el que esperaría.
  2. Una suma entre un número positivo y un número negativo (que devuelve un resultado con el signo del primer argumento).
  3. Una suma entre un número positivo y un número negativo (que devuelve un resultado con el signo del segundo argumento).
  4. Una suma entre dos números negativos.
  5. Una adición que resulta en un desbordamiento.

Para verificar los resultados, puede utilizar varios métodos afirmarXXX de la clase org.junit.Assert (por conveniencia, puede hacer 'importar static org.junit.Assert. *'). Estos métodos prueban una condición particular y fallan la prueba si no se valida (con un mensaje específico, opcionalmente).

Ejemplo de clase de caso de prueba en su caso (sin los contenidos de los métodos definidos):

import static org.junit.Assert.*;

public class AdditionTests {
    @Test
    public void testSimpleAddition() { ... }


    @Test
    public void testPositiveNegativeAddition() { ... }


    @Test
    public void testNegativePositiveAddition() { ... }


    @Test
    public void testNegativeAddition() { ... }


    @Test
    public void testOverflow() { ... }
}

Si no está acostumbrado a escribir pruebas unitarias, sino que prueba su código escribiendo pruebas ad-hoc que luego valida "visualmente" (por ejemplo, escribe un método principal simple que acepta argumentos ingresados ​​usando el teclado y luego imprime los resultados - y luego sigue ingresando valores y validándose a sí mismo si los resultados son correctos), entonces puede comenzar escribiendo tales pruebas en el formato anterior y validando los resultados con el método afirmar XXX correcto en lugar de hacerlo manualmente. De esta manera, puede volver a ejecutar la prueba mucho más fácilmente que si tuviera que hacer pruebas manuales.

Seramme
fuente
8

Como mencionó @CoolBeans, eche un vistazo a jUnit . Aquí hay un breve tutorial para que comiences también con jUnit 4.x

Finalmente, si realmente desea obtener más información sobre las pruebas y el desarrollo basado en pruebas (TDD), le recomiendo que eche un vistazo al siguiente libro de Kent Beck: Desarrollo basado en pruebas por ejemplo .

vladmore
fuente
6

Otras respuestas le han mostrado cómo usar JUnit para configurar clases de prueba. JUnit no es el único marco de prueba de Java. Sin embargo, concentrarse en los detalles técnicos del uso de un marco de trabajo resta valor a los conceptos más importantes que deberían guiar sus acciones, por lo que hablaré sobre ellos.

  • La prueba (de todo tipo de todo tipo de cosas) compara el comportamiento real de algo (The System Under Test, SUT) con su comportamiento esperado .

  • Las pruebas automatizadas se pueden hacer usando un programa de computadora. Debido a que esa comparación está siendo realizada por un programa informático inflexible y poco inteligente, el comportamiento esperado debe ser conocido de manera precisa e inequívoca.

  • Lo que se espera que haga un programa o parte de un programa (una clase o método) es su especificación . Por lo tanto, probar el software requiere que tenga una especificación para el SUT. Esto podría ser una descripción explícita o una especificación implícita en su cabeza de lo que se espera.

  • Por lo tanto, las pruebas unitarias automatizadas requieren una especificación precisa e inequívoca de la clase o método que está probando.

  • Pero necesitabas esa especificación cuando te propusiste escribir ese código. Entonces, parte de lo que se trata la prueba realmente comienza antes de escribir incluso una línea del SUT. La técnica de prueba de Test Driven Development (TDD) lleva esa idea al extremo y le hace crear el código de prueba de la unidad antes de escribir el código que se va a probar.

  • Los marcos de prueba de unidad prueban su SUT utilizando aserciones . Una aserción es una expresión lógica (una expresión con un booleantipo de resultado; un predicado ) que debe ser truesi el SUT se comporta correctamente. Por lo tanto, la especificación debe expresarse (o reexpresarse) como aserciones.

  • Una técnica útil para expresar una especificación como aserciones es la programación por contrato . Estas especificaciones son en términos de postcondiciones . Una condición posterior es una afirmación sobre el estado públicamente visible del SUT después del retorno de un método o un constructor. Algunos métodos tienen condiciones posteriores que son invariantes , que son predicados que son verdaderos antes y después de la ejecución del método. También se puede decir que una clase tiene invariantes, que son condiciones posteriores de cada constructor y método de la clase y, por lo tanto, siempre deben ser verdaderas. Las condiciones posteriores (e invariantes) se expresan solo en términos de estado visible de publicidad: ypublic y protectedcampos, los valores devueltos por devueltos porpublicprotected métodos (como getters) y el estado públicamente visible de los objetos pasados ​​(por referencia) a los métodos.


Muchos principiantes publican preguntas aquí preguntando cómo pueden probar algún código, presentando el código pero sin indicar la especificación para ese código. Como muestra esta discusión, es imposible que alguien dé una buena respuesta a esa pregunta, porque en el mejor de los casos, los posibles respondedores deben adivinar la especificación y podrían hacerlo incorrectamente. El autor de la pregunta de la cuestión, evidentemente, no entiende la importancia de una especificación, y por tanto es un principiante que necesita para comprender los fundamentos que he descrito aquí antes de intentar escribir algo de código de prueba.

Raedwald
fuente