Bazy danych i testy jednostek / integracji

25

Rozmawiałem z kimś na temat testów jednostkowych / integracyjnych z aplikacjami internetowymi i nie zgadzam się co do 1 podstawowego pomysłu. Problem polega na tym, że osoba, z którą rozmawiam, uważa, że ​​baza danych, na której działa test jednostkowy, powinna mieć w niej wstępnie wypełnione dane i uważam, że powinna ona być całkowicie pusta przed i po wykonaniu testów.

Moje obawy dotyczące wstępnie wypełnionych danych w bazie danych polegają na tym, że nie ma sposobu, aby upewnić się, że dane są utrzymywane w dobrym stanie. Same testy będą tworzyć, usuwać i modyfikować dane w bazie danych, więc naprawdę nie widzę, jak dobrze mieć dane w bazie danych przed rozpoczęciem testów.

Wydaje się, że najlepszym sposobem testowania funkcjonalności bazy danych byłyby następujące ustawienia:

  1. W fazie „instalacji” przed uruchomieniem testu najpierw obetniesz wszystkie tabele w bazie danych
  2. Następnie wstaw wszystkie dane potrzebne do przypadków testowych, które zamierzasz uruchomić
  3. Następnie uruchom i zweryfikuj przypadki testowe
  4. Następnie w fazie „porzucania” ponownie obcinamy wszystkie tabele w bazie danych

Nie widzę innego lepszego sposobu, aby upewnić się, że dane, na których testujesz, są dobrym testem.

Czy coś mi umyka? Czy to nie jest najlepszy sposób na przetestowanie funkcjonalności związanej z bazą danych? Czy istnieje korzyść z posiadania wstępnie wypełnionej bazy danych, która zawsze istnieje w bazie danych (nawet przed rozpoczęciem testów lub po ich zakończeniu)? Każda pomoc w pomysłach na wyjaśnienie mojego procesu w inny sposób, aby lepiej przedstawić mój punkt widzenia, byłaby również świetna (to znaczy, jeśli mój punkt ma zalety).

ryanzec
źródło
patrz także: Techniki testowania oprogramowania
wtorek

Odpowiedzi:

21

Dla mnie testy jednostkowe nie powinny dotyczyć bazy danych, testy integracyjne dotyczą bazy danych.

Testy integracyjne, które dotyczą bazy danych, powinny w praktyce mieć pustą bazę danych z podejściem odrywania i rozrywania, przy użyciu podejścia opartego na transakcjach jest to całkiem dobra droga (tj. Utworzenie transakcji przy konfiguracji i wycofywanie po rozebraniu).

Twój przyjaciel brzmi tak, jakby chciał zrobić, to przetestować go z punktu widzenia „regresji”, tzn. Mieć tam prawdziwe dane i zobaczyć, jak reaguje system, w końcu żaden system nie jest idealny i zwykle mogą znajdować się złe dane, które zapewniają kilka dziwactw do twojego modelu domeny.

Najlepszymi sposobami są twoje najlepsze praktyki i to, co zwykle robię, to jeśli znajdę scenariusz dotyczący złych danych, napiszę test integracji z konfiguracją i wybiję dokładnie ten scenariusz.

Nicholas Mayne
źródło
Po prostu jestem pewien, jaka jest różnica między testowaniem jednostek a testami integracji, poza tym słyszę, że jednostka powinna używać wyśmiewanych danych, a integracja powinna korzystać z bazy danych (uruchomiłem inny programista wątków. Stackexchange.com/questions/101300/... ). Poza tym wszystko, co mówisz, wydaje się zgodne z tym, o czym myślę.
ryanzec
Nie ma problemu, dodałem więcej informacji do twojej drugiej odpowiedzi
Nicholas Mayne
1
dlaczego nie możesz przetestować DB? Jeśli umieścisz swój SQL w procedurach przechowywanych, możesz je przetestować jednostkowo za pomocą danych zdefiniowanych w teście, a nagle wszystko staje się łatwe. Jest to zdecydowanie najlepsza praktyka, którą powinno stosować więcej osób, zobacz, co mówi MS
gbjbaanb
1
integration tests- co masz na myśli? Jak wspomniałem, moduły korzystające z bazy danych mogą i powinny być testowane za pomocą testów jednostkowych. Baza danych może zostać wyśmiewana ręcznie lub zastąpiona implementacją w pamięci
hellboy
6

Jeśli Twoje testy zależą od bazy danych, myślę, że ważniejsze jest, aby dane, na których Ci zależy, były w stanie znanym z testów, a nie pusta baza danych. Jedną z miar dobrych testów jest to, że każdy test powinien zakończyć się niepowodzeniem z jednego powodu i żaden inny test nie powinien zakończyć się niepowodzeniem z tego samego powodu.

Jeśli więc w teście zależy na stanie danych, przenieś dane do znanego stanu i przywróć dane do tego stanu po uruchomieniu testów, aby testy były odtwarzalne.

Jeśli potrafisz oddzielić testy od stanu danych przez wyśmiewanie, byłoby to również dobre. Wspominasz, że wykonujesz testy jednostkowe / integracyjne, ale oczywiście te dwie rzeczy należy rozpatrywać osobno. Jeśli to w ogóle możliwe, testy jednostkowe powinny zostać odłączone od bazy danych, a testy integracyjne powinny odbywać się w bazie danych w znanym stanie.

Paddyslacker
źródło
2

Cóż, widzę jedną zaletę posiadania wstępnie wypełnionej bazy danych: nie musisz pisać kodu, który wstawi potrzebne dane, ponieważ one tam są. W przeciwnym razie są tylko wady. Może ktoś zmodyfikował dane testowe w bazie danych? Może ktoś próbował odświeżyć dane? Ale najgorsze jest to, że jeden przypadek testowy źle psuje bazę danych ... W efekcie ręcznie odtwarzasz całą bazę danych kilka razy.

Masz rację, jak pisać testy, z wyjątkiem tego, że niczego nie obcinam:

  • faza konfiguracji: uzyskaj połączenie z bazą danych i wstaw dane
  • faza uruchamiania
  • faza rozbiórki: usuń wstawione dane (obcięcie)

Teraz ten scenariusz jest świetny do testów jednostkowych. Kiedy potrzebujemy danych do testów jednostkowych i integracyjnych, zauważyłem, że jedna duża faza konfiguracji wspólna dla wszystkich przypadków testowych (zgrupowaliśmy wszystkie „wstawki” w jedną metodę statyczną) może również działać bardzo dobrze. To jest jak środek pomiędzy twoim pomysłem a pomysłem twojego przyjaciela. Jedyną wadą jest to, że musisz być bardzo ostrożny przy dodawaniu nowych danych, aby nie uszkodzić istniejących przypadków testowych (ale jeśli dodasz jak dwa-trzy wiersze na tabelę tak jak my, nie powinno to stanowić problemu)

Jalayn
źródło
Czy nie wolałbym raczej tworzyć części bazy danych potrzebnych do testu, niż gdyby ktoś przypadkowo zmodyfikował dane w sposób powodujący awarię? Konieczność upewnienia się, że dane są poprawne w przypadku niepowodzenia testu, wydaje się czymś, czemu można zapobiec.
ryanzec
1
Duża faza konfiguracji, w której wstawiane są dane przydatne w różnych przypadkach testowych, może być użyteczna tylko w testach integracyjnych, w których należy sprawdzić różne części aplikacji współpracujące ze sobą. Warto mieć ten duży wspólny zestaw „wstawek”, ponieważ najprawdopodobniej będziesz potrzebować niektórych z nich do innych testów integracyjnych. W przeciwnym razie, jeśli mówimy tylko o czystym testowaniu jednostkowym, absolutnie jestem za posiadaniem jednego zestawu danych do wstawienia dla każdego przypadku testowego.
Jalayn,
1

Myślę, że musisz zawęzić przykład ze swoim kolegą i dowiedzieć się, co dokładnie oznaczają. Oboje możecie być na tej samej stronie.

Przykład: sprawdzanie tabeli transakcji na rachunku

  1. Czy nie chcesz przetestować wyświetlania tej tabeli dla użytkownika / konta bez transakcji?
  2. Przetestuj dodanie pierwszego rekordu i sprawdź, czy możesz stworzyć saldo.
  3. Twórz rekordy, gdy już istnieją, i sprawdzaj saldo bieżące oraz wszelkie inne reguły biznesowe.
  4. Zobacz tabelę z istniejącymi rekordami i wszystkimi innymi CRUD.

Czy osiągniesz to, wykonując kroki 1 i 2 lub rozpoczynając od bazy danych już w tym stanie (przywrócić kopię zapasową?) Nie jestem pewien, czy to ma znaczenie. Twój pomysł na napisanie do mnie skryptu ułatwia zarządzanie potrzebnymi zmianami (na przykład, jeśli zapomniałeś utworzyć konto administratora i potrzebujesz go dla nowego użytkownika). Pliki skryptowe łatwiej poddać kontroli źródła niż niektóre pliki kopii zapasowych. Wpływa to również na to, czy rozpowszechniasz tę aplikację.

JeffO
źródło
0

Aby narysować aspekty kilku odpowiedzi razem i dodać mój 2p ...

Uwaga: moje komentarze dotyczą w szczególności testowania bazy danych , a nie testowania interfejsu użytkownika (choć oczywiście dotyczy to podobnych).

Bazy danych wymagają tyle samo testowania, co aplikacje typu front-end, ale zwykle są testowane na podstawie „czy to działa z front-endem?” lub „czy raporty dają poprawny wynik?”, który moim zdaniem testuje bardzo późno w procesie tworzenia bazy danych i nie jest zbyt solidny.

Mamy wielu klientów, którzy używają testów jednostkowych / integracyjnych / systemowych w swojej bazie danych hurtowni danych oprócz zwykłego UAT / performance / et al. testy. Odkryli, że dzięki ciągłej integracji i automatycznym testom wychwytują wiele problemów przed przejściem do tradycyjnego UAT, oszczędzając w ten sposób czas i zwiększając szansę na sukces UAT.

Jestem pewien, że większość zgodzi się, że do testowania bazy danych należy zastosować podobny rygor, jak w przypadku testów interfejsu użytkownika lub raportów.

Kluczową rzeczą w testowaniu jest testowanie małych prostych bytów, zapewniając ich poprawność, przed przystąpieniem do złożonych kombinacji bytów, zapewniając ich poprawność przed rozszerzeniem na szerszy system.

Dając kontekst dla mojej odpowiedzi ...

Testów jednostkowych

  • koncentruje się na testowaniu, aby udowodnić, że jednostka działa, np. tabela, widok, funkcja, procedura składowana
  • powinien „zepchnąć” interfejsy w celu usunięcia zewnętrznych zależności
  • dostarczy własne dane. Potrzebujesz znanego stanu początkowego danych, więc jeśli istnieje szansa, że ​​dane istnieją przed testem, to przed zapełnianiem powinny wystąpić obcięcia / usunięcia
  • będzie działać idealnie we własnym kontekście wykonywania
  • po sobie wyczyści i usunie użyte dane; jest to ważne tylko wtedy, gdy nie są używane kody pośredniczące.

Zaletą tego jest to, że usuwasz wszystkie zewnętrzne zależności od testu i wykonujesz najmniejszą liczbę testów w celu udowodnienia poprawności. Oczywiście tych testów nie można uruchomić w produkcyjnej bazie danych. Może się zdarzyć, że wykonasz wiele rodzajów testów, w zależności od rodzaju jednostki, w tym:

  • sprawdzanie schematu, niektórzy mogą nazwać to testem „kontraktu danych”
  • przechodzące wartości kolumn
  • ćwiczenie ścieżek logicznych z różnymi wartościami danych dla funkcji, procedur, widoków, kolumn obliczeniowych
  • testowanie krawędzi - NULL, złe dane, liczby ujemne, wartości, które są zbyt duże

(Unit) Testy integracyjne

Uważam, że ten post SE jest pomocny w mówieniu o różnych typach testów.

  • koncentruje się na testach, aby udowodnić, że jednostki integrują się ze sobą
  • wykonywane na kilku jednostkach razem
  • powinien „zepchnąć” interfejsy w celu usunięcia zewnętrznych zależności
  • dostarczy własne dane, aby usunąć skutki wpływów danych zewnętrznych
  • będzie działać idealnie we własnym kontekście wykonywania
  • wyczyści się po sobie i usunie utworzone dane; jest to ważne tylko wtedy, gdy nie są używane kody pośredniczące.

Przechodząc od testów jednostkowych do tych testów integracyjnych, często będzie nieco więcej danych, aby przetestować szerszą gamę przypadków testowych. Oczywiście tych testów nie można uruchomić w produkcyjnej bazie danych.

To z kolei zachodzi na testowanie systemu , system kontrolny integracji (czyli testu końcowego 2-koniec), wraz ze wzrostem ilości danych oraz zwiększenie zakresu. Wszystkie te testy powinny stać się częścią ramowych testów regresji. Niektóre z tych testów mogą zostać wybrane przez użytkowników do wykonania w ramach UAT, ale UAT to testy zdefiniowane przez użytkowników , a nie takie, jak zdefiniowane przez IT - częsty problem!

Teraz, gdy podałem kontekst, aby odpowiedzieć na wasze aktualne pytania

  • wstępne wypełnianie danych do testów jednostkowych i integracyjnych może powodować fałszywe błędy testowe i należy tego unikać.
  • Jedynym sposobem na zapewnienie spójnych testów jest brak jakichkolwiek założeń dotyczących danych źródłowych i rygorystyczna kontrola.
  • ważny jest osobny kontekst wykonywania testu, aby upewnić się, że jeden tester nie jest w konflikcie z innym testerem wykonującym te same testy w innej gałęzi kodu bazy danych kontrolowanej przez źródło.
Marcus D.
źródło
-3

Szczerze mówiąc, myślę, że jeśli przeprowadzasz testy jednostkowe bez bazy danych mniej więcej tego samego rozmiaru co istniejąca produkcyjna baza danych, będziesz mieć wiele rzeczy, które przejdą testy i zawiodą w produkcji pod względem wydajności. Oczywiście jestem przeciwny opracowywaniu w tym celu maleńkiej lokalnej bazy danych.

A jeśli kod jest specyficzny dla danych, jak możesz go skutecznie przetestować bez danych? Nie zauważysz, czy zapytania zwróciły prawidłowe wyniki. Dlaczego miałbyś w ogóle rozważyć testowanie na pustej bazie danych, wszystko mówi tylko, czy składnia jest poprawna, a nie jeśli zapytanie jest poprawne. Wydaje mi się to krótkowzroczne. Widziałem zbyt wiele rzeczy, które działają i przechodzą testy, które są kategorycznie złe. Nie chcesz tego znaleźć w testach jednostkowych? Ja robię.

HLGEM
źródło
Nie sugeruję uruchamiania z pustą bazą danych, jeśli zobaczysz krok 2, mam „Następnie wstawiasz wszystkie dane potrzebne do przypadków testowych, które zamierzasz uruchomić”. Jeśli chodzi o problem z wydajnością, nie sądzę, że po to jest testowanie jednostkowe, czyli więcej testów obciążenia. Testowanie jednostkowe w celu przetestowania pod kątem logiczności kodu. jeśli logika zadziała, będzie działać dla 1 rekordu lub 100 000 000 000 rekordów tych samych podstawowych danych (myślałem, że będzie o wiele wolniej).
ryanzec
Zapytania do bazy danych dotyczą nie tylko logiki i im szybciej się przekonasz, nie będzie działać lepiej. To, co działa dla 1 rekordu, często przekroczy limit czasu na prod, a test jednostkowy pokaże to jak najszybciej.
HLGEM,
Testy jednostkowe i integracyjne dotyczą funkcjonalności, a nie wydajności, dzięki czemu można testować przy użyciu niewielkiej ilości danych
użytkownik151019
Testy jednostkowe nigdy nie powinny korzystać z bazy danych - testy integracyjne wykorzystują bazy danych.
Nicholas Mayne,
1
To, o czym właściwie mówisz, to testy obciążenia. Gdybyś miał zestaw testów akceptacyjnych i podłączył je do narzędzia do testowania obciążenia, byłbyś w stanie osiągnąć pożądany efekt.
Nicholas Mayne,