Jedyną prawdziwą logiką jest składnia zapytania dla zewnętrznego interfejsu API. Nie chcę testować, czy wysyła zapytanie do interfejsu API, chcę przetestować, czy wysyła zapytanie w taki sposób, aby zwrócone zostały prawidłowe dane. Na przykład jakiś pseudo-kod:
function retrieve_related_data(id)
{
query = "[potentially long, syntactically complex query that
uses param id to get some data]";
results = api_wrapper.query(query);
return results;
}
Bardziej konkretny przykład z gotowym interfejsem API:
function retrieveLifeSupportingObjectsWithinRegion(id)
{
query = "
within region(" + id + ") as r
find objects matching hydration>0 and temp_range has 75
send name, id, relative(position, r)
";
results = astronomicalObjectApiWrapper.query(query);
return results;
}
Kwerenda ma niestandardową składnię interfejsu API i jest złożona oraz istnieje wiele sposobów na uzyskanie takich samych lub podobnych wyników. Celem tej funkcji nie jest uzyskanie danych identyfikowanych przez, id
ale znalezienie podzbioru innych danych opartych na rozmytej relacji z danymi identyfikowanymi przez to, id
który spełnia również kilka innych wymagań. Pozostałe wymagania są zawsze takie same niezależnie od, id
ale mogą ulec zmianie w miarę modyfikowania systemu. Na przykład, jeśli przykładowy interfejs API dodał obsługę informacji o grawitacji, możemy chcieć zmienić zapytanie, aby użyć grawitacji również do udoskonalenia wyników. A może wymyślimy bardziej skuteczny sposób sprawdzenia zakresu temperatur, ale to nie zmienia wyników.
Chcę przetestować, że dla danego wejścia id
zwracany jest prawidłowy zestaw danych. Chcę to przetestować, aby jeśli ktoś pomieszał kwerendę w taki sposób, że nie zwraca już poprawnych danych w związku z id
tym, że zakończy się ona niepowodzeniem, ale chcę również, aby ludzie mogli modyfikować zapytanie w celu dopracowania go bez konieczności modyfikacji test.
Opcje, które rozważałem:
Mógłbym usunąć interfejs API, ale byłoby to albo zbyt proste (sprawdź, czy
id
jest ono obecne w zapytaniu, a następnie zwrócił oczekiwany zestaw danych, jeśli jest, lub nieoczekiwany zestaw, jeśli nie jest), zbyt kruche (sprawdź, czy ciąg zapytania jest dokładnie to, co znajduje się w funkcji) lub zbyt skomplikowane (sprawdź, czy użyte zapytanie jest poprawne pod względem składniowym i spowoduje zwrócenie poprawnych danych).Mógłbym przesłać zapytanie do prawdziwego interfejsu API, ale oczekiwane wyniki mogą się zmieniać w czasie wraz ze zmianami danych w systemie zewnętrznym, poza kontrolą systemu testowego.
Mógłbym spojrzeć na konfigurację instalacji prawdziwego interfejsu API w celu kontrolowania posiadanych danych, ale to jest duży wysiłek.
Opieram się na # 2 i robię to raczej test integracyjny, który nie jest uruchamiany często, i widzę, jak często zmiany w danych systemu zewnętrznego powodują przerwanie testu. Myślę, że na razie byłoby to najprostsze, ale zastanawiam się, czy istnieją alternatywy, o których nie myślę, ani lepsze sposoby rozwiązania tego problemu. Wszelkie porady będą mile widziane.
źródło
Odpowiedzi:
Może się wydawać, że sprawdzając zewnętrzną odpowiedź API, testowalibyśmy naszą funkcję, ale nie byłoby to do końca prawdą. W jakiś sposób testowalibyśmy zewnętrzny interfejs API i środowisko, w którym działa interfejs API.
Nasze testy powinny zostać zaadresowane, aby zagwarantować oczekiwane zachowanie napisanego przez nas kodu, a nie kodu napisanego przez strony trzecie.
Do pewnego stopnia musimy ufać właściwej funkcji interfejsów API i bibliotek, na których polegamy. Na przykład zwykle nie testujemy implementowanych komponentów środowiska.
Dlaczego tak mówię?
Co by tu przetestowano? Jak powiedziałeś, dane i ich poprawność nie są pod naszą kontrolą, dlatego ograniczamy sukces fazy testowania do zewnętrznego agenta, na który nie mamy żadnej kontroli. Testy te są kandydatami, aby stać się niedeterministycznymi i ostatecznie, nie chcemy tego rodzaju testów w naszym procesie budowy .
Inną kwestią jest zatwierdzenie umowy. Uważam, że bardzo przydatny jest test umowy 1, aby upewnić się, że integracja nadal działa zgodnie z oczekiwaniami, przed wydaniem lub wdrożeniem.
Co jeśli zapytanie jest prawidłowe, ale dane są nieprawidłowe z powodu błędów w interfejsie API? Nie tylko dane są poza naszą kontrolą. Logika też jest.
Pomóc może w tym wdrożenie testów funkcjonalnych lub kompleksowych testów. Możesz rozwiązać ten test, aby sprawdzić poprawność określonych ścieżek wykonania, aby jeśli API zwróciły nieprawidłowe dane, prawdopodobnie spowodowałoby to nieoczekiwane zachowanie i wyniki. Z drugiej strony spodziewałbym się, że interfejs API zgłasza błędy, jeśli moje zapytania były źle sformatowane.
Sugeruję wdrożenie narzędzia do tego celu. Może to być tak proste, jak:
Lub coś bardziej wyrafinowanego. Na przykład samodzielny klient.
W każdym razie funkcja pod pytaniem, warta dwóch rodzajów testów:
Test jednostkowy. Jak już powiedziałeś, musisz zetrzeć zewnętrzny interfejs API, ale taki jest cel testów jednostkowych. Testowanie naszego kodu izolującego zależności.
Test integracyjny. Sprawdź, czy kod nie tylko wysyła prawidłowe żądanie, ale także odpowiednio obsługuje treść odpowiedzi, błędy, przekierowania itp. Wykonaj testy dla wszystkich tych przypadków, ale nie testuj danych .
Uwaga dodatkowa: Twoje pytanie jest podobne do pytania: w jaki sposób testujesz instrukcje SQL aplikacji?
Powiązane pytania :
1: Być może zainteresuje Cię odpowiedź @ DocBrown na ten temat
źródło
Widziałem kontrole jednostek, które sprawdzają, czy wygenerowany ciąg zapytania odpowiada oczekiwanej wartości.
Jednak. Moim zdaniem było to ograniczone użycie. Składnia zapytania była skomplikowana, prawdopodobnie błędna, więc A istniały nieskończone możliwości sprawdzania, a B, nawet jeśli łańcuch został „poprawnie” wygenerowany, nieoczekiwane wyniki można było zwrócić w środowisku na żywo.
Myślę, że masz rację, wybierając opcję 2. uruchom testy integracji z instancją na żywo.
Dopóki nie są destrukcyjne, są to pierwsze testy, które powinieneś napisać, ponieważ wychwytują, ale nie identyfikują przyczyny, żadnego błędu.
Przejście na opcję 3 „wdrożenie instancji testowej z danymi zastępczymi” jest lepsze. Nie ma to jednak wpływu na pisanie testów, ponieważ możesz skierować te same testy na serwer testowy, jeśli i kiedy będzie to dobre wykorzystanie czasu na jego wdrożenie.
źródło
Zależy to od interfejsu API, ale jeśli to możliwe, wybierz opcję nr 3 (prywatna instancja testowa).
Stubbing API (opcja nr 1) jest najgorszą opcją z powodów, o których wspomniałeś, a wybranie tej trasy prawdopodobnie wyrządzi więcej szkody niż pożytku (dużo straconego czasu).
Uruchamianie z prawdziwym API (opcja 2) powoduje, że testy są niestabilne i niewiarygodne, a po kilku fałszywych trafieniach ludzie przestaną ich używać. Dane mogą nie tylko ulec zmianie, ale usługa może również nie działać. Moim zdaniem jest to podobne do braku testów zapytań i polegania na testach integracyjnych / systemowych w celu znalezienia problemów. To powiedziawszy, jeśli dane API rzadko się zmieniają, a sam interfejs API prawie zawsze działa, może to być opłacalna opcja. Większość interfejsów API nie pasuje do tego opisu.
Ostatecznie sprowadza się to do tego, jak ważne i złożone są te zapytania: jeśli jest ich więcej niż kilka, a niektóre z nich są na tyle złożone, że odczuwasz potrzebę ich przetestowania, zainwestowałbym w utworzenie prywatnej instancji do testowania . Opłaci się tak jak inne testy jednostkowe.
źródło