Buscar..


Observaciones

Parámetro Contexto Detalles
@Antes de clase Estático Ejecutado cuando la clase se crea por primera vez
@Antes de Ejemplo Ejecutado antes de cada prueba en la clase.
@Prueba Ejemplo Se debe declarar cada método a probar.
@Después Ejemplo Ejecutado después de cada prueba en la clase.
@Después de clases Estático Ejecutado antes de la destrucción de la clase.

Ejemplo de formato de clase de prueba

public class TestFeatureA {

    @BeforeClass
    public static void setupClass() {}
    
    @Before
    public void setupTest() {}
    
    @Test
    public void testA() {}
    
    @Test
    public void testB() {}
    
    @After
    public void tearDownTest() {}
    
    @AfterClass
    public static void tearDownClass() {}
    
    }
}

Pruebas unitarias utilizando JUnit

Aquí tenemos una clase Counter con métodos countNumbers() y hasNumbers() .

public class Counter {

    /* To count the numbers in the input */
    public static int countNumbers(String input) {
        int count = 0;
        for (char letter : input.toCharArray()) {
            if (Character.isDigit(letter))
                count++;
        }
        return count;
    }

    /* To check whether the input has number*/
    public static boolean hasNumber(String input) {
        return input.matches(".*\\d.*");
    }
}

Para la prueba unitaria de esta clase, podemos usar el framework Junit. Agregue el junit.jar en la junit.jar de su clase de proyecto. Luego crea la clase de caso de prueba como se muestra a continuación:

import org.junit.Assert; // imports from the junit.jar
import org.junit.Test;

public class CounterTest {

    @Test // Test annotation makes this method as a test case
    public void countNumbersTest() {
        int expectedCount = 3;
        int actualCount = Counter.countNumbers("Hi 123");
        Assert.assertEquals(expectedCount, actualCount); //compares expected and actual value
    }

    @Test
    public void hasNumberTest() {
        boolean expectedValue = false;
        boolean actualValue = Counter.hasNumber("Hi there!");
        Assert.assertEquals(expectedValue, actualValue);
    }
}

En su IDE puede ejecutar esta clase como "Junit testcase" y ver el resultado en la GUI. En el símbolo del sistema, puede compilar y ejecutar el caso de prueba de la siguiente manera:

\> javac -cp ,;junit.jar CounterTest.java
\> java  -cp .;junit.jar org.junit.runner.JUnitCore CounterTest

El resultado de una ejecución de prueba exitosa debe ser similar a:

JUnit version 4.9b2
..
Time: 0.019

OK (2 tests)

En el caso de una falla de prueba se vería más como:

Time: 0.024
There was 1 failure:
1) CountNumbersTest(CounterTest)
java.lang.AssertionError: expected:<30> but was:<3>
... // truncated output
FAILURES!!!
Tests run: 2,  Failures: 1

Accesorios

De Wikipedia :

Un dispositivo de prueba es algo que se usa para probar consistentemente algún elemento, dispositivo o pieza de software.

También puede mejorar la legibilidad de las pruebas al extraer el código común de inicialización / finalización de los métodos de prueba en sí.

Cuando se puede ejecutar una inicialización común una vez en lugar de antes de cada prueba, esto también puede reducir la cantidad de tiempo que se tarda en ejecutar las pruebas.

El siguiente ejemplo está diseñado para mostrar las opciones principales proporcionadas por JUnit. Supongamos una clase Foo que es caro inicializar:

public class Foo {
    public Foo() {
        // expensive initialization
    }

    public void cleanUp() {
        // cleans up resources
    }
}

Otra clase de Bar tiene una referencia a Foo :

public class Bar {
    private Foo foo;
    
    public Bar(Foo foo) {
        this.foo = foo;
    }

    public void cleanUp() {
        // cleans up resources
    }
}

Las siguientes pruebas esperan un contexto inicial de una Lista que contenga una única Bar .

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import java.util.Arrays;
import java.util.List;

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

public class FixturesTest {
    
    private static Foo referenceFoo;
    
    private List<Bar> testContext;
    
    @BeforeClass
    public static void setupOnce() {
        // Called once before any tests have run
        referenceFoo = new Foo();
    }

    @Before
    public void setup() {
        // Called before each test is run
        testContext = Arrays.asList(new Bar(referenceFoo));
    }
    
    @Test
    public void testSingle() {
        assertEquals("Wrong test context size", 1, testContext.size());
        Bar baz = testContext.get(0);
        assertEquals(referenceFoo, baz.getFoo());
    }
    
    @Test
    public void testMultiple() {
        testContext.add(new Bar(referenceFoo));
        assertEquals("Wrong test context size", 2, testContext.size());
        for (Bar baz : testContext) {
            assertEquals(referenceFoo, baz.getFoo());
        }
    }
    
    @After
    public void tearDown() {
        // Called after each test is run
        for (Bar baz : testContext) {
            baz.cleanUp();
        }
    }
    
    @AfterClass
    public void tearDownOnce() {
        // Called once after all tests have run
        referenceFoo.cleanUp();
    }
}

En el ejemplo de la @BeforeClass método anotado setupOnce() se utiliza para crear la Foo objeto, que es caro para inicializar. Es importante que no se modifique por ninguna de las pruebas, de lo contrario, el resultado de la ejecución de la prueba podría depender del orden de ejecución de las pruebas individuales. La idea es que cada prueba sea independiente y pruebe una pequeña característica.

El @Before método anotado setup() configura el contexto de prueba. El contexto puede modificarse durante la ejecución de la prueba, por lo que debe inicializarse antes de cada prueba. El efecto equivalente podría lograrse incluyendo el código contenido en este método al comienzo de cada método de prueba.

El @After anotada método tearDown() limpia los recursos dentro del contexto de prueba. Se llama después de cada invocación de prueba y, como tal, a menudo se utiliza para liberar recursos asignados en un método anotado @Before .

El @AfterClass método anotado tearDownOnce() limpia los recursos una vez que todas las pruebas se han ejecutado. Estos métodos se utilizan normalmente para liberar recursos asignados durante la inicialización o en un método anotado @BeforeClass . Dicho esto, probablemente es mejor evitar los recursos externos en las pruebas unitarias para que las pruebas no dependan de nada fuera de la clase de prueba.

Pruebas unitarias utilizando teorías.

Desde JavaDoc

Theory Theory Runner permite probar cierta funcionalidad contra un subconjunto de un conjunto infinito de puntos de datos.

Teorias corrientes

import org.junit.experimental.theories.Theories;
import org.junit.experimental.theories.Theory;
import org.junit.runner.RunWith;

@RunWith(Theories.class)
public class FixturesTest {

    @Theory
    public void theory(){
        //...some asserts
    }
}

Los métodos anotados con @Theory serán leídos como teorías por el corredor de teorías.

@DataPoint anotación

@RunWith(Theories.class)
public class FixturesTest {

    @DataPoint
    public static String dataPoint1 = "str1";
    @DataPoint
    public static String dataPoint2 = "str2";
    @DataPoint
    public static int intDataPoint = 2;

    @Theory
    public void theoryMethod(String dataPoint, int intData){
        //...some asserts
    }
}

Cada campo anotado con @DataPoint se usará como un parámetro de método de un tipo dado en las teorías. En el ejemplo anterior, theoryMethod se ejecutará dos veces con los siguientes parámetros: ["str1", 2] , ["str2", 2]

@DataPoints anotación @RunWith (Theories.class) clase pública FixturesTest {

    @DataPoints
    public static String[] dataPoints = new String[]{"str1", "str2"};
    @DataPoints
    public static int[] dataPoints = new int[]{1, 2};

    @Theory
    public void theoryMethod(String dataPoint, ){
        //...some asserts
    }
}

Cada elemento de la matriz anotada con la anotación @DataPoints se usará como un parámetro de método de un tipo dado en las teorías. En el ejemplo anterior, theoryMethod se ejecutará cuatro veces con los siguientes parámetros: ["str1", 1], ["str2", 1], ["str1", 2], ["str2", 2]

Medición del desempeño

Si necesita verificar si su método de prueba demora demasiado en ejecutarse, puede hacerlo mencionando el tiempo de ejecución esperado usando la propiedad de tiempo de espera de la anotación @Test. Si la ejecución de la prueba lleva más de esa cantidad de milisegundos, el método de prueba falla.

public class StringConcatenationTest {

    private static final int TIMES = 10_000;
    
    // timeout in milliseconds
    @Test(timeout = 20)
    public void testString(){

        String res = "";

        for (int i = 0; i < TIMES; i++) {
            res += i;
        }

        System.out.println(res.length());
    }

    @Test(timeout = 20)
    public void testStringBuilder(){

        StringBuilder res = new StringBuilder();

        for (int i = 0; i < TIMES; i++) {
            res.append(i);
        }

        System.out.println(res.length());
    }

    @Test(timeout = 20)
    public void testStringBuffer(){

        StringBuffer res = new StringBufferr();

        for (int i = 0; i < TIMES; i++) {
            res.append(i);
        }

        System.out.println(res.length());
    }

}

En la mayoría de los casos sin JVM, la testString de testString fallará. Pero testStringBuffer y testStringBuilder deberían pasar esta prueba con éxito.



Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow