W fail()
bibliotece JUnit4 jest metoda. Podoba mi się, ale doświadczam braku pass()
metody, której nie ma w bibliotece. Dlaczego tak się dzieje?
Odkryłem, że mogę użyć assertTrue(true)
zamiast tego, ale nadal wygląda to nielogicznie.
@Test
public void testSetterForeignWord(){
try {
card.setForeignWord("");
fail();
} catch (IncorrectArgumentForSetter ex){
}
// assertTrue(true);
}
pass
metody.Odpowiedzi:
Dopóki test nie zgłosi wyjątku, przechodzi, chyba że twoja
@Test
adnotacja określa oczekiwany wyjątek. Przypuszczam, żepass()
można by rzucić specjalny wyjątek, który JUnit zawsze interpretuje jako pozytywny, aby zewrzeć test, ale byłoby to sprzeczne ze zwykłym projektowaniem testów (tj. Zakładałoby sukces i kończyło się niepowodzeniem tylko wtedy, gdy asercja nie powiedzie się) i jeśli ludzie otrzymają pomysłpass()
, który byłby preferowany , znacznie spowolniłby duży zestaw testów zaliczających (ze względu na narzut tworzenia wyjątków). Niepowodzenie testów nie powinno być normą, więc nie jest to wielka sprawa, jeśli mają taki narzut.Zauważ, że twój przykład może zostać przepisany w ten sposób:
@Test(expected=IncorrectArgumentForSetter.class) public void testSetterForeignWord("") throws Exception { card.setForeignWord(""); }
Powinieneś także preferować używanie standardowych wyjątków Java. Twój
IncorrectArgumentForSetter
prawdopodobnie powinien byćIllegalArgumentException
.źródło
pass()
metoda nie mogła po prostu nic nie zrobić, aby test nie mógł się nie powieść po jej wywołaniu. Więc usunąłem to zdanie.Call
return
oświadczenie za każdym razem, gdy test zostanie zakończony i zdany.źródło
Myślę, że to pytanie wymaga zaktualizowanej odpowiedzi, ponieważ większość odpowiedzi tutaj jest dość nieaktualna.
Po pierwsze, na pytanie PO:
Myślę, że całkiem dobrze przyjęto, że wprowadzenie koncepcji „oczekiwanego wyjątku” do JUnit było złym posunięciem, ponieważ ten wyjątek można zgłosić w dowolnym miejscu i zda on test. Działa, jeśli wyrzucasz (i potwierdzasz) wyjątki specyficzne dla domeny, ale tego typu wyjątki rzucam tylko wtedy, gdy pracuję nad kodem, który musi być absolutnie nieskazitelny, - większość APIS po prostu wyrzuci wbudowane wyjątki, takie jak
IllegalArgumentException
lubIllegalStateException
. Jeśli dwa wywołania, które wykonujesz, mogą potencjalnie spowodować te wyjątki, to@ExpectedException
adnotacja zielony pasek twojego testu, nawet jeśli jest to zła linia, która zgłasza wyjątek!W tej sytuacji napisałem zajęcia, które na pewno napisało wielu innych, to jest
assertThrows
metoda:public class Exceptions { private Exceptions(){} public static void assertThrows(Class<? extends Exception> expectedException, Runnable actionThatShouldThrow){ try{ actionThatShouldThrow.run(); fail("expected action to throw " + expectedException.getSimpleName() + " but it did not."); } catch(Exception e){ if ( ! expectedException.isInstance(e)) { throw e; } } } }
ta metoda po prostu zwraca, jeśli wyjątek zostanie zgłoszony, umożliwiając wykonanie dalszych asercji / weryfikacji w teście.
dzięki składni java 8 twój test wygląda naprawdę ładnie. Poniżej znajduje się jeden z prostszych testów na naszym modelu wykorzystującym metodę:
@Test public void when_input_lower_bound_is_greater_than_upper_bound_axis_should_throw_illegal_arg() { //setup AxisRange range = new AxisRange(0,100); //act Runnable act = () -> range.setLowerBound(200); //assert assertThrows(IllegalArgumentException.class, act); }
testy te są trochę dziwne, ponieważ krok „działaj” w rzeczywistości nie wykonuje żadnej czynności, ale myślę, że znaczenie jest nadal dość jasne.
na maven jest też mała biblioteka o nazwie catch -ception, która używa składni w stylu mockito, aby sprawdzić, czy wyjątki są generowane. Wygląda ładnie, ale nie jestem fanem dynamicznych proxy. To powiedziawszy, składnia jest tak zręczna, że pozostaje kusząca:
// given: an empty list List myList = new ArrayList(); // when: we try to get the first element of the list // then: catch the exception if any is thrown catchException(myList).get(1); // then: we expect an IndexOutOfBoundsException assert caughtException() instanceof IndexOutOfBoundsException;
Na koniec, w sytuacji, w której znalazłem się, aby dostać się do tego wątku, istnieje sposób na zignorowanie testów, jeśli zostanie spełniony jakiś warunek.
W tej chwili pracuję nad uzyskaniem niektórych bibliotek DLL wywoływanych przez bibliotekę java natywną ładującą bibliotekę o nazwie JNA, ale nasz serwer kompilacji jest w systemie Ubuntu. Lubię próbować napędzać ten rodzaj rozwoju za pomocą testów JUnit - chociaż w tym momencie są one dalekie od „jednostek” -. Chcę przeprowadzić test, jeśli jestem na komputerze lokalnym, ale zignorować test, jeśli jesteśmy na Ubuntu. JUnit 4 ma na to przepis, zwany
Assume
:@Test public void when_asking_JNA_to_load_a_dll() throws URISyntaxException { //this line will cause the test to be branded as "ignored" when "isCircleCI" //(the machine running ubuntu is running this test) is true. Assume.assumeFalse(BootstrappingUtilities.isCircleCI()); //an ignored test will typically result in some qualifier being put on the results, //but will also not typically prevent a green-ton most platforms. //setup URL url = DLLTestFixture.class.getResource("USERDLL.dll"); String path = url.toURI().getPath(); path = path.substring(0, path.lastIndexOf("/")); //act NativeLibrary.addSearchPath("USERDLL", path); Object dll = Native.loadLibrary("USERDLL", NativeCallbacks.EmptyInterface.class); //assert assertThat(dll).isNotNull(); }
źródło
Szukałem również
pass
metody dla JUnit, abym mógł zwierać niektóre testy, które nie miały zastosowania w niektórych scenariuszach (są testy integracyjne, a nie czyste testy jednostkowe). Więc szkoda, że go nie ma.Na szczęście jest sposób na warunkowe zignorowanie testu, co w rzeczywistości pasuje jeszcze lepiej w moim przypadku przy użyciu
assumeTrue
metody:Więc tutaj test zostanie wykonany tylko wtedy, gdy isTestApplicable ma wartość true, w przeciwnym razie test zostanie zignorowany.
źródło
Nie ma potrzeby stosowania metody pass, ponieważ gdy nie zostanie zgłoszony wyjątek AssertionFailedException z kodu testu, przypadek testu jednostkowego zostanie przekazany.
Metoda fail () w rzeczywistości zgłasza wyjątek AssertionFailedException w celu odrzucenia testu testCase, jeśli kontrola dojdzie do tego punktu.
źródło
Myślę, że to pytanie jest wynikiem małego niezrozumienia procesu wykonywania testów. W JUnit (i innych narzędziach testujących) wyniki są liczone według metody, a nie dla wywołania assert. Nie ma licznika, który śledzi, ile
assertX
wykonano pomyślnie / zakończonych niepowodzeniem .JUnit wykonuje każdą metodę testową oddzielnie. Jeśli metoda zakończy się pomyślnie, test zostanie zarejestrowany jako „zaliczony”. Jeśli wystąpi wyjątek, test zarejestrowany jako „nie powiódł się”. W tym drugim przypadku możliwe są dwie subprzypadki: 1) wyjątek asercji JUnit, 2) dowolny inny rodzaj wyjątków. W pierwszym przypadku stan będzie oznaczony jako „błąd”, w drugim „błąd”.
W
Assert
klasie dostępnych jest wiele metod skrótowych do rzucania wyjątków asercji. Innymi słowy,Assert
jest warstwą abstrakcji ponad wyjątkami JUnit.Na przykład to jest kod źródłowy
assertEquals
na GitHub :/** * Asserts that two Strings are equal. */ static public void assertEquals(String message, String expected, String actual) { if (expected == null && actual == null) { return; } if (expected != null && expected.equals(actual)) { return; } String cleanMessage = message == null ? "" : message; throw new ComparisonFailure(cleanMessage, expected, actual); }
Jak widać, w przypadku równości nic się nie dzieje, w przeciwnym razie zostanie rzucony wyjątek.
Więc:
assertEqual("Oh!", "Some string", "Another string!");
po prostu zgłasza
ComparisonFailure
wyjątek, który zostanie przechwycony przez JUnit, aassertEqual("Oh?", "Same string", "Same string");
nic nie robi.
Podsumowując, coś takiego
pass()
nie miałoby sensu, bo nic nie dało.źródło