Po co używać bazy danych w pamięci do testowania integracji?

18

Jestem naprawdę zdezorientowany, gdy widzę dużo implementacji bazy danych w pamięci używanej do testowania, ponieważ słyszałem również wiele z najlepszych praktyk testowania integracji, że środowisko uruchamiające test powinno jak najbardziej przypominać środowisko produkcyjne, w tym system operacyjny , biblioteka, silnik bazy danych itp.

Czego tu brakuje?

dnang
źródło
Widziałem to bardzo często, ponieważ można programowo zapewnić spójność danych, a ponadto są one stosunkowo szybkie. Zwłaszcza jeśli test jest testem jednostkowym, chcesz, aby był to system zamknięty. Chcesz, aby twoje testy były całkowicie objęte testem.
rig
Miło jest, aby deweloper mógł pobrać najnowszy kod i uruchomić testy bez konieczności wcześniejszej konfiguracji zewnętrznej bazy danych.
Jason Evans,
1
Aspekty, które wymagają ścisłego przypominania środowiska produkcyjnego, należą do testów obciążenia i testów warunków skrajnych, które moim zdaniem powinny być wykonywane oddzielnie od testów jednostkowych (które jako kryteria spełniają kryteria bramkowe).
rwong

Odpowiedzi:

19

W typowej sytuacji związanej z tworzeniem oprogramowania testy są stosowane w dwóch punktach: podczas programowania i przed przeniesieniem produktu w łańcuch rozwoju.

Pierwsza sytuacja, przeprowadzanie testów podczas programowania, służy celom krótkoterminowym: definiowaniu zadań (jak w TDD: napisanie testu zakończonego niepowodzeniem, a następnie przejściu go), zapobieganiu regresom, upewnieniu się, że zmiany nie psują niczego innego itp. Takie testy muszą być niezwykle szybkie: idealnie cały zestaw testów działa w mniej niż 5 sekund i możesz po prostu uruchomić go w pętli obok IDE lub edytora tekstu podczas pisania kodu. Każda regresja, którą wprowadzisz, pojawi się w ciągu kilku sekund. Szybkie testy są ważniejsze w tej fazie niż wyłapanie 100% regresji i błędów, a ponieważ opracowanie dokładnych kopii systemów produkcyjnych jest niepraktyczne (lub wręcz niemożliwe), wysiłek wymagany do uzyskania doskonałych testów tutaj nie jest wart to. Korzystanie z baz danych w pamięci jest kompromisem: nie są to dokładne kopie systemu produkcyjnego, ale pomagają utrzymać testy poniżej 5 sekund; jeśli mam wybór między nieco inną konfiguracją bazy danych dla moich testów związanych z bazą danych, a brakiem testów, wiem, co wybrałem.

Druga sytuacja, przeniesienie kodu łańcuchu rozwoju, jednak nie wymagają szeroko zakrojonych testów. Ponieważ możemy (i powinniśmy) zautomatyzować tę część procesu programowania, możemy sobie pozwolić na znacznie wolniejsze testy - nawet jeśli pełny test trwa kilka godzin, zaplanowanie nocnej kompilacji nadal oznacza, że ​​zawsze mamy dokładny obraz wczorajszej bazy kodu. Dokładne symulowanie środowiska produkcyjnego jest teraz ważne, ale możemy sobie na to pozwolić. Dlatego nie dokonujemy kompromisu w bazie danych w pamięci: instalujemy dokładnie taką samą wersję dokładnie tego samego DBMS, co systemy produkcyjne, i jeśli to możliwe, wypełniamy ją rzeczywistymi danymi produkcyjnymi przed rozpoczęciem testów.

tdammers
źródło
6

Myślę, że jest to kompromisowa prędkość / dopasowanie do środowiska. Testy powinny być przeprowadzane często, a to oznacza, że ​​muszą być szybkie. Zwłaszcza testy jednostkowe, które nie powinny trwać dłużej niż kilka sekund.

Testy integracyjne będą działały wolniej, ale gdy są szybkie, możesz je uruchamiać częściej. Na przykład przed każdym zatwierdzeniem. Oczywiście nie jest tak kompletne jak pełne środowisko, ale przynajmniej testujesz warstwę mapowania, wygenerowany SQL, sposób, w jaki część się ze sobą rozmawia itp. W przypadku kosztownej bazy danych upewniasz się, że nie „ muszę kupić licencję dla wszystkich. Możesz złapać więcej błędów obejmujących 90% kodu przy testach przeprowadzanych raz na godzinę niż obejmujących 100% testów kodu raz dziennie lub, co najgorsze, tydzień.

To powiedziawszy, oczywiście potrzebujesz testu z prawdziwą bazą danych iw pełni zintegrowanym środowiskiem. Nie możesz uruchamiać tych testów tak często, ale ponieważ poprzedni test dał ci już pewność, pozostało tylko dziwny błąd związany z platformą.

Laurent Bourgault-Roy
źródło
3

W przypadku wykonywania prostych testów kpowanie z warstwy dostępu do bazy danych jest całkowicie dopuszczalne. Wołasz getName(), to nazywa wyśmiewanego DAO i zwraca „John” dla imienia i „Smith” dla nazwiska, składa je i wszystko jest idealne. Nie ma potrzeby testowania w tym miejscu bazy danych.

Sprawy stają się nieco bardziej, gdy logika staje się nieco bardziej złożona. Co jeśli masz metodę „createOrUpdateUser (...)”. Jeśli wyśmiewałeś bazę danych, możesz sprawdzić, czy dana metoda została wywołana jeden raz z pewnym parametrem, gdy próbka nie zwraca żadnych obiektów, a inna baza danych jest wywoływana w bazie danych, gdy zwraca istniejący obiekt. To zaczyna przechodzić do tej niewyraźnej linii, w której może być łatwiej (szczególnie, jeśli już tam była), rozwinąć wyspecjalizowaną bazę danych pamięci i przetestować ten kod ze wstępnie skonfigurowanymi danymi.

W niektórych kodach, nad którymi pracowałem (w punkcie sprzedaży), mieliśmy resumeSuspededTransaction(...)metodę. Spowodowałoby to wyciągnięcie transakcji z bazy danych do obiektu (i jego składników) i zaktualizowanie bazy danych. Wyśmiewaliśmy go, a gdzieś w kodzie krył się błąd z serializacją i deserializacją danych przechodzących do bazy danych (zmieniliśmy typ, który był różnie serializowany w bazie danych).

Makieta nie pokazała nam błędu, ponieważ powracała z radosną ścieżką - serializuj transakcję, przechowuj ją w makiecie, deserializuj z makiety, testuj, czy są równe. Jednak, gdy serializujesz obiekt z wiodącym zerem do bazy danych, upuszcza je, a następnie rekombinuje z powrotem do łańcucha bez zer. Wykryliśmy błąd bez bazy danych przez rozwiązywanie problemów (nie było to trudne do wykrycia, kiedy już wiedzieliśmy, że tam jest).

Później umieściliśmy tam bazę danych i zdaliśmy sobie sprawę, że błąd nigdy nie przeszedłby tego testu junit, gdybyśmy zamiast tego wybrali się do bazy danych w pamięci.


W bazach pamięci mają zalety:

  • można je szybko rozkręcić (bez potrzeby DBA do konfigurowania kont, tabel itp.) do testowania
  • dane można wstępnie skonfigurować dla tego testu
  • test nie musi się martwić o wycofanie testu po zakończeniu
  • każdy test ma swoją własną bazę danych w pamięci, więc nie musisz się martwić, że dwa testy działają jednocześnie
  • można je uruchamiać w systemach, które nie mają łączności z prawdziwymi bazami danych

źródło
1

Zależy to w dużej mierze od używanego systemu baz danych. Gdy system db zapewnia alternatywną opcję w pamięci, która jest prawie w 100% zgodna z interfejsem API i zachowaniem zgodnym z konfiguracją baz danych na dyskach (z wyjątkiem szybkości i bezpieczeństwa w razie awarii lub oczywiście), użycie wariantu w pamięci jest oczywiście w porządku .

Jeśli jednak w twoim systemie DB występują znaczące różnice między konfiguracją w pamięci a użytkowaniem innym niż w pamięci, masz rację: w tym przypadku testy integracyjne wiążą się z większym ryzykiem zacienienia błędu. Ale nawet wtedy możesz być w stanie samodzielnie „oddzielić te różnice”, pod warunkiem, że dobrze znasz swój system DB i różnice.

Doktor Brown
źródło
1

Słowami laika:

Wyśmiewanie ważnych części architektury jest w porządku (i koniecznością) do testów jednostkowych .

Ale jeśli chodzi o testy integracyjne, zdecydowanie się z tobą zgadzam. Wyśmiewanie nie powinno być wykonywane, a środowisko powinno być jak najbardziej podobne do rzeczywistego.

W końcu testy integracyjne polegają na sprawdzeniu, jak różne części architektury zachowują się razem.

Tulains Córdova
źródło