JUnit: jak uniknąć „niemożliwych do uruchomienia metod” w klasach narzędzi testowych


118

Przerzuciłem się na JUnit4.4 z JUnit3.8. Uruchamiam testy za pomocą programu Ant, wszystkie testy przebiegają pomyślnie, ale klasy narzędzi testowych kończą się niepowodzeniem z błędem „Brak metod do uruchomienia”. Wzorzec, którego używam, polega na umieszczeniu wszystkich klas o nazwie * Test * w folderze testowym.

Rozumiem, że biegacz nie może znaleźć żadnej metody z adnotacją @Test. Ale nie zawierają takiej adnotacji, ponieważ te klasy nie są testami. Zaskakujące jest to, że uruchamiając te testy w zaćmieniu, nie narzeka na te klasy.

W JUnit3.8 nie był to żaden problem, ponieważ te klasy narzędziowe nie rozszerzały TestCase, więc runner nie próbował ich wykonać.

Wiem, że mogę wykluczyć te konkretne klasy z docelowego junit w skrypcie Ant. Ale nie chcę zmieniać pliku kompilacji przy każdej nowej klasie narzędzi, którą dodam. Mogę też zmieniać nazwy zajęć (ale nadawanie klasom dobrych nazw zawsze było moim najsłabszym talentem :-))

Czy jest jakieś eleganckie rozwiązanie tego problemu?


Czy twoje testy działają w Eclipse / NetBeans / twoim ulubionym IDE?
guerda

Używam zaćmienia. Właściwie nie ma w tym problemu, jakoś eclipse nie próbuje uruchomić tych klas. Zastanawiam się jak?
LiorH

Nie wiem, czy zrozumieliśmy twoje pytanie. Przeczytaj ponownie swoje pytanie i prawdopodobnie dodaj więcej informacji.
guerda

1
@guerda: Pytanie wydaje mi się całkiem jasne. Jego zadaniem Ant jest znalezienie klas, które nie zawierają testów, ponieważ filtr wybiera klasę użytkową. Stąd moja odpowiedź, która nadal uważam za całkowicie aktualną.
Jon Skeet

LiorH: Dziękuję za wyjaśnienie, więc moja odpowiedź to marnotrawstwo :)
guerda

Odpowiedzi:


50

Zakładając, że masz kontrolę nad wzorcem używanym do znajdowania klas testowych, sugerowałbym *Testraczej zmianę go tak, aby pasował *Test*. W ten sposób TestHelpernie zostanie dopasowany, ale FooTestbędzie.


1
Nie sądzę, żeby to pomogło, ponieważ przeniósł się na JUnit 4.4 i to nie powinno mieć znaczenia.
guerda

2
Wydaje się, że przegapiłeś sens mojej odpowiedzi. Ma filtr nazw, który określa klasy, które mają być traktowane jako testy. Jeśli zmieni filtr, może łatwo wykluczyć klasy pomocnicze.
Jon Skeet

1
Twoja sugestia jest słuszna, jednak sprawdziłem moje zajęcia z testów i niektóre zaczynają się od testu, a niektóre kończą na teście. brak wyraźnego rozróżnienia między klasami użytkowymi a prawdziwymi klasami testowymi. Czy uważasz, że zaproponowana przez Ciebie konwencja jest dobrą praktyką? (tj. narzędzia zaczynają się od Test, a testy kończą się od Test)
LiorH

4
Prawie konwencją jest dodawanie sufiksu do klas testcase z * Test. Może zajść potrzeba refaktoryzacji, odpowiednio zmieniając nazwy klas testowych, a także zmieniając nazwy pomocników, aby nie używały tej konwencji sufiksu.
Spoike,

2
Zgadzam się ze Spoike - jeśli nie możesz stwierdzić z nazwy klasy, czy to test, czy pomocnik, powinieneś zmienić nazwę klasy. Konwencja jest bardziej „klasa jest testem wtedy i tylko wtedy, gdy kończy się na Test”. Klasy narzędziowe mogą, ale nie muszą rozpoczynać się od testu - to nie ma znaczenia.
Jon Skeet

142

Dodaj adnotacje do swoich klas użytkowych za pomocą @Ignore. Spowoduje to, że JUnit nie będzie próbował uruchamiać ich jako testów.


6
Właściwie nie, nie powinno. @Ignore służy do tymczasowego wyłączania testów.
Alice Young

1
Przepraszam, ale to zły pomysł. Chcesz zacząć dodawać adnotacje do kodu produkcyjnego za pomocą adnotacji związanych z testami tylko dlatego, że mogą one pasować do wzorca testowego? Prawidłową odpowiedzią jest poprawienie nazw klas, jeśli wyzwalają one dopasowywanie wzorców dla testów. I upewnij się, że wzorzec znajduje tylko klasy, które kończą się na Test. To powszechnie przyjęty wzorzec
Kevin M

Tak, to jest złe i nie zdawałem sobie z tego sprawy, dopóki nie złożyłem kolejnego głosu za, którego nie mogę usunąć. Uczyń swoją klasę bazową abstrakcyjną, a JUnit ją zignoruje. Zobacz odpowiedź @ gmoore poniżej.
Ryan Shillington,

83

Mój konkretny przypadek ma następujący scenariusz. Nasze testy

public class VenueResourceContainerTest extends BaseTixContainerTest

wszystko się wydłuża

BaseTixContainerTest

a JUnit próbował uruchomić BaseTixContainerTest. Biedny BaseTixContainerTest próbował tylko ustawić kontener, ustawić klienta, zamówić pizzę i zrelaksować się… stary.

Jak wspomniano wcześniej, możesz dodać do klasy adnotację

@Ignore

Ale to spowodowało, że JUnit zgłosił ten test jako pominięty (w przeciwieństwie do całkowicie zignorowanego).

Tests run: 4, Failures: 0, Errors: 0, Skipped: 1

To mnie irytowało.

Zrobiłem więc BaseTixContainerTest abstrakcyjnym, a teraz JUnit naprawdę to ignoruje.

Tests run: 3, Failures: 0, Errors: 0, Skipped: 0

7
Znacznie lepiej niż@Ignore
neworld

Próbowałem podejście @Ignore i myśli, dobrze, że jest dobre, a potem czytam tę odpowiedź i klepnął się w czoło, „Of oczywiście !”
dnuttle

38

Aby uniemożliwić JUnit utworzenie instancji testowej klasy bazowej, po prostu zrób to

public abstract class MyTestBaseClass { ... whatever... }

(@Ignore zgłasza to jako ignorowane, które rezerwuję na tymczasowo ignorowane testy).


3
Programy uruchamiające JUnit często próbują również utworzyć instancję klas abstrakcyjnych, a następnie kończą się niepowodzeniem z powodu błędu instancji.
Holly Cummins,

Działa idealnie dla moich podstawowych klas testowych
ruX

3
To działa z powodu nazwy (nie kończy się na Test), a nie z powodu modyfikatora abstract. Zmień nazwę klasy na MyBaseClassTest i spróbuje utworzyć instancję, o której wspomniał @HollyCummins (i nie powiedzie się)
Hutch

W moim przypadku tak powinno być protected abstract class.
Mystic Lin

18
  1. Jeśli jest to Twoja podstawowa klasa testowa, na przykład AbstractTest, a wszystkie testy ją rozszerzają, zdefiniuj tę klasę jako abstrakcyjną
  2. Jeśli jest to klasa Util, lepiej usuń * Test z klasy zmień nazwę, to jest MyTestUtil lub Utils itp.

10

Zachowaj ostrożność, używając uzupełniania kodu IDE, aby dodać import dla @Test.

Musi być, import org.junit.Testa nie import org.testng.annotations.Testna przykład. Jeśli zrobisz to drugie, pojawi się błąd „brak uruchomionych metod”.


Powinien to być raczej komentarz niż odpowiedź.
Swaranga Sarma

3
Nie rozumiem dlaczego. To prawidłowe rozwiązanie.
Sridhar Sarnobat

4
Intellij Idea 2017 mieszał mi w głowie, importując org.junit.jupiter.api.Testzamiast tego! ale dzięki tobie jest już rozwiązany
AmiNadimi

Dziękuję bardzo, byłem zdezorientowany podczas otrzymywania problemu „brak dostępnych metod”.
Peter S.

7

Mrówka ma teraz skipNonTestsatrybut, który został zaprojektowany, aby robić dokładnie to, czego szukasz. Nie ma potrzeby zmieniania klas bazowych na abstrakcyjne lub dodawania do nich adnotacji.


2
Wygląda na to, że skipNonTestsatrybut jest dostępny tylko w mrówce 1.9+, a szkoda, bo wygląda niesamowicie użytecznie. Wyklucza również abstrakcyjne nadklasy testowe.
Holly Cummins,

4

A co z dodaniem pustej metody testowej do tych klas?

public void avoidAnnoyingErrorMessageWhenRunningTestsInAnt() {
    assertTrue(true); // do nothing;
}

8
ale to fałszywie zwiększa liczbę testów, które mamy :) nie to jest wielka sprawa
Sudarshan

1

W Twojej klasie testowej, jeśli została napisana import org.junit.jupiter.api.Test; usuń go i napisz import org.junit.Test; W tym przypadku też mi się udało.


1
zadziwiające, zadziałało. wykonałem ręcznie w wierszu poleceń systemu Windows. jednak innym problemem jest to @BeforeAlli @AfterAllnie są one uruchamiane.
BingLi224

pozornie JUnit4 działał (z @BeforeClassi @AfterClass, ale JUnit5 nie. Źródła
BingLi224

0

Miałem również do czynienia z podobnym problemem („brak metod do uruchomienia…”) przy uruchamianiu najprostszego z prostego fragmentu kodu (przy użyciu @Test, @Before itp.) I nigdzie nie znalazłem rozwiązania. Używałem Junit4 i Eclipse SDK w wersji 4.1.2. Rozwiązałem mój problem, używając najnowszego zestawu Eclipse SDK 4.2.2. Mam nadzieję, że pomoże to ludziom, którzy borykają się z podobnym problemem.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.