Testy jednostkowe procedur przechowywanych

44

Długo się nad tym zastanawiam.

Podstawowe pytanie brzmi: jak testować jednostkowo procedury składowane?

Widzę, że mogę stosunkowo łatwo ustawić testy jednostkowe dla funkcji w sensie klasycznym (to znaczy, że otrzymują zero lub więcej argumentów i zwracają wartość). Ale jeśli wezmę pod uwagę rzeczywisty przykład pozornie prostej procedury wstawiania gdzieś wiersza, z kilkoma wyzwalaczami, które robią to i to przed lub po wstawieniu, nawet zdefiniowanie granic „jednostki” jest dość trudne. Czy powinienem przetestować tylko INSERTsiebie? Myślę, że to dość proste - o stosunkowo niskiej wartości. Czy powinienem przetestować wynik całego łańcucha wydarzeń? Oprócz pytania, czy jest to test jednostkowy, czy nie, zaprojektowanie odpowiedniego testu może być dość uciążliwym zadaniem, a po drodze pojawi się wiele dodatkowych znaków zapytania.

A potem pojawia się problem ciągłej zmiany danych. W przypadku UPDATEwpływu na więcej niż kilka wierszy, każdy potencjalnie dotknięty wiersz musi zostać w jakiś sposób włączony do przypadków testowych. Dalsze trudności z DELETEsi itd. I tak dalej.

Jak więc przeprowadzasz testowanie procedur przechowywanych? Czy istnieje próg złożoności, w którym staje się całkowicie beznadziejny? Jakie zasoby są potrzebne do konserwacji?

EDYCJA Jeszcze jedno małe pytanie, oparte na odpowiedzi AlexKuzniecowa: Czy istnieje próg, poniżej którego jest całkowicie bezużyteczny?

dezso
źródło

Odpowiedzi:

32

Robimy to od prawie pięciu lat i uważamy, że wyraźne testowanie modyfikacji jest zdecydowanie wykonalne, ale jest dość powolne. Poza tym nie możemy łatwo uruchomić takich testów jednocześnie z kilku połączeń, chyba że użyjemy oddzielnych baz danych. Zamiast tego powinniśmy bezwzględnie przetestować modyfikacje - używamy ich do gromadzenia co najmniej niektórych danych testowych i sprawdzania, czy nasze wybrane wyniki zwracają oczekiwane wyniki.

Napisałem artykuł zatytułowany Zamknij te luki: wnioski wyciągnięte z testów jednostkowych T-SQL , a także niektóre posty na blogu

Jeśli chodzi o pytanie „Czy istnieje próg złożoności, w którym staje się całkowicie beznadziejny?”, Złożone moduły wymagają testów znacznie więcej niż prostych.

Aby uprościć konserwację, generujemy oczekiwane wyniki i przechowujemy je w osobnych plikach - to ogromna różnica.

AK
źródło
15

Tak, powinieneś przetestować cały łańcuch zdarzeń jako całość. Tak więc w przykładzie z procedurą, która wstawia się do tabeli i powoduje uruchomienie kilku wyzwalaczy, powinieneś napisać testy jednostkowe, które ocenią procedurę dla różnych danych wejściowych. Każdy test jednostkowy powinien przejść pomyślnie lub nie, w zależności od tego, czy zwraca prawidłowe wartości, poprawnie zmienia stan tabel, tworzy poprawny e-mail, a nawet wysyła poprawne pakiety sieciowe, jeśli ma to na celu. Krótko mówiąc, każdy efekt powinien zostać zweryfikowany.

Masz rację, że projektowanie testów jednostkowych wymaga pewnej pracy, ale większość z nich musi zostać wykonana w celu ręcznego przetestowania jednostki, po prostu zapisujesz pracę wymaganą do przetestowania jednostki, aby w przypadku zmiany w przyszłości testowanie może być równie dokładne i znacznie łatwiejsze.

Zmiana danych sprawia, że ​​testowanie jest trudniejsze, ale nie czyni testowania mniej ważnym i faktycznie zwiększa wartość testowania jednostkowego, ponieważ większość trudności należy przemyśleć tylko raz, a nie za każdym razem, gdy wprowadzana jest zmiana w jednostce. Aby to ułatwić, można zapisać zapisane zestawy danych, wstawki / aktualizacje / skasowania, które są częścią instalacji / porzucenia, oraz operacje o wąskim zakresie. Ponieważ pytanie nie jest specyficzne dla bazy danych, szczegóły mogą się różnić.

Na górnym lub dolnym końcu nie ma progu złożoności, który powinien powstrzymywać cię przed testowaniem lub testowaniem jednostkowym. Rozważ następujące pytania:

  1. Czy zawsze piszesz kod wolny od błędów?
  2. Czy małe jednostki są zawsze wolne od błędów?
  3. Czy w przypadku dużego urządzenia może być błąd?
  4. Ile błędów zajmuje katastrofa?

Załóżmy, że zaczynasz nową pracę i masz za zadanie zoptymalizować małą funkcję używaną w wielu miejscach. Cała aplikacja została napisana i utrzymywana przez pracownika, którego nikt nawet nie pamięta. Jednostki mają dokumentację opisującą normalne oczekiwane zachowanie, ale niewiele więcej. Który z nich wolisz znaleźć?

  • Brak testów jednostkowych w aplikacji. Po dokonaniu zmiany możesz wykonać ręczne testowanie samego urządzenia, aby upewnić się, że nadal zwraca oczekiwane wartości w dokumentacji. Następnie możesz wdrożyć go do produkcji, trzymać kciuki i mieć nadzieję, że zadziała (w końcu zawsze piszesz kod wolny od błędów, a optymalizacja w jednej jednostce nigdy nie wpłynie na inną) lub poświęcisz mnóstwo czasu na naukę, jak cała aplikacja działa, dzięki czemu można ręcznie przetestować każdą jednostkę bezpośrednio lub pośrednio.
  • Testy jednostkowe w całej aplikacji, które są uruchamiane automatycznie codziennie lub na żądanie. Sprawdzają nie tylko normalne wartości wejściowe i ich oczekiwaną odpowiedź, ale także nieprawidłowe wartości i oczekiwane wyjątki. Dokonujesz zmiany i uruchamiasz pakiet testów jednostkowych dla aplikacji, natychmiast zauważając, że trzy inne jednostki nie zwracają już oczekiwanych wyników. Dwa z nich są łagodne, więc dostosowujesz testy jednostkowe, aby to uwzględnić. Trzeci wymaga kolejnego drobnego ulepszenia i małego nowego testu jednostkowego. Po wprowadzeniu zmian cały zestaw testów kończy się powodzeniem, a Ty wprowadzasz zmiany z pewnością.
Leigh Riffel
źródło
1
Po pierwsze, dziękuję za odpowiedź - nie spodziewałem się dalszego postępu w tym pytaniu ... Po drugie, muszę przyznać, że masz rację co do prostych operacji: nawet dwukolumnowe INSERT może powodować błąd. Jeśli jest napisane tak, aby można było dopasować kolejność kolumn do argumentów, może być OK, ale masz rację, znowu: prawdopodobnie lepiej jest trzymać całą aplikację pod kontrolą systemu testowego.
dezso
@dezso To świetne pytanie i koncepcja, która wymaga znacznie większego ujawnienia w świecie baz danych.
Leigh Riffel,
„powinieneś przetestować cały łańcuch zdarzeń jako całość” - to najbardziej sprzeczna z intuicją rzecz, jaką możesz powiedzieć. To nie jest jednostka, jeśli tak jest. Robisz testy integracyjne
Joe Phillips
@Joe Philips - Nazwij to, co lubisz, upewniając się, że procedura, która wykonuje wstawkę i uruchamia kilka wyzwalaczy, robi to, co powinno mieć automatyczne testy.
Leigh Riffel
8

W przypadku PostgreSQL sprawdź pgTAP :

pgTAP to zestaw funkcji bazy danych, które ułatwiają pisanie testów jednostkowych emitujących TAP w skryptach psql lub funkcjach testowych w stylu xUnit.

Frank Heikens
źródło
Widziałem to, dzięki. Czy ktoś ma z tym doświadczenie?
dezso,
Tak, całkiem sporo ludzi w dzisiejszych czasach. Subskrybuj listę mailową, jeśli masz pytania.
teoria
6

Jeśli wolisz, aby testowanie procedur przechowywanych odbywało się wyłącznie w języku SQL, zajrzyj na http://tsqlt.org/

Jest kompatybilny z MS SQL 2005 SP2 i nowszym, a zaletą jest to, że programiści nie muszą znać C # ani innego języka, aby wdrożyć testy.

Istnieją również narzędzia do wykonywania próbnych tabel i widoków, aby pomóc Ci w ponownym uruchomieniu pakietu testowego.

Alain King
źródło