Suche…


Bemerkungen

Parameter Kontext Einzelheiten
@Vor dem Unterricht Statisch Wird ausgeführt, wenn die Klasse zum ersten Mal erstellt wird
@Vor Beispiel Vor jedem Test in der Klasse ausgeführt
@Prüfung Beispiel Sollte jede Methode zum Testen deklariert werden
@Nach dem Beispiel Wird nach jedem Test in der Klasse ausgeführt
@Nach dem Unterricht Statisch Vor Zerstörung der Klasse ausgeführt

Beispiel für das Testklassenformat

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() {}
    
    }
}

Unit-Test mit JUnit

Hier haben wir eine Klasse Counter mit Methoden countNumbers() und 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.*");
    }
}

Um diese Klasse zu testen, können wir das Junit-Framework verwenden. Fügen Sie die junit.jar in Ihren Projektklassenpfad ein. Dann erstellen Sie die Testfallklasse wie folgt:

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);
    }
}

In Ihrer IDE können Sie diese Klasse als "Junit-Testfall" ausführen und die Ausgabe in der GUI sehen. In der Eingabeaufforderung können Sie den Testfall wie folgt kompilieren und ausführen:

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

Die Ausgabe eines erfolgreichen Testlaufs sollte folgendermaßen aussehen:

JUnit version 4.9b2
..
Time: 0.019

OK (2 tests)

Im Falle eines Testfehlers würde es eher so aussehen:

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

Fixtures

Von Wikipedia :

Ein Testgerät dient zum durchgängigen Testen eines Artikels, Geräts oder einer Software.

Es kann auch die Lesbarkeit von Tests verbessern, indem allgemeiner Initialisierungs- / Finalisierungscode aus den Testmethoden selbst extrahiert wird.

Wenn die gemeinsame Initialisierung einmal vor jedem Test ausgeführt werden kann, kann dies auch den Zeitaufwand für die Durchführung von Tests reduzieren.

Das folgende Beispiel zeigt die wichtigsten Optionen von JUnit. Angenommen, eine Klasse Foo deren Initialisierung teuer ist:

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

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

Eine andere Klasse Bar hat einen Verweis auf Foo :

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

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

Die folgenden Tests erwarten einen Anfangskontext einer Liste, die einen einzelnen 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();
    }
}

Im Beispiel ist die @BeforeClass kommentierten Methode setupOnce() wird verwendet , um das zu schaffen , Foo - Objekt, das zu initialisieren teuer ist. Es ist wichtig, dass es durch keinen der Tests geändert wird, da das Ergebnis des Testlaufs von der Reihenfolge der einzelnen Tests abhängen kann. Die Idee ist, dass jeder Test unabhängig ist und ein kleines Feature testet.

Die mit @Before annotierte Methode setup() legt den @Before . Der Kontext kann während der Testausführung geändert werden, weshalb er vor jedem Test initialisiert werden muss. Der äquivalente Effekt könnte erreicht werden, indem der in dieser Methode enthaltene Code zu Beginn jeder Testmethode eingefügt wird.

Die @After annotierte Methode tearDown() bereinigt Ressourcen im tearDown() . Sie wird nach jedem @Before aufgerufen und wird daher häufig dazu verwendet, Ressourcen zuzuweisen, die in einer mit @Before annotierten Methode zugewiesen wurden.

Die annotierte tearDownOnce() @AfterClass Methode tearDownOnce() bereinigt Ressourcen, sobald alle Tests ausgeführt wurden. Mit diesen Methoden werden normalerweise Ressourcen @BeforeClass die während der Initialisierung oder in einer annotierten @BeforeClass Methode zugewiesen wurden. Das heißt, es ist wahrscheinlich am besten, externe Ressourcen bei Komponententests zu vermeiden, damit die Tests nicht von etwas außerhalb der Testklasse abhängen.

Unit-Tests mit Theorien

Aus JavaDoc

Der Theories Runner ermöglicht das Testen einer bestimmten Funktionalität gegen eine Teilmenge einer unendlichen Menge von Datenpunkten.

Theorien laufen lassen

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
    }
}

Mit @Theory annotierte @Theory werden vom Theories Runner als Theorien gelesen.

@DataPoint-Annotation

@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
    }
}

Jedes mit @DataPoint annotierte @DataPoint wird als Methodenparameter eines bestimmten Typs in den Theorien verwendet. In obigem theoryMethod wird theoryMethod zweimal mit den folgenden Parametern ausgeführt: ["str1", 2] , ["str2", 2]

@DataPoints Annotation @RunWith (Theories.class) öffentliche Klasse 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
    }
}

Jedes Element des mit @DataPoints Annotation annotierten @DataPoints wird als Methodenparameter eines bestimmten Typs in den Theorien verwendet. In dem obigen theoryMethod wird theoryMethod viermal mit den folgenden Parametern ausgeführt: ["str1", 1], ["str2", 1], ["str1", 2], ["str2", 2]

Leistungsmessung

Wenn Sie prüfen müssen, ob die Ausführung Ihrer Testmethode zu lange dauert, können Sie dies durch Angabe der erwarteten Ausführungszeit mit der timeout-Eigenschaft der @ Test-Annotation tun. Wenn die Testausführung länger als diese Anzahl von Millisekunden dauert, schlägt die Testmethode fehl.

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());
    }

}

In den meisten Fällen testString ohne JVM- testString fehl. testStringBuffer und testStringBuilder sollten diesen Test jedoch erfolgreich bestehen.



Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow