Skonfigurowałem klasę z kilkoma testami i zamiast używać @Beforemetody konfiguracji, która jest wykonywana tylko raz przed wszystkimi testami. Czy to możliwe dzięki Junit 4.8?
Chociaż zgadzam się z @assylias, używanie @BeforeClassjest klasycznym rozwiązaniem nie zawsze jest wygodne. Metoda z adnotacją @BeforeClassmusi być statyczna. Jest to bardzo niewygodne w przypadku niektórych testów, które wymagają wystąpienia przypadku testowego. Na przykład testy oparte na Spring, które służą @Autowireddo pracy z usługami zdefiniowanymi w kontekście Spring.
W tym przypadku osobiście używam zwykłej setUp()metody z @Beforeadnotacją i zarządzam własną flagą static(!) boolean:
privatestaticboolean setUpIsDone =false;.....@Beforepublicvoid setUp(){if(setUpIsDone){return;}// do the setup
setUpIsDone =true;}
Dodając do komentarza Kenny'ego Casona, dlaczego musi być statyczny. Musi być statyczny, ponieważ JUnit tworzy nową instancję klasy testowej dla każdej metody @Test. Zmienna instancji zostanie zresetowana do wartości domyślnej (false) dla każdej instancji, jeśli nie jest statyczna. Zobacz więcej informacji: martinfowler.com/bliki/JunitNewInstance.html
dustin.schultz
2
Działa to z wyjątkiem przypadku, gdy setUp()metoda znajduje się w nadklasie - opublikowali odpowiedź poniżej, próbując rozwiązać ten problem.
Steve Chambers
4
Waham się, czy powiedzieć to komuś, kto ma 84 tys. Przedstawicieli, ale BeforeClass w rzeczywistości nie odpowiada na pytanie: BeforeClass jest uruchamiany na początku każdej klasy testowej. Ale OP poprosił o taki, który uruchamia się „tylko raz przed wszystkimi testami”. Proponowane przez Ciebie rozwiązanie mogłoby to zrobić, ale musiałbyś sprawić, by wszystkie Twoje klasy testowe rozszerzyły klasę „CommonTest” ...
mike gryzoń
1
@mikerodent, IMHO OP zapytał o wszystkie testy w jego przypadku testowym, a nie wszystkie testy ogólnie. Więc twój komentarz jest mniej istotny. Swoją drogą, nie martw się, że powiesz cokolwiek komukolwiek, nawet jeśli ma dobrą reputację. Tak przynajmniej robię :). Moja reputacja była znacznie niższa w sierpniu 2012 r., Kiedy odpowiedziałem na pytanie.
AlexR
Nie działa w moim przypadku, zmienne zainicjowane w konfiguracji są resetowane po każdym teście, więc nie ma sensu inicjować go tylko raz.
@mikerodent Zrozumiałem to pytanie jako „wszystkie testy w klasie” - ale masz rację, może nie być to, czego chciał OP.
assylias
29
JUnit 5 ma teraz adnotację @BeforeAll:
Wskazuje, że metoda z adnotacjami powinna zostać wykonana przed wszystkimi metodami @Test w bieżącej klasie lub hierarchii klas; analogicznie do @BeforeClass w JUnit 4. Takie metody muszą być statyczne.
Wydaje się, że adnotacje dotyczące cyklu życia JUnit 5 w końcu się udało! Możesz odgadnąć, które adnotacje są dostępne, nawet nie patrząc (np. @BeforeEach @AfterAll)
Ma ten sam problem @BeforeClass, co musi static. Rozwiązanie IMO @ AlexR jest ładniejsze.
zengr
@zengr zwykle się z tobą zgadza: jak powiedziałem AlexR, jego rozwiązanie wymaga, aby wszystkie klasy testowe były podklasami z klasy CommonTest, jeśli ma to być uruchomione tylko raz. Ale jest to proste, tak proste, jak to tylko możliwe, i IMHO prawdopodobnie nie powinieneś używać "fantazyjnego" rozwiązania dostarczanego przez framework, gdy prosty mechanizm jest dostępny z języka. Chyba że ma ku temu dobry powód. Ponadto użycie prostej rzeczy, takiej jak jego, z dobrą nazwą typu „robi to, co mówi na puszce”, pomaga w czytelności.
mike gryzoń
Powiedziawszy to, znowu IMHO, wydaje się znacznie więcej uzasadnienia dla posiadania adnotacji „AfterAll”: byłoby bardzo trudne i wymyślone opracowanie mechanizmu wykrywania, kiedy wszystkie testy zostały wykonane. I odwrotnie, oczywiście, puryści prawdopodobnie powiedzą, że nigdy nie powinno się wykonywać „ostatecznego czyszczenia”, tj. Że każde „tearDown” powinno pozostawić wszystkie zasoby w nienaruszonym stanie… i prawdopodobnie mają rację!
mike gryzoń
Czy to działa z Maven, gdzie jest wiele modułów, każdy z własnymi testami?
Mark Boon
@mike gryzonie, w moim przypadku konfigurowanie i niszczenie plików testowych w systemie plików przed / po każdym teście wydaje się prowadzić do zakleszczenia plików. Na razie dotarłem samodzielnie do rozwiązania AlexR do konfiguracji raz. Mam już dwie statyczne flagi, ustawione i brudne. setup () wywołuje cleanup (), jeśli początkowo zostanie wykryty stan brudny lub jeśli błąd konfiguracji prowadzi do stanu brudnego. Aby posprzątać po uruchomieniu testów, uruchamiam je ponownie. Niechlujny, wcale nie idealny, nie w naszym procesie tworzenia. Wciąż szukam lepszego sposobu (jUnit 4.12).
Rebeccah
9
Gdy setUp()jest w nadklasie klasy testowej (np. AbstractTestBasePoniżej), zaakceptowaną odpowiedź można zmodyfikować w następujący sposób:
publicabstractclassAbstractTestBase{privatestaticClass<?extendsAbstractTestBase> testClass;.....publicvoid setUp(){if(this.getClass().equals(testClass)){return;}// do the setup - once per concrete test class.....
testClass =this.getClass();}}
Powinno to zadziałać w przypadku pojedynczej setUp()metody niestatycznej , ale nie jestem w stanie stworzyć odpowiednika tearDown()bez zagłębiania się w świat złożonej refleksji… Nagrody dla każdego, kto może!
Edytować:
właśnie dowiedziałem się podczas debugowania, że instancja klasy jest również tworzona przed każdym testem. Myślę, że adnotacja @BeforeClass jest tutaj najlepsza.
Możesz też ustawić na konstruktorze, klasa testowa jest przecież klasą. Nie jestem pewien, czy to zła praktyka, ponieważ prawie wszystkie inne metody są opatrzone adnotacjami, ale działa. Możesz stworzyć takiego konstruktora:
public UT (){// initialize once here}@Test// Some test here...
Ctor zostanie wywołany przed testami, ponieważ nie są one statyczne.
za pomocą @BeforeAllMethods/ @AfterAllMethodsadnotation można wykonać dowolną metodę w klasie Test w kontekście wystąpienia, w którym dostępne są wszystkie wstrzyknięte wartości.
Dodaj do swojej klasy abstrakcyjnej Base (mam na myśli klasę abstrakcyjną, w której inicjalizujesz sterownik w metodzie setUpDriver () ) tę część kodu:
privatestaticboolean started =false;static{if(!started){
started =true;try{
setUpDriver();//method where you initialize your driver}catch(MalformedURLException e){}}}
A teraz, jeśli twoje klasy testowe będą rozszerzać się z klasy abstrakcyjnej Base -> metoda setUpDriver () zostanie wykonana przed pierwszym @Test tylko JEDEN raz na uruchomienie.
Odpowiedzi:
Chociaż zgadzam się z @assylias, używanie
@BeforeClass
jest klasycznym rozwiązaniem nie zawsze jest wygodne. Metoda z adnotacją@BeforeClass
musi być statyczna. Jest to bardzo niewygodne w przypadku niektórych testów, które wymagają wystąpienia przypadku testowego. Na przykład testy oparte na Spring, które służą@Autowired
do pracy z usługami zdefiniowanymi w kontekście Spring.W tym przypadku osobiście używam zwykłej
setUp()
metody z@Before
adnotacją i zarządzam własną flagąstatic
(!)boolean
:źródło
setUp()
metoda znajduje się w nadklasie - opublikowali odpowiedź poniżej, próbując rozwiązać ten problem.Możesz użyć z
BeforeClass
adnotacji :źródło
TheClassYouWant.class
zamiast wywołania getClass ()? Jest to rzeczywista Java:String.class.getName()
.JUnit 5 ma teraz adnotację @BeforeAll:
Wydaje się, że adnotacje dotyczące cyklu życia JUnit 5 w końcu się udało! Możesz odgadnąć, które adnotacje są dostępne, nawet nie patrząc (np. @BeforeEach @AfterAll)
źródło
@BeforeClass
, co musistatic
. Rozwiązanie IMO @ AlexR jest ładniejsze.Gdy
setUp()
jest w nadklasie klasy testowej (np.AbstractTestBase
Poniżej), zaakceptowaną odpowiedź można zmodyfikować w następujący sposób:Powinno to zadziałać w przypadku pojedynczej
setUp()
metody niestatycznej , ale nie jestem w stanie stworzyć odpowiednikatearDown()
bez zagłębiania się w świat złożonej refleksji… Nagrody dla każdego, kto może!źródło
Edytować: właśnie dowiedziałem się podczas debugowania, że instancja klasy jest również tworzona przed każdym testem. Myślę, że adnotacja @BeforeClass jest tutaj najlepsza.
Możesz też ustawić na konstruktorze, klasa testowa jest przecież klasą. Nie jestem pewien, czy to zła praktyka, ponieważ prawie wszystkie inne metody są opatrzone adnotacjami, ale działa. Możesz stworzyć takiego konstruktora:
Ctor zostanie wywołany przed testami, ponieważ nie są one statyczne.
źródło
Wypróbuj to rozwiązanie: https://stackoverflow.com/a/46274919/907576 :
za pomocą
@BeforeAllMethods
/@AfterAllMethods
adnotation można wykonać dowolną metodę w klasie Test w kontekście wystąpienia, w którym dostępne są wszystkie wstrzyknięte wartości.źródło
Moje brudne rozwiązanie to:
Używam go jako podstawy do wszystkich moich przypadków testowych.
źródło
Jeśli nie chcesz wymuszać deklaracji zmiennej, która jest ustawiana i sprawdzana w każdym podteście, dodanie tego do SuperTestu może zrobić:
źródło
Rozwiązałem ten problem w ten sposób:
Dodaj do swojej klasy abstrakcyjnej Base (mam na myśli klasę abstrakcyjną, w której inicjalizujesz sterownik w metodzie setUpDriver () ) tę część kodu:
A teraz, jeśli twoje klasy testowe będą rozszerzać się z klasy abstrakcyjnej Base -> metoda setUpDriver () zostanie wykonana przed pierwszym @Test tylko JEDEN raz na uruchomienie.
źródło
Użyj metody @PostConstruct Springa, aby wykonać całą pracę inicjalizacyjną, a ta metoda jest uruchamiana przed wykonaniem któregokolwiek z @Test
źródło