Szukaj…


Uwagi

Parametr Kontekst Detale
@Przed zajęciami Statyczny Wywoływany, gdy klasa jest tworzona po raz pierwszy
@Przed Instancja Wykonywany przed każdym testem w klasie
@Test Instancja Należy zadeklarować każdą metodę do przetestowania
@Po Instancja Wykonywany po każdym teście w klasie
@Po zajęciach Statyczny Wykonany przed zniszczeniem klasy

Przykładowy format klasy testowej

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

Testy jednostkowe przy użyciu JUnit

Tutaj mamy klasę Counter z metodami countNumbers() i 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.*");
    }
}

Aby przetestować tę klasę w jednostce, możemy użyć frameworka Junit. Dodaj junit.jar do ścieżki klasy projektu. Następnie utwórz klasę przypadku testowego, jak poniżej:

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

W swoim IDE możesz uruchomić tę klasę jako „walizkę testową Junit” i zobaczyć dane wyjściowe w GUI. W wierszu polecenia możesz skompilować i uruchomić przypadek testowy, jak poniżej:

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

Dane wyjściowe z pomyślnego uruchomienia testowego powinny wyglądać podobnie do:

JUnit version 4.9b2
..
Time: 0.019

OK (2 tests)

W przypadku niepowodzenia testu wyglądałoby to bardziej:

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

Lampy

Z Wikipedii :

Urządzenie testowe służy do konsekwentnego testowania jakiegoś elementu, urządzenia lub oprogramowania.

Może także poprawić czytelność testów poprzez wydobycie wspólnego kodu inicjalizacji / finalizacji z samych metod testowych.

Tam, gdzie wspólną inicjalizację można wykonać raz zamiast przed każdym testem, może to również skrócić czas potrzebny na uruchomienie testów.

Poniższy przykład ma na celu pokazanie głównych opcji dostarczonych przez JUnit. Załóżmy, że zainicjowanie klasy Foo jest drogie:

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

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

Bar innej klasy ma odniesienie do Foo :

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

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

Poniższe testy oczekują początkowego kontekstu Listy zawierającej pojedynczy 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();
    }
}

W przykładzie @BeforeClass opisywane sposób setupOnce() jest wykorzystywane do tworzenia Foo Obiekt, który jest kosztowny do inicjalizacji. Ważne jest, aby nie był modyfikowany przez żaden z testów, w przeciwnym razie wynik testu może zależeć od kolejności wykonywania poszczególnych testów. Chodzi o to, że każdy test jest niezależny i testuje jedną małą funkcję.

@Before adnotacji @Before setup() konfiguruje kontekst testowy. Kontekst może być modyfikowany podczas wykonywania testu, dlatego należy go inicjować przed każdym testem. Równoważny efekt można osiągnąć, włączając kod zawarty w tej metodzie na początku każdej metody testowej.

Metoda @After adnotacji tearDown() czyści zasoby w kontekście testowym. Jest wywoływany po każdym wywołaniu testowym i jako taki jest często używany do zwolnienia zasobów przydzielonych w @Before komentarzem @Before .

@AfterClass adnotowana tearDownOnce() czyści zasoby po uruchomieniu wszystkich testów. Takie metody są zwykle używane do @BeforeClass zasobów przydzielanych podczas inicjowania lub w @BeforeClass adnotacjami @BeforeClass . To powiedziawszy, prawdopodobnie najlepiej unikać zasobów zewnętrznych w testach jednostkowych, aby testy nie zależały od niczego poza klasą testów.

Testy jednostkowe z wykorzystaniem teorii

Z JavaDoc

Runner Theories pozwala przetestować określoną funkcjonalność względem podzbioru nieskończonego zestawu punktów danych.

Uruchamianie teorii

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

Metody opatrzone adnotacją @Theory będą czytane jako teorie przez biegacza Theories.

Adnotacja @DataPoint

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

Każde pole opatrzone @DataPoint będzie używane jako parametr metody danego typu w teoriach. W powyższym przykładzie theoryMethod będzie działać dwa razy z następującymi parametrami: ["str1", 2] , ["str2", 2]

@DataPoints adnotacja @RunWith (Theories.class) public class 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
    }
}

Każdy element tablicy opatrzony adnotacją @DataPoints będzie używany jako parametr metody danego typu w teoriach. W powyższym przykładzie theoryMethod będzie działać cztery razy z następującymi parametrami: ["str1", 1], ["str2", 1], ["str1", 2], ["str2", 2]

Pomiar wydajności

Jeśli musisz sprawdzić, czy wykonanie metody testowania trwa zbyt długo, możesz to zrobić, wspominając o oczekiwanym czasie wykonania przy użyciu właściwości timeout adnotacji @Test. Jeśli wykonanie testu trwa dłużej niż ta liczba milisekund, powoduje to niepowodzenie metody testowej.

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

}

W większości przypadków bez testu rozgrzewania JVM testString nie powiedzie się. Ale testStringBuffer i testStringBuilder powinny pomyślnie przejść ten test.



Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow