Testy jednostkowe - uzycie testowej bazy danych oraz testowanie modeli.

0

Jakiś pomysł jak mogę zorganizować połęcznie z testową bazą danych? Nie chce trzymac polaczenia z DB w setUp() w kazdej klasie w ktorej uzywam placzenia z baza danych.

3

eeeee użyć odpowiedniego enva?

1
poniatowski napisał(a):

Nie chce trzymac polaczenia z DB w setUp() w kazdej klasie w ktorej uzywam placzenia z baza danych

Przeciez ten pomysl to rak jakis.

Jak korzystasz z DB? Przez jakies repository, unit of work? Jesli tak to wystarczy podmienic instancje wlasciwego UOW na taka co korzysta z np. RAMu jako bazy danych. Jesli nie to musisz miec developerska baze danych. Ewentualnie transakcje + rollback ale cos zepsujesz to wlasciwa baze zasmiecisz.

0

Postawilem baze testowa na dockerze (postgresql 9.6). Migracje oraz seeding tworze za pomoca Phinx. Umiescilem user/password itd w phpunit.xml. I tutaj chodzi mi o samo polaczenie do bazy danych, bo usatalam je w setUp(), ale tam tego kodu troche jest. Nie chce tego powtarzac dla kazdego testowanego DB modelu. I myslalem, zeby stworzyc jakos parent klase czy trail czy cos takiego. Takie w sumie troche o banal zapytalem, ale pytanie jak pytanie. Dzis cos napisze, zeby to rozwiazac.

1

Nie wiem co tam ten Twój setUp() ma, ale kodowanie na sztywno haseł w kodzie, czy to do testów czy nie to zła praktyka.
Masz wskazówkę od @mr_jaro i sugestię użycia env i zmiennych środowiskowych.
Zobacz to: https://github.com/vlucas/phpdotenv
Zmieniasz cały plik z ustawieniami i środowisko do testów gotowe.

0

Czemu nie moge niby trzymac tego tak jak jest w dokumentacji. Uzywam tej env biblioteki, niby moge dodac do env. Trzymalbym wszystko w jednym miejscu.

<?xml version="1.0" encoding="UTF-8" ?>
<phpunit>
    <php>
        <var name="DB_DSN" value="mysql:dbname=myguestbook;host=localhost" />
        <var name="DB_USER" value="user" />
        <var name="DB_PASSWD" value="passwd" />
        <var name="DB_DBNAME" value="myguestbook" />
    </php>
</phpunit>

Tip: Use your own Abstract Database TestCase

1

W porządnie zrobionej architekturze, czyli chociażby we frameworkach symfony czy laravel, masz enva i tego enva możesz ustawiać pod różne środowiska, dla testów stosuje się env.testing przez co i kod testowany i same testy automatycznie sobie zaciągają te ustawienia chociażby związane z połączeniem do bazy. A gdy sobie popatrzysz na kod testów stosowany w tych frameworka to zobaczysz że nigdzie nie ma ręcznie wpisywanych ustawień w setup.

0

Aj, faktycznie zapomnialem :/ Juz ponad 2 lata siedze na bez fmowym projekcje. Masz racje, dzieki. A co myslicie z samym polaczeniem z baza danych? Nampisac jakas klase i pozniej wywolywac z setup tearDown?

1

poszukaj sobie na necie jak to się profesjonalnie rozwiązuje albo prześledź kod frameworków

0

Wlasnie nie moge w ogole znalezc przykladow w Google :/

0

Polecam PHP DbUnit

https://github.com/sebastianbergmann/dbunit

Tworzysz startową strukturę. Odpowiednie metody w DbUnit pozwalają na załadowanie danych testowych z plików dataset a po zakończonym teście baza jest przywracana do stanu pierwotnego (czyli zanim test został wykonany).

Testy na bazie danych trwają znacznie dłużej. Dobrze jest też przygotować sobie odpowiednie datasety dla testów.

0

@skyner Z tego co pamietam to DBUnit nie jest kompatybilny z Unit tests 8.5 ( a taka wersje obecnie uzywam). Wiec zainstalowalem Phinx, ale tutaj tez mam problem, bo Phinx nie ma 0 downtime development :/ LoL

@skyner Wiesz moze jak przyspieszyc powolne testy jednostkowe? Mam jedna tabele dodalem 33 rekordy i unit test oznacza mi ten test jako bardzo wolny. Ale niby jak go mam przypieszyc? Index nic tutaj nie dam. Nie kumam.

1

Testy na bazie generalnie nie należą do najszybszych.
Jak robiłem takie testy w oparciu o PgSql to jednym z rozwiązań były zmiany w konfiguracji bazy testowej.
Niestety nie mogę znaleźć artykułu, który opisywał które parametry należy zmienić.

Piszesz, że tabela ma 33 rekordy to faktycznie wydaje się nie dużo. Jednak bez zagłębienia w kod trochę ciężko stwierdzić, gdzie może leżeć przyczyna problemu. Może coś dodatkowego w metodach setUp bądź tearDown jest wykonywane, może jakieś powiązania na bazie?

Ciężko mi powiedzieć jak działa Phink ponieważ, go nie używałem. W przypadku DbUnit działało to tak, że przed każdym testem były ładowane wskazane dane do bazy a po teście DbUnit je sobie czyścił. Także ta procedura w zależności jak test miał sobie przygotować bazę też mogła zajmować sporo czasu.

0

Brzmi tak samo jak moje ustawienie. w setUp/tearDwon robie migracje i seeds/nastepnie wszsytko usuwam. I tak za kazda testowana metoda. Szperalem juz cos, ale ciezko znalezc cokolwiek ciekawego.

1

Możesz sobie ustawić jakieś punkty czasowe, żeby sprawdzić ile trwa metoda setUp ile test a ile tearDown.
Może trzeba zobaczyć jak zoptymalizować właśnie setUp i terarDown, bo sam test będzie trwał niewiele czasu.
Pytanie czy robisz pełną migrację za każdym razem?

W moim przypadku baza testowa była stała, tabele słownikowe były przygotowane, i nic do nich nie ładowałem podczas uruchamiania testów, a ładowanie danych odbywało się tylko do tabeli bądź tabel, które aktualnie testowałem.

0

A wlasnie. W sumie masz racje. Ja za kazdym razem tworze tabele i inserty. A w sumie tabele mogly by zostac prawda? Chodzi mi o to, ze w polaczenie z baza dana oraz utowrzenie tabel mozna zrobic jeden raz. I tylko dodawanie oraz usuwanie danych w setup/teardown. Czy to jest to co masz na mysli?

Znalazlem fsync w postgresie moze byc wylaczony i ponoc to tez przyspiesza testy. fsync=off Zaraz bede testowal :)

0

@skyner Jak w ogole wywoluejsz DBunit metody? setUp/tearDown to nie stayczne metody a setUpBeforeClass i tearDownAfterClass to juz statyczne metody. Wiec potrzebna jest klasa albo trait, ktory bedzie dziala w obu metodach. Dlaczego ktos w ogole tak zrobil? Nie ma to sensu. Ja sobie napisalem ladnie nowa klase TestDatabase, ktora dziedziczy TestCase i jak mam DB model do przetestowania to dziedzine TestDatabase i tam mam juz TestCase i wszystko potrzebne do polaczenia z testowa baza danych oraz do migracji tabeli oraz danych. Nie wiem po co ktos zrobic to static? ;(

0
poniatowski napisał(a):

A wlasnie. W sumie masz racje. Ja za kazdym razem tworze tabele i inserty. A w sumie tabele mogly by zostac prawda? Chodzi mi o to, ze w polaczenie z baza dana oraz utowrzenie tabel mozna zrobic jeden raz. I tylko dodawanie oraz usuwanie danych w setup/teardown. Czy to jest to co masz na mysli?

Znalazlem fsync w postgresie moze byc wylaczony i ponoc to tez przyspiesza testy. fsync=off Zaraz bede testowal :)

Tak chodzi o to, że przygotowujesz startową bazę do testów i w czasie testów baza nie zmienia swojej struktury tzn, nie tworzysz nowych tabel, a dane w tabelach słownikowych masz już na starcie. Także podczas testów obsługujesz konkretne przypadki operacji na bazie danych.

Ja sobie napisałem skrypt który jak trzeba było tworzył mi instancję bazy testowej na nowo i ładował do niej niezbędne dane, które nie były modyfikowane w czasie testów (np. tabele słownikowe)

Jeżeli chodzi o opcję fsync to bardzo możliwe, że to była ta opcja. Ja ze względu na konfigurację środowiska bazodanowego nie byłem w stanie przetestować czy ta opcja działa

0

@skyner podstawowe dane tak ale dane potrzebne w konkretnym teście muszą być dodawane tylko w ramach tego testu i potem zmiany wycofywane najlepiej gdy całość jest zamknięta w transakcji (tak robią to frameworki)

0
poniatowski napisał(a):

@skyner Jak w ogole wywoluejsz DBunit metody? setUp/tearDown to nie stayczne metody a setUpBeforeClass i tearDownAfterClass to juz statyczne metody. Wiec potrzebna jest klasa albo trait, ktory bedzie dziala w obu metodach. Dlaczego ktos w ogole tak zrobil? Nie ma to sensu. Ja sobie napisalem ladnie nowa klase TestDatabase, ktora dziedziczy TestCase i jak mam DB model do przetestowania to dziedzine TestDatabase i tam mam juz TestCase i wszystko potrzebne do polaczenia z testowa baza danych oraz do migracji tabeli oraz danych. Nie wiem po co ktos zrobic to static? ;(

Niestety na to pytanie nie potrafię Ci odpowiedzieć. Ostatnie testy wykorzystujące DB Unit przeprowadzałem 2 lata temu, jednak nie przypominam sobie żebym korzystal z metod setUpBeforeClass i tearDownAfterClass.

0
mr_jaro napisał(a):

@skyner podstawowe dane tak ale dane potrzebne w konkretnym teście muszą być dodawane tylko w ramach tego testu i potem zmiany wycofywane najlepiej gdy całość jest zamknięta w transakcji (tak robią to frameworki)

@mr_jaro Dokładnie, jeżeli któraś moja odpowiedź sugeruje inaczej to przepraszam.

Na czas testu ładujemy dane konieczne tylko do tego testu. Przez dane podstawowe które mogą cały czas istnieć w bazie testowej rozumiem np. dane zawarte w tabelach słownikowych.

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