Jaka jest różnica między awarią a błędem w JUnit?

93

Przeprowadzam testy JUnit na dużej bazie kodu i zdałem sobie sprawę, że czasami dostaję „Błędy”, a innym razem otrzymuję „Awarie”. Co za różnica?

froadie
źródło

Odpowiedzi:

117

Ok, właśnie zauważyłem wzór i myślę, że go rozgryzłem (popraw mnie, jeśli się mylę). Wydaje mi się, że niepowodzenia są wtedy, gdy zawodzą twoje przypadki testowe - tj. Twoje twierdzenia są niepoprawne. Błędy to nieoczekiwane błędy, które pojawiają się podczas próby rzeczywistego uruchomienia testu - wyjątki itp.

froadie
źródło
5
Chociaż jeśli java.lang.AssertionErrorrzucony zostanie cokolwiek rozszerzającego , zostanie to pokazane jako niepowodzenie testu zamiast błędu testu. Powinieneś rozważyć zaakceptowanie własnej odpowiedzi, ponieważ jest poprawna.
ponzao
Tak, na tym właśnie polega różnica. A z pragmatycznego punktu widzenia nie ma „żadnej różnicy” - jeśli pojawi się błąd lub awaria, to trzeba to naprawić. Więc prawdopodobnie błędem było osobne liczenie „awarii” i „błędów” w JUnit. JUnit 4 łączy te dwa elementy (jak wyjaśniono w odpowiedzi poniżej).
Jeff Grigg
A jeśli oczekiwany jest wyjątek, należy dodać adnotację @Testz expected = SomeException.class.
Downhillski
@JeffGrigg istnieje pragmatyczna różnica. Jeśli w wielu przypadkach testowych polegamy na jednym zachowaniu, nadal mogę napisać tylko jeden przypadek testowy, który potwierdza to zachowanie, jednocześnie rzucając niepochwycone, prawdopodobnie wyjątki czasu wykonywania we wszystkich pozostałych. Oznacza to, że pozostałe przypadki testowe testują coś innego, mimo że nadal zależą od tego konkretnego zachowania, aby je uruchomić. Kiedy to zachowanie jest zepsute, tylko jeden przypadek testowy zgłosi błąd, podczas gdy reszta zgłosi błąd, iz tego widzę, że mam dokładnie jeden błąd do naprawienia, mimo że wiele przypadków testowych nie przeszło pomyślnie.
RonJRH
Jeśli nie powiedzie się org.junit.Assert.assertEquals (), raport JUnit4 HTML uznaje za BŁĄD. To zaprzecza twojemu stwierdzeniu (o którym wiedziałem do tej pory). Czy możesz rzucić na to więcej światła?
Krishnom
15

Jeśli test zgłasza wyjątek, który nie jest propagowany przez platformę Assertion w Junit, zostanie zgłoszony jako błąd. Na przykład wyjątek NullPointer lub ClassNotFound zgłosi błąd:

String s = null;
s.trim();

lub,

try {

    // your code
} catch(Exception e) {
    // log the exception
    throw new MyException(e);
}

Mimo to następujące osoby zgłoszą awarię:

Assert.fail("Failure here");

lub,

Assert.assertEquals(1, 2);

lub nawet:

throw new AssertionException(e);

To zależy od używanej wersji Junit. Junit 4 rozróżnia awarię od błędu, ale Junit 4 upraszcza to tylko jako awarie.

Poniższy link zawiera bardziej interesujące dane wejściowe:

http://www.devx.com/Java/Article/31983/1763/page/2

Neel
źródło
To nie jest dokładne. W JUnit 4 nie zniknęło rozróżnienie między niepowodzeniem testu a błędem testu. Właśnie go przetestowałem. Połączony artykuł wprowadzał w błąd. Napisano w nim: „JUnit 4 upraszcza to tylko dzięki wykorzystaniu błędów”, ale powinien podkreślać, że JUnit 4 zamienia java.lang.AssertionError w niepowodzenia testów, więc nie musisz używać junit.framework.AssertionFailedError. Zaletą jest to, że możesz rozpocząć pisanie asercji testowych w kodzie produkcyjnym bez połączenia projektu z JUnit. Rozróżnienie między błędem testu a niepowodzeniem testu jest również niezwykle przydatne i byłoby krokiem wstecz, gdyby zostało usunięte.
RonJRH
RonJRH, czy jesteś w stanie zobaczyć błędy w swoim domyślnym raporcie z junit?
Neel
Tak, Neel. Właśnie tego spróbowałem. Nie do końca jestem pewien, jaka jest etyka łączenia obrazu tutaj, ale to pokazuje wynik mojego testu: imagebucket.net/abpxucddkvn1/Capture.PNG
RonJRH
6

Z „Pragmatic Unit Testing in Java 8 with JUnit”:

Asercje (lub potwierdzenia) w JUnit to statyczne wywołania metod, które dodajesz do testów. Każde stwierdzenie jest okazją do zweryfikowania, że ​​jakiś warunek jest prawdziwy. Jeśli potwierdzony warunek nie jest spełniony, test zatrzymuje się w tym miejscu, a JUnit zgłasza niepowodzenie testu.

(Jest również możliwe, że gdy JUnit uruchomi Twój test, wyjątek zostanie zgłoszony i nie zostanie przechwycony. W takim przypadku JUnit zgłasza błąd testu).

Matias Elorriaga
źródło
5

Poniższy test wyjaśnia różnicę między błędem testu a niepowodzeniem testu .

Skomentowałem linię, która wyrzuca błąd testu i błąd testu.

    @Test
    public void testErrorVsTestFailure() {

        final String sampleString = null;

        assertEquals('j', sampleString.charAt(0) );
        //above line throws test error as you are trying to access charAt() method on null reference

        assertEquals(sampleString, "jacob");
        //above line throws Test failure as the actual value-a null , is not equal to expected value-string "jacob"
        }

Tak więc Junit wyświetla błąd testu za każdym razem, gdy pojawi się wyjątek, i błąd testu, gdy oczekiwana wartość wyniku nie jest zgodna z rzeczywistą wartością

Deen John
źródło
2

Klasa źródłowa: JUnitReportReporter.java

public void generateReport(List<XmlSuite> xmlSuites, List<ISuite> suites, String defaultOutputDirectory) {
//......

            for (ITestResult tr : (Set) entry.getValue()) {
                TestTag testTag = new TestTag();

                boolean isSuccess = tr.getStatus() == 1;
                if (!(isSuccess)) {
                    if (tr.getThrowable() instanceof AssertionError)
                        ++errors;
                    else {
                        ++failures;
                    }
                }
}

Jak widać poniżej w powyższej metodzie

instancja tr.getThrowable () AssertionError

liczba błędów wzrasta, gdy jest to wystąpienie AssertionError, w przeciwnym razie (dowolny Throwable) jest liczony jako awarie.

Roushan
źródło
1

Masz rację, że awarie pochodzą z AssertionErrors wyrzuconych przez metody asercji JUnit lub przez zgłoszenie błędu AssertionError lub przez zgłoszenie wyjątku, który zadeklarowałeś w swojej @Testadnotacji, a błędy pochodzą z innych, nieoczekiwanych wyjątków. Ale jest między nimi ważna różnica:

Niepowodzenie oznacza, że ​​test został przeprowadzony poprawnie i zidentyfikował defekt w kodzie.

Błąd może oznaczać błąd w kodzie, ale taki, którego nawet nie testowałeś. Może to również oznaczać, że błąd występuje w samym teście.

Krótko mówiąc, awaria oznacza, że ​​musisz przepisać testowany kod. Błąd oznacza, że ​​może to być test jednostkowy, który musisz przepisać. Może to oznaczać, nawet jeśli błąd wystąpił w Twoim kodzie, na przykład a NullPointerException, ponieważ wykryłeś lukę, której nawet nie testowałeś, więc warto to sprawdzić.

MiguelMunoz
źródło
0

Paradoksalnie, JUnit i innych ram badań związanych (TestNG, hamcrest) zapewniają assert operacji, które sprawdzają stan i jeśli to się nie powiedzie , wyrzucany jest "pod maską" błąd java.lang.AssertionError, który rozszerza java.lang.Error.

Ale to nie zaprzecza powyższym odpowiedziom, które są oczywiście w pełni aktualne. Aby więc oznaczyć określony przepływ testów jako niepowodzenie, można rzucić AssertionError, jednak nie jestem pewien, czy jest to naprawdę udokumentowane w odpowiednich instrukcjach, ponieważ bardziej odpowiednie jest użycie dedykowanego API fail (). Inne rodzaje broni miotanej będą traktowane jako błędy, a nie awarie.

agolubev81
źródło
0

Zasadniczo niepowodzenia odnoszą się do niespełnionych stwierdzeń, podczas gdy błędy wynikają z nieprawidłowego wykonania testu . i myślę, że każde IDE ma symboliczne ikony z różnymi kolorami oznaczające powodzenie , niepowodzenie i błąd testów.

Aby uzyskać więcej informacji, sprawdź to .

Soufiane Roui
źródło