Wątek przeniesiony 2019-01-19 23:15 z Nietuzinkowe tematy przez somekind.

[JVM] Framework do dynamicznych testów

0

Przeszukałem sporo stron, popytałem wielu osób i nie znalazłem nic odpowiadającego mi. Także, jeśli chcesz mnie zawstydzić wstawiaj linka z Googla wyklikanego w 5 minut, odpowiadającego na moje pytanie.

Chciałbym stworzyć dynamiczne testy integracyjne najlepiej w języku Kotlin, które odpalałyby się analogicznie tak jak JUnitowe za pomocą Gradle. Zależałoby mi na tym, by na odpowiedź na wywołane zapytanie można było wywołać X testów, a także, aby każdy test mógł zawołać następne Y testów. Widziałbym to tak, że mam sobie klasy, które w konstruktorze przyjmują potrzebne parametry do wykonania testów, a na metodę "run" wywołują wszystkie metody z adnotacją Test. Mógłbym to napisać niby jako zwykły program, tylko wtedy nie miałbym ładnych raportów, tak jak w JUnit. Słyszał ktoś o takim frameworku?

0

Nie wiem jak inni, ale ja zupełnie nie rozumiem jak by to miało wyglądać i działać. Co to jest wywołane zapytanie? Jak to chcesz konfigurować? To ma się odpalać przez gradle/mavena czy jak?

0

Jenkinsem (albo innym CI) mozesz wywolywac tak hierarchicznie testy, o to Ci chodzi? Platforma/jezyk/framework nie bedzie miec znaczenia.

0

Dziwne, nie dostałem powiadomienia o postach pod tym tematem.

@Shalom odpalać powinno się z gradle/mavena, mogę stworzyć test który wywoła mi faktyczne zapytanie sieciowe i przetestuje czy przejdzie poprawnie przez parsowanie odpowiedzi, np taki kod

class HomeTest : BaseTest() {

  private val network by inject<Network>()

  private val productNetwork by inject<ProductNetwork>()

  @Test
  fun `home should load`() {
    val home = network.requestHome().blockingGet()
    home.size `should be greater than` 0
  }

  @Test
  fun `home single and slider boxes content should load`() {
    network.requestHome().blockingGet().forEach { loadBoxContent(it) }
  }

  private fun loadBoxContent(box: Box) {
    when (box) {
      is SliderBox -> network.requestSliderBoxContent(box.id).blockingGet()
      is SingleBox -> network.requestSingleBoxContent(box.id).blockingGet()
    }
  }
}

Fajnie, że przejdzie mi przez to i powie, że 2 testy przeszły. Byłoby super gdyby dało do raportu, że załadowanie większości boxów z testu 2 przeszło, ale na przykład 3 testy załadowania kontentu boxów nie przeszły bo serwer zwrócił dla nich 500. Obecnie muszę wchodzić w logi wywołania testu 2 i sprawdzać co mój klient http wypluł, że się wywaliło.

Jenkins mi obecnie odpala taki test cyklicznie.

0

Czyli ty chyba potrzebujesz, po prostu testów parametrycznych. A najlepiej do przypadku pasuje @DynamicTest z junit 5.

0

W sumie tak, tylko nie znalazłem sposobu by @DynamicTest tworzyć testy na podstawie odpowiedzi z zapytania sieciowego. Jedynie na sztywno wpisane wartości w plik tekstowy, kod.

0

Nie ogarniam. Skoro możesz przeczytać z pliku, to możesz (prawie tak samo) z sieci.

0

Bump, ktoś coś? Podać więcej danych lub przykładów?

0

Czytam, czytam i nie rozumiem jakiej funkcjonalności potrzebujesz.

  1. Przychodzi jakiś rqeuest
  2. Na bazie tego requestu chcesz wykonywać (istniejące?), a może generować (zupełnie nowe) testy i mieć raport?
0
  1. Odpalać/generować zupełnie nowe testy i mieć z nich raport. Podając klasę, która wie jak coś przetestować i parametry (te chciałbym obliczać runtime z response).
0

Hmm, to nie wystarczy wziąć i zrobić własnego TestRunnera, np. w oparciu o JUNita, http://putridparrot.com/blog/writing-a-custom-junit-test-runner/ ?

0

Dla mnie to nadal jest test parametryczny. Bo przecież funkcja serwująca parametry nie musi ich podawać ze statycznej tablicy, może je pobrać skądś, np. z tego twojego requestu.
Chyba że chciałbyś jeszcze sam test tworzyć dynamicznie albo dynamicznie wybierać które testy odpalić? Trudno mi sobie wyobrazić realne zastosowanie.

1

Ja tak właśnie sobie wyobrażam, że z jakiegoś klienta leci request z parametrem TEST_PATTERN=foo.bar.test.XYZ*,bar.baz.ABC* i "coś" ma uruchomić wybrane testy, wygenerować informację o statusie wykonania testów.

Ciężko mi sobie wyobrazić, że autor ma jakieś bloki budulcowe, z których składa "nieznany jeszcze test", ale kto wie ;)

0

@Shalom Chciałbym 2 opcje, mamy bardzo niestabilny backend, który jest konfigurowalny przez CMSa, w każdej chwili ktoś może walnąć błąd konfiguracji. Chciałbym w zależności od kontentu odpalać odpowiednie testy przekazując parametry z kolejnych odpowiedzi na zapytania. Sprawdzając dzięki temu czy zapytania na obecnej konfiguracji działają.

@yarel wolałbym jakiś sprawdzony framework, ale to jest jakaś myśl, nie wiem tylko ile czasu mi zejdzie zanim napisałbym to tak by się nadawało.

Dałem to też do nietuzinkowych tematów na początku, bo nie wydaje mi się to trywialne zagadnienie.

0

Hmm, jeśli chodzi o uruchamianie wybranych testów, to może API Jenkinsa do tworzenia jobów, które z kolei uruchamiałyby np. mavena z pluginem surefire (wspiera JUnit, TestNG), który uruchamiałby wybrane testy i generował raporcik...

https://maven.apache.org/surefire/maven-surefire-plugin/examples/single-test.html

0

Jeśli jest tylko taka możliwość, to super gdyby można było to odpalić za pomocą gradle/mavena lokalnie bez Jenkinsa. Jenkins by sobie odpalał cyklicznie takie testy z pomocą gradle/mavena.

1

@viader nadal nie bardzo rozumiem po co. Zróbcie kilkaset porządnych testów backendu e2e i po prostu odpalajcie je cyklicznie co kilka minut. Po co robić jakieś cyrki z odpalaniem wybranych testów z jakąś konfiguracją generowaną na postawie odpowiedzi z aplikacji, kiedy można po prostu odpalić wszystkie testy?

0

Jak dla mnie, ktoś kto wie, które testy mają być uruchamiane tworzy Joba w Jenknsie (używając np. curla, wgeta czy czego tam chce) i przekazuje parametry (grupy testów do wykonania), Jenkins odpala testy via maven i wykonywane są tylko grupy testów.

Nie rozumiem jak Jenkins cyklicznie miałby odpalać testy, skoro nie wiedziałby które? Bo co wyzwalałoby wykonanie określonej grupy testów? Chyba, że w jobie miałbyś na sztywno zapisane, np. "wykonaj tylko testy na literkę A".

Mavena można uruchomić programowo i przekazać mu "goals" do wykonania, razem z parametrami typu: -Dtest=pattern1,pattern2,pattern3.
http://maven.apache.org/shared/maven-invoker/usage.html

Z gradle nie korzystam, więc nie wiem.

0

Mamy aplikację mobilną, użytkownik dostaje określoną treść i może przeglądać określony kontent jaki dostaje po wejściu w aplikację. Często coś nie działa, bo backend/konfiguracja ma błędy. Jako zespół mobilny potrzebujemy napisać testy, które będą nam mówiły czy zapytania idące w tej chwili do backendu (takie jakie może wywołać użytkownik w tej chwili) działają. Nie mamy dostępu do kodu backendu, ale zgłoszone błędy muszą nam poprawiać.

Tak więc mamy sceniarusz:

  1. Użytkownik wchodzi na home
  2. Dostaje response z kontentem
  3. Może wejść teraz w ekrany promocji lub konkretne produkty
  4. Żeby sprawdzić czy faktycznie może tam wejść trzeba wywołać requesty dla produktów/stron promocyjnych, bo jak zejdzie zły response to apka się wywali użytkownikowi
  5. Często nie działa tylko pojedyńcza strona/produkt przez błędy konfiguracji
0

o_O A ja myślałem że to był żart że w Javie o błędach mówi ci kompilator a w PHP klient...
W normalnym życiu takie rzeczy się testuje ZANIM wejdą na produkcje. Developer pisze test e2e pod ten konkretny przypadek i dopiero jak działa na teście, to wchodzi na produkcje.

0

Niestety... Także ktoś coś wie?

0

Ach, czyli robicie development jakiejś apki i jesteście zależni od zewnętrznego serwisu. Jak Wam zgłoszą błąd, to nie wiadomo czy to błąd, czy brak serwisu? I stąd ten pomysł na "dynamiczne testy"?

0

Raczej chcemy wiedzieć o błędach backendu zanim klienci nam je wyślą w słowach - "Apka nie działa, do d**y". Także potrzebujemy sami napisać testy integracyjne o dynamicznej konfiguracji w zależności od obecnego kontentu, bo kontent jest dynamiczny i ciągle zmieniany.

0

Problem kojarzy mi się raczej z monitorowaniem dostępności usług, a nie testami integracyjnymi.

W takiej sytuacji to zwykły SOAP UI i jakiś projekt weryfikujący URLe nie rozwiązuje problemu? Ewentualnie jakieś rozwiązanie oparte o Nagiosa/Zabbixa?

--edited: Jak chcecie działać prewencyjnie, to zakłądam, że jak coś nie działą, to trzeba podnieść alarm i zgłosić do odpowiedniego zespołu. Stąd te nagiosy/zabbixy.

0

Pisaliśmy w SoapUI (darmowej wersji), ale szybko okazało się, że poziom skomplikowania i hackowania niektórych rozwiązań w testach, przez to utrzymania i rozwijania, przekroczył zyski.

Obecnie mamy wydzielony moduł sieciowy z aplikacji mobilnej jako artefakt na repozytorium mavenowym. Dlatego bardzo łatwo jest pisać te testy w JVM, mamy też za darmo mechanizmy OAuth 2 i wszystkie headery które musi wysyłać apka mobilna, utrzymanie sesji itp. O Nagios/Zabbix niesłyszałem, spróbuję doczytać.

0

Z tego co zrozumiałem, to backend dla niektórych produktów może być niepoprawnie skonfigurowany. Co oznacza w praktyce ta niepoprawna konfiguracja i czym się objawia? Przychodzi zły JSON albo jakaś niepoprawna kombinacja pól? Nie rozumiem, po chcesz robić taką dynamiczną parametryzację, jak opisujesz. Można napisać zwykłe testy uderzające w prawdziwe endpointy, na którejś z warstw aplikacji, żeby sprawdzić poprawność danych.

0

Na przyklad przychodzi miniatura produktu, ale przy zaciagnieciu calego produktu aplikacja dostaje blad.

W tej chwili mamy to jako zwykle testy, ale musze recznie patrzec w to co poszlo nie tak bo raporty sa bardzo ogolne. Typu nie przeszedl test ladujacy wszystkie produkty z home. Fajniej byloby "podczas ladowania wszystkich produktow z home, wywalily sie testy pobierajace takie i takie idki produktow, ale inne przeszly." Albo promocja z produktu XYZ ktory jest dostepny na home nie laduje sie.

Idealnie byloby by raporty pokazywaly, request z home powiodl sie, dane wygladaja na wstepnie poprawne. Poniewaz home mial 10 produktow to uruchomil on 10 testow dla kazdego produktu. Teraz kazdy test produktu sprawdza czy dobrze sie on zaciaga i przykladowo kazdy mial 3 promocje wiec kazdy test produktu odpala 3 testy promocji.

1

No to ja bym skorzystał z jakiegoś frameworka do testowania specyfikacji. Na przykład KotlinTest. Wtedy możesz napisać taką specyfikację jak poniżej. Mój przykład nie ma dużo sensu i to blockingGet() boli, ale chcę tylko pokazać, że można spokojnie pisać skomplikowane scenariusze, które generują ładne raporty. W moim przypadku najpierw sprawdzi kontrybutorów do Retrofita, potem przeleci po wszystkich użytkownikach i dla każdego wykona odpowiedni test a potem wyniki zostaną zagregowane. Poza tym KotlinTest jest bardzo fajny, bo można ładnie kombinować z kontekstem testów i pisać testy w różnych stylach.

class GitHubApiSpecification : DescribeSpec({
  describe("Retrofit contributors") {
    val github = WebApi.github
    val contributors = github.contributors("square", "retrofit").blockingGet()
    it("do exists") {
      contributors shouldHaveAtLeastSize 0
    }

    for (contributor in contributors) {
      it("and contributor ${contributor.login} has at least 2 repositories") {
        val repositories = github.repos(contributor.login).blockingGet()
        repositories shouldHaveAtLeastSize 2
      }
    }
  }
})
0

Jutro przetestuje interesuje mnie wygląd raportu. Zastanawia mnie czy czasem testy sie nie przerwa gdy poleci wyjatek/blad zapytania. A może ta lambda zlapie go i ladnie zraportuje, jutro sobie zobaczę :)

Na początku odrzucilem cucumbera (o KotlinTest nie wiedzialem :)) bo jak w JUnicie nie widzialem w nim sposobu by dla przykladu z GithubApiSpecification odpalic GithubRepoSpecification. Takie cos pozwoliloby na duza reuzywalnosc jednego testu w roznych kontekstach.

0

@Michał Sikora:
Przetestowałem, fajnie generuje raport gdzie pod 1 testem może być N testów. Dalej utrudniające jest, że każdy z testów z pierwszego zagnieżdzenia nie może zawołać własnych testów.

+ lepsze od JUnita, najlepsze z tego co zostało podane dotychczas, zamieni JUnita :)
- dalej trochę hackowanie, bo jeden poziom zagnieżdzenia to trochę mało w moim wypadku

Przykład wywołania:
https://imgur.com/a/paLIijY

Jeśli ktoś zna coś jeszcze lepszego niech daje znać.

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