W tej lekcji dokończymy temat Singletona i poruszymy sobie temat, o którym wspomniałam w poprzedniej lekcji, czyli synchronizacja w Singletonie.
Uwaga: plik z projektem testowym, na którym pracujemy w lekcjach dotyczących POM wymaga uzyskania dostępu. Dostaniesz go tutaj.
Poruszymy temat sekcji krytycznej oraz bloku synchronizowanego. Zobaczysz też co daje dodanie przed zmienną słówka volatile. Gdy już zamkniemy temat Singletona wrócimy do konfiguracji i przerobimy tą klasę na taką, która nie używa Singletona i pokażę Ci jak to ładnie rozwiązać.
Dodatkowo posłużymy się adnotacją @TestInstance(Lifecycle.PER_CLASS) w JUnit 5. Adnotacja ta sprawi, że wszystkie metody testowe będą korzystały z tej samej instancji klasy testowej. Domyślnie, gdy nie dodamy tej adnotacji, nowa instancja jest tworzona dla każdej metody testowej. Oznacza to, że naszych testów nie będziemy mogli w przyszłości zrównoleglić na poziomie metod, czyli nie będziemy mogli uruchamiać testów w jednej klasie równolegle. Żeby to zrobić będziemy musieli przenieść inicjalizację konfiguracji z BeforeAll to BeforeEach. Natomiast nadal będziemy mogli uruchamiać testy równolegle na poziomie klas (czyli testy z kilku różnych klas testowych nadal będą mogły być uruchamiane równolegle).
Zaktualizowane klasy
- Klasa testowa: PaymentsTests
- Klasa testowa: CartTests
- Klasa testowa: BaseTest
- Klasa Page Object: CheckoutPage
- Klasa Page Object: CartPage
- Klasa Page Object: ProductPage
- Klasa Page Object: CategoryPage
- Klasa Page Object: BasePage
- Klasa Page Object: DemoFooterPage
- Klasa Page Object: HeaderPage
- Klasa Page Object: OrderReceivedPage
- Klasa: DriverFactory
- Enum: Browser
- Klasa: ConfigurationManager (wzorzec Singleton)
- Configuration.properties
Klasa testowa: PaymentsTests
Ukryta treść
Nie masz dostępu do tego kursu. Wykup dostęp albo zaloguj się, by móc zobaczyć pełną lekcję.
Klasa testowa: CartTests
Ukryta treść
Nie masz dostępu do tego kursu. Wykup dostęp albo zaloguj się, by móc zobaczyć pełną lekcję.
Klasa testowa: BaseTest
Ukryta treść
Nie masz dostępu do tego kursu. Wykup dostęp albo zaloguj się, by móc zobaczyć pełną lekcję.
Klasa Page Object: CheckoutPage
Ukryta treść
Nie masz dostępu do tego kursu. Wykup dostęp albo zaloguj się, by móc zobaczyć pełną lekcję.
Klasa Page Object: CartPage
Ukryta treść
Nie masz dostępu do tego kursu. Wykup dostęp albo zaloguj się, by móc zobaczyć pełną lekcję.
Klasa Page Object: ProductPage
Ukryta treść
Nie masz dostępu do tego kursu. Wykup dostęp albo zaloguj się, by móc zobaczyć pełną lekcję.
Klasa Page Object: CategoryPage
Ukryta treść
Nie masz dostępu do tego kursu. Wykup dostęp albo zaloguj się, by móc zobaczyć pełną lekcję.
Klasa Page Object: BasePage
Ukryta treść
Nie masz dostępu do tego kursu. Wykup dostęp albo zaloguj się, by móc zobaczyć pełną lekcję.
(czyli nasza stopka w POM)
Ukryta treść
Nie masz dostępu do tego kursu. Wykup dostęp albo zaloguj się, by móc zobaczyć pełną lekcję.
Klasa Page Object: HeaderPage
Ukryta treść
Nie masz dostępu do tego kursu. Wykup dostęp albo zaloguj się, by móc zobaczyć pełną lekcję.
Klasa Page Object: OrderReceivedPage
Ukryta treść
Nie masz dostępu do tego kursu. Wykup dostęp albo zaloguj się, by móc zobaczyć pełną lekcję.
Klasa: DriverFactory
Ukryta treść
Nie masz dostępu do tego kursu. Wykup dostęp albo zaloguj się, by móc zobaczyć pełną lekcję.
Enum: Browser
Ukryta treść
Nie masz dostępu do tego kursu. Wykup dostęp albo zaloguj się, by móc zobaczyć pełną lekcję.
Klasa: ConfigurationManager (wzorzec Singleton)
Ukryta treść
Nie masz dostępu do tego kursu. Wykup dostęp albo zaloguj się, by móc zobaczyć pełną lekcję.
Configuration.properties
Ukryta treść
Nie masz dostępu do tego kursu. Wykup dostęp albo zaloguj się, by móc zobaczyć pełną lekcję.
Lista lekcji dotyczących budowy Frameworka:
Cześć Ela, mam dwa pytania:
1) Czy klasy BaseTest i BasePage nie powinny być abstrakcyjne?
2) Czy te dwie poniższe linijki z klasy BaseTest można przenieść do metody @BeforeAll? Czy są jakieś przeciwskazania?
[java]
DriverFactory driverFactory = new DriverFactory();
driver = driverFactory.create(configuration);
[/java]
Halko! BasePage powinna być abstrakcyjna, zresztą pokazuję to w lekcjach dotyczących BasePage, taki ze mnie śmieszek widzę, że tutaj tego nie zrobiłam 😀 BaseTest też w zasadzie można, tylko upewnij się, że testy się odpalają poprawnie. Chodzi o to, żeby sprawdzić czy JUnit sobie poradzi z nadrzędną klasą testową, która jest abstrakcyjna.
Co do drugiego pytania: to musi iść do BeforeEach, bo tam tworzymy nową instancję drivera, a chcemy mieć “świeżego” drivera w każdym teście. Używanie tej samej instancji drivera jest niebezpieczną praktyką – mogą Ci zostać jakieś śmieci w sesji po poprzednim teście albo w ogóle driver z różnych powodów może umrzeć i wtedy wszystkie testy umrą też. To by też utrudniło, jeżeli nie uniemożliwiło w przyszłości odpalanie testów równolegle.
Dziękuję 🙂
Cześć,
w tej lekcji dużo zmian jest spowodowanych umożliwieniem późniejszego odpalania testów równolegle.
Czy jest jakaś lekcja gdzie omawiasz konfigurację i odpalanie testów Selenium w JUnit równolegle?
Halko! Nie, nie ma takiej lekcji. Staram się Was jednak przygotować na wypadek, gdybyście musieli kiedyś tak testy pisać. Może kiedyś to zrobię w jakimś mini kursie JUnita.
to ja się już zapisuje na taki kurs :-).
Szukałem w dokumentacji JUnit i znalazłem, że “Parallel test execution is an experimental feature”. Konfiguracja nie jest też tak intuicyjna jak używanie adnotacji i wymaga dodatkowej konfiguracji.
Jakby ktoś jeszcze szukał to zostawiam link:
https://junit.org/junit5/docs/snapshot/user-guide/#writing-tests-parallel-execution
Szukałem trochę materiałów i zauważyłem też, że podejścia są dość różne w JUnit i TestNG.
Cześć,
udało mi się opanować podstawy uruchamiania testów równolegle w JUnit zarówno w terminala z mavena jak i w IntelliJ.
Z zastosowaniem singletona wszystko śmiga, ale po przejściu na użycie @BeforeAll z adnotacją @TestInstance(TestInstance.Lifecycle.PER_CLASS) niestety testy z tej samej klasy uruchamiają się jednowątkowo.
Z użyciem tej adnotacji każda klasa z testami może mieć jeden wątek i jest to dla mnie zrozumiałe po tym jak wytłumaczyłaś jak działa ta adnotacja.
Zastanawiam się jednak czemu nie zmieniłaś w @BeforeAll metody getConfiguration() na statyczną?
W lekcji [od 13:55] tłumaczysz, że po zmianie tej metody na statyczną pole ConfigurationManager configuration też musiałoby być statyczne i dlatego nie możemy zmienić tej metody na statyczną. Ale właściwie dlaczego to pole configuration nie może być statyczne?
Ja usunąłem adnotację @TestInstance(TestInstance.Lifecycle.PER_CLASS), metodę getConfiguration() zrobiłem statyczną i pole ConfigurationManager configuration też oznaczyłem jako statyczne i wszystkie testy mi działają. Wszystkie testy wykonują się prawidłowo i mogę puszczać testy z tej samej klasy wielowątkowo. Uruchamiając testy jednowątkowo też wszystko działa jak należy.
Jest jakiś powód dla którego pole ConfigurationManager configuration nie może być statyczne skoro testy się uruchamiają?
Hej! Trzy razy przesłuchałam fragment od 13:55 do 15:00 i nie mówię tam nic, że pole configuration nie może być statyczne. Na pewno chodzi Ci o ten fragment?
Cześć, może źle Cię zrozumiałem w nagraniu, bo opowiadając podświetliłaś nazwę tego pola i tak to opatrznie zrozumiałem.
W każdym razie czy możesz mi wytłumaczyć czemu nie zdecydowałaś się na zrobienie tego pola statycznym, tylko zastosowałaś adnotację @TestInstance(TestInstance.Lifecycle.PER_CLASS), która ogranicza wykonywanie testów równolegle?
W 14:04 mówisz “Chodzi o to, że tworzymy tutaj obiekt jakiejś klasy, a ta metoda jest statyczna i tak się nie da”. Nie do końca zrozumiałem czy są jakieś przeciwwskazania do oznaczenia metody getConfiguration() i pola configuration jako statyczne?
Nie zdecydowałam się na zrobienie tego pola statycznym, tylko zastosowałam adnotację @TestInstance(TestInstance.Lifecycle.PER_CLASS), bo rozwiązania które przygotowałam (czyli po prostu zamiana singletona na nie singletona) nie planowałam użyć w statycznym kontekście. Nie umiem Ci teraz powiedzieć, czy tutaj mogą się pojawić jakieś nieprzewidziane konsekwencje. Gdybym planowała zrobić to pole statycznym, to zbudowałabym całość od nowa mając takie założenie w głowie.
Dzięki za wyjaśnienie