Przyśpieszyć springowe testy

0

Same testy trwają malutko, każdy < 1 s., ale każda klasa testowa z dodanym @SpringBootTest ładuje się po kilka sekund.

Co mogę zrobić by ten spring odpalał szybciej? Zastanawiałem się nad tym czy np. nie zrobić 1 klasy testowej z tą adnotacją i każda klasa testowa by dziedziczyła ją.

2

Pierwsze, co mi się nasuwa:

  • bazowa klasa testowa lub adnotacja zawierająca interesujące Cię inne adnotacje to ogólnie dobry pomysł
  • jeśli tylko się da unikaj @MockBean @SpyBean i @DirtiesContext aby nie powodować przeładowania kontekstu springowego między klasami testowymi
  • zastanów się, czy nie warto przepisać testów mocno korzystających z @MockBean etc. na unitowe (w sensie: bez springa)
  • jeśli korzystasz np. z Testcontainers, upewnij się że kontener jest stawiany tylko raz (w przypadku małych rzeczy, jak Redis, nie ma to wielkiego znaczenia, za to dla takiej Kafki jest odczuwalne)
1
  • Może po prostu customowa adnotacja @CustomTest która ma najczęstsze komponenty.
@Retention(RetentionPolicy.RUNTIME)
@Import(MyCustomMockBeans.class)
@AutoConfigureMockMvc
@SpringBootTest
public @interface CustomTest {
}
  • Testy bez wstającego kontekstu

I w sumie wszystko co @MW600

1

Co mogę zrobić by ten spring odpalał szybciej? Zastanawiałem się nad tym czy np. nie zrobić 1 klasy testowej z tą adnotacją i każda klasa testowa by dziedziczyła ją.

This. Tylko pamiętaj żeby mieć jakieś @After i sprzątać po każdym teście.

0

Jednak ten extends MyApplicationTest w każdej klasie testowej zamiast @SpringBootTest nie pomoże, bo mam jeszcze @EnableAutoConfiguration i tego nie da się już dać do MyApplicationTest
Żadnych mocków czy test containers nie mam. Tylko @SpringBootTest i @EnableAutoConfiguration

0

@NamingException: no dobra ale dokładnie po co? :) W sensie co chcesz tą adnotacją osiągnąć?

0

wczytuje mi np. ustawienia mongo czy te z propertasów chyba, nie wiem, bo jak to wywalam to sypie się to.
Dokumentacja:

By default, once loaded, the configured ApplicationContext is reused for each test. 

https://docs.spring.io/spring-framework/docs/current/reference/html/testing.html
ech...

2

Cargo cult at it's finest xD Przecież i tak masz gdzieś w tym kodzie @SpringBootApplication które robi dokładnie to samo. Powinno być jakieś:

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Main.class)

gdzie Main.class to twoja klasa z @SpringBootApplication.

Czy ty chcesz zmieniać properties per test? Wydaje się to bardzo dziwnym pomysłem. Zobacz sobie: https://github.com/Pharisaeus/almost-s3/tree/master/test/src/test/java/net/forprogrammers/almosts3/test tutaj kontekst wstaje raz i jak zrobisz kolejne klasy extendujące BaseIT to nadal będzie raz.

0

Zależy co te testy testują, jak dla mnie to jeśli nie ma jakiejś wielkiej potrzeby to może trzeba ten Springowy kontekst do testów wywalić w cholerę i jechać po testy samym JUnitem.

0

Już wiem po co ten @EnableAutoConfiguration,bo w nim wywalam auto konfigurację Kafki, której nie chcę do testów przez @EnableAutoConfiguration(exclude = KafkaAutoConfiguration.class).
To co pewnie jakoś w pom.xml mavena bym musiał to excludować?

0

A nie prościej dać jakieś @TestPropertySource(locations = "classpath:application-test.properties") i tam ustawić jakiś fejkowy endpoint dla tej kafki? Albo jakiegoś mocka który udaje kafke? Albo kafke z testcontainers? Trudno powiedzieć co ty chcesz robić, skoro z jednej strony odpalasz aplikacje a z drugiej jednak nie do końca :D
Możesz też dać classes = FakeMain.class i ten FakeMain zrobić żeby ładował co tam sobie chcesz.

0

Robię na embedowej kafce, żeby każdy mógł to odpalić bez kafki zewnętrznej, dlatego wywalam tę prawdziwą.
Dodałem do propertasów:
spring.autoconfigure.exclude=org.apache...
i teraz nie muszę już używać @EnableAutoConfiguration(exclude=...)
zszedłem tym sposobem tylko o 20% jeśli chodzi o czas wykonywania...

0

zszedłem tym sposobem tylko o 20% jeśli chodzi o czas wykonywania...

No to pytanie co w takim razie tyle trwa w tych testach skoro aplikacja wstaje ci teraz już tylko raz?

0

@Shalom: Wstaje wiele razy bo są jeszcze mockMvc i skakanie po profilach. Ale troche rzadziej już wsaje niz wczesniej.

2

No to już nic nie poradzę jak robisz jakieś cyrki w tych testach. Nie bardzo rozumiem co one mają na celu, ale znów: nie znając projektu trudno coś doradzić. mockMvc to rak, ale wątpie zeby w czymś tu przeszkadzał, ot tyle że nie testujesz pewnego fragmentu projektu. Ja bym użył normalnego własnego programowego klienta. Jak chcesz zmieniać profile to cudów nie ma, musisz wystartować kolejny raz, ale moze w takim razie zrób sobie suity testów per profil?

0

bo jest @AutoConfigureMockMvc i on powoduje ładowanie całego contextu od nowa.

A jak można zrobić bez @Profili i bez @ComponentScan, żeby Spring ignorował wybranego Beana w testach?

@Service
@Profile("!test")
class MyService {

}

@ActiveProfile("test")
@SpringBootTest
ComponentTest {
    @Test
    void shouldDoSmoething() {

    }
}
1

Ale co to są w ogóle za testy skoro chcesz ignorować część konfiguracji? :D Jaki to ma sens? Przecież idea testów jest taka żeby testować kod którego używasz w aplikacji produkcyjnej. Jasne, można sobie podmienić bazkę na h2, można zamiast jakiegoś zewnętrznego serwisu dać wiremocka, ale to tyle. Kod twojej aplikacji powinien działać możliwie tak jak działa na produkcji, inaczej to zwyczajnie nie ma sensu.
No ale skoro (wydaje ci się że) musisz, to niech będzie taki profil, ale to i tak przecież konfigiruje się raz.

bo jest @AutoConfigureMockMvc i on powoduje ładowanie całego contextu od nowa.

To je wywaj bo to rak i do niczego nie potrzebne. Tylko przeszkadza bo nie testujesz znowu prawdziwego kodu tylko się wpinasz gdzieś "na pałe". Weź łaskawie sobie property server.port, zrób normalnego HttpClienta na localhost:port i uderzaj jak człowiek do tej aplikacji, tak jak będzie uderzać ktoś kto z niej korzysta. Mniej adnotacji, mniej magii, więcej rozumu. Jeszcze raz odsyłam do githuba którego linkowałem wyżej.

0

Bo to są testy unitowe to nie potrzebuję całej apki stawiać. Potrzebuję tylko niektórych rzeczy.
Jak ustawię normalnego http clienta jak człowiek to nie będą to jednostkowe, nie odpalę ich bez internetu i bez dostępów do środowiska.

0

Skąd wytrzasnąłeś ta potrzebę środowiska czy internetu? Aplikacja wstaje na localhoscie i do niej uderzasz http clientem, tak samo na localhoscie stoją zmockowane zewnętrzne zależności.

0

nie odpalę ich bez internetu i bez dostępów do środowiska.

Co? xD Ustawiasz w test properties adresy na wiremocki itp i nie trzeba żadnych "dostępów". Jeszcze raz odsyłam do githuba który linkowałem...

Bo to są testy unitowe to nie potrzebuję całej apki stawiać.

No ale stawiasz kontekst springa, czyli stawiasz całą apkę, nawet jeśli jakoś dziwnie wykastrowaną z jakimiś wyłączonymi beanami (co jest głupie). To co robisz nie wygląda na testy jednostkowe ;) Wygląda na jakiś WTF pomiędzy testem jednostkowym a integracyjnym. I ja się domyślam czemu tak robisz - pewnie kod jest zrypany i masz np. 50 zależności w jakimś serwisie i masz problem zrobić w teście new MyService() żeby napisać testy jednostkowe tego serwisu, więc próbujesz to "obejść" stawiając kontekst aplikacji...

1 użytkowników online, w tym zalogowanych: 0, gości: 1