{"id":37666,"date":"2019-10-31T22:18:55","date_gmt":"2019-10-31T19:18:55","guid":{"rendered":"https:\/\/prohoster.info\/blog\/unit-testy-v-subd-kak-my-delaem-eto-v-sportmastere-chast-vtoraya\/"},"modified":"2019-10-31T22:18:55","modified_gmt":"2019-10-31T19:18:55","slug":"unit-testy-v-subd-kak-my-delaem-eto-v-sportmastere-chast-vtoraya","status":"publish","type":"post","link":"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/unit-testy-v-subd-kak-my-delaem-eto-v-sportmastere-chast-vtoraya","title":{"rendered":"Testy jednostkowe w bazach danych \u2014 jak to robimy w Sportmasterze, cz\u0119\u015b\u0107 druga","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><i>Pierwsza cz\u0119\u015b\u0107 \u2014 <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/sportmaster_lab\/blog\/464335\/\">tutaj<\/a><\/noindex>.<\/i><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/sportmaster_lab\/blog\/465047\/\"><img decoding=\"async\" alt=\"Testy jednostkowe w bazach danych \u2014 jak to robimy w Sportmasterze, cz\u0119\u015b\u0107 druga\" src=\"\/wp-content\/uploads\/2019\/09\/b9fb8c934885abdf3ef928bfd75bdc2a.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/a><\/noindex><\/p>\n<p>Wyobra\u017acie sobie sytuacj\u0119. Waszym zadaniem jest opracowanie nowej funkcjonalno\u015bci. Macie materia\u0142y od swoich poprzednik\u00f3w. Je\u015bli za\u0142o\u017cymy, \u017ce nie macie \u017cadnych moralnych zobowi\u0105za\u0144, co by\u015bcie zrobili?<\/p>\n<p>Najcz\u0119\u015bciej wszystkie stare materia\u0142y popadaj\u0105 w zapomnienie i wszystko zaczyna si\u0119 od nowa. Nikt nie lubi grzeba\u0107 w czyim\u015b kodzie, a przy braku czasu, czemu nie stworzy\u0107 w\u0142asnego systemu? To typowe podej\u015bcie i w wielu przypadkach s\u0142uszne. Jednak w naszym projekcie post\u0105pili\u015bmy inaczej. Podstaw\u0105 przysz\u0142ego systemu automatycznego testowania by\u0142y materia\u0142y z unit-test\u00f3w na utPLSQL od naszych poprzednik\u00f3w, a nast\u0119pnie zacz\u0119li\u015bmy pracowa\u0107 w kilku r\u00f3wnoleg\u0142ych kierunkach.<br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<ol>\n<li><b>Przywr\u00f3cenie starych unit-test\u00f3w.<\/b> Przez przywr\u00f3cenie rozumiemy dostosowanie test\u00f3w do obecnego stanu systemu lojalno\u015bciowego oraz dostosowanie test\u00f3w do standard\u00f3w utPLSQL. <\/li>\n<li><b>Rozwi\u0105zanie problemu z zrozumieniem, co dok\u0142adnie, jakie metody i procesy mamy pokryte automatycznymi testami. <\/b>Trzeba trzyma\u0107 t\u0119 informacj\u0119 w g\u0142owie lub wyci\u0105ga\u0107 wnioski na podstawie samego kodu automatycznych test\u00f3w. Dlatego postanowili\u015bmy stworzy\u0107 katalog. Ka\u017cdemu automatycznemu testowi przypisali\u015bmy unikalny mnemonik, stworzyli\u015bmy opis i zapisali\u015bmy ustawienia (na przyk\u0142ad, w jakich warunkach powinien by\u0107 uruchamiany, lub co powinno si\u0119 zdarzy\u0107, je\u015bli uruchomienie testu zako\u0144czy si\u0119 niepowodzeniem). W istocie wype\u0142nili\u015bmy metadane dotycz\u0105ce automatycznych test\u00f3w i umie\u015bcili\u015bmy te metadane w standardowych tabelach schemy utPLSQL.<\/li>\n<li><b>Okre\u015blenie strategii rozszerzenia, tzn. wyb\u00f3r funkcjonalno\u015bci, kt\u00f3ra ma by\u0107 sprawdzana przez automatyczne testy.<\/b> Postanowili\u015bmy zwr\u00f3ci\u0107 uwag\u0119 na trzy rzeczy: nowe usprawnienia systemu, incydenty z produkcji oraz kluczowe procesy systemu. W ten spos\u00f3b rozwijamy si\u0119 r\u00f3wnolegle z wydaniem, zapewniaj\u0105c wy\u017csz\u0105 jako\u015b\u0107, jednocze\u015bnie rozszerzaj\u0105c zakres regresji i zapewniaj\u0105c niezawodno\u015b\u0107 systemu w krytycznych punktach. Pierwszym takim w\u0105skim gard\u0142em by\u0142 proces przyznawania zni\u017cek i bonus\u00f3w na paragonie.<\/li>\n<li><b>Naturalnie, zacz\u0119li\u015bmy pracowa\u0107 nad nowymi automatycznymi testami. <\/b>Jednym z pierwszych zada\u0144 po wydaniu by\u0142o ocenienie wydajno\u015bci zdefiniowanych zbior\u00f3w systemu lojalno\u015bciowego. W naszym projekcie znajduj\u0105 si\u0119 sta\u0142e bloki zapyta\u0144 SQL, kt\u00f3re wybieraj\u0105 klient\u00f3w wed\u0142ug okre\u015blonych kryteri\u00f3w. Na przyk\u0142ad, uzyska\u0107 list\u0119 wszystkich klient\u00f3w, kt\u00f3rych ostatni zakup odby\u0142 si\u0119 w konkretnym mie\u015bcie, lub list\u0119 klient\u00f3w, kt\u00f3rych \u015brednia kwota zakupu jest wy\u017csza od okre\u015blonej warto\u015bci. Po napisaniu autotest\u00f3w sprawdzili\u015bmy zdefiniowane zbiory, ustalili\u015bmy wzorcowe parametry wydajno\u015bci, a dodatkowo przeprowadzili\u015bmy testy obci\u0105\u017ceniowe.<\/li>\n<li><b>Praca z autotestami powinna by\u0107 wygodna<\/b>. Najcz\u0119\u015bciej wykonywane s\u0105 dwa dzia\u0142ania: uruchomienie autotest\u00f3w i stworzenie danych testowych. W naszej systemie powsta\u0142y dwa pomocnicze modu\u0142y: modu\u0142 uruchamiania i modu\u0142 generowania danych.\n<p>Modu\u0142 uruchamiania jest przedstawiony w postaci jednej uniwersalnej procedury z jednym tekstowym parametrem wej\u015bciowym. Jako parametr mo\u017cna przekaza\u0107 mnemonik autotestu, nazw\u0119 pakietu, nazw\u0119 testu, ustawienia autotestu lub zarezerwowane s\u0142owo kluczowe. Procedura wybiera i uruchamia wszystkie autotesty, kt\u00f3re spe\u0142niaj\u0105 warunki.<\/p>\n<p>Modu\u0142 generowania danych jest przedstawiony w postaci pakietu, w kt\u00f3rym dla ka\u017cdego obiektu testowanego systemu (tabela w bazie danych) tworzona jest specjalna procedura, kt\u00f3ra wstawia tam dane. W tej procedurze maksymalnie wype\u0142nione s\u0105 domy\u015blne warto\u015bci, co umo\u017cliwia tworzenie obiekt\u00f3w w dos\u0142ownie kilka chwil. Dla wygody u\u017cytkowania stworzono tak\u017ce szablony tworzonej danych. Na przyk\u0142ad, stworzy\u0107 klienta okre\u015blonego wieku z testowym numerem telefonu i dokonanym zakupem.<\/li>\n<li><b>Autotesty powinny by\u0107 uruchamiane i dzia\u0142a\u0107 w akceptowalnym czasie dla twojego systemu. <\/b>W zwi\u0105zku z tym zorganizowano codzienne nocne uruchamianie, po kt\u00f3rym tworzony jest raport z wynikami i wysy\u0142any do ca\u0142ego zespo\u0142u deweloperskiego na poczt\u0119 firmow\u0105. Po przywr\u00f3ceniu starych autotest\u00f3w i stworzeniu nowych ca\u0142kowity czas pracy wyni\u00f3s\u0142 30 minut. Tego rodzaju wydajno\u015b\u0107 odpowiada\u0142a wszystkim, poniewa\u017c uruchomienie odbywa\u0142o si\u0119 poza godzinami pracy.\n<p>Ale nad optymalizacj\u0105 pr\u0119dko\u015bci dzia\u0142ania trzeba by\u0142o popracowa\u0107. Aktualizacja systemu lojalno\u015bciowego na produkcji odbywa si\u0119 w nocy. W ramach jednego z wyda\u0144 w nocy trzeba by\u0142o nagle wprowadzi\u0107 zmiany. P\u00f3\u0142godzinne czekanie na wyniki autotest\u00f3w o trzeciej nad ranem nie uszcz\u0119\u015bliwi\u0142o osoby odpowiedzialnej za wydanie (gor\u0105ce pozdrowienia dla Alekseja Wasiukowa!), a nast\u0119pnego ranka w stron\u0119 naszego systemu pad\u0142o wiele ciep\u0142ych s\u0142\u00f3w. Ostatecznie ustalono 5-minutowy standard pracy.<\/p>\n<p>Aby przyspieszy\u0107 wydajno\u015b\u0107, skorzystali\u015bmy z dw\u00f3ch metod: autotesty zacz\u0119\u0142y dzia\u0142a\u0107 w trzech r\u00f3wnoleg\u0142ych w\u0105tkach, co by\u0142o bardzo wygodne dzi\u0119ki architekturze naszego systemu lojalno\u015bciowego. Zrezygnowali\u015bmy r\u00f3wnie\u017c z podej\u015bcia, w kt\u00f3rym autotest nie tworzy danych testowych dla siebie, lecz pr\u00f3buje znale\u017a\u0107 co\u015b odpowiedniego w systemie. Po wprowadzeniu zmian ca\u0142kowity czas pracy skr\u00f3ci\u0142 si\u0119 do 3-4 minut.<\/li>\n<li><b>Projekt z autotestami powinien by\u0107 mo\u017cliwy do uruchomienia na r\u00f3\u017cnych \u015brodowiskach.<\/b> Na pocz\u0105tku pojawi\u0142y si\u0119 pr\u00f3by napisania w\u0142asnych skrypt\u00f3w, ale szybko zrozumieli\u015bmy, \u017ce samodzielnie zaprojektowana automatyczna instalacja to ca\u0142kowity koszmar, wi\u0119c zwr\u00f3cili\u015bmy si\u0119 ku rozwi\u0105zaniom przemys\u0142owym. Poniewa\u017c w projekcie jest bardzo du\u017co kodu (przede wszystkim przechowujemy kod autotest\u00f3w) i bardzo ma\u0142o danych (g\u0142\u00f3wne dane to metadane o autotestach), wdro\u017cenie Liquibase by\u0142o bardzo proste.\n<p>To niezale\u017cna od bazy danych biblioteka open source do \u015bledzenia, zarz\u0105dzania i stosowania zmian w schemacie bazy danych. Jest zarz\u0105dzana za pomoc\u0105 wiersza polece\u0144 lub framework\u00f3w typu Apache Maven. Zasada dzia\u0142ania Liquibase jest do\u015b\u0107 prosta. Mamy uporz\u0105dkowany projekt sk\u0142adaj\u0105cy si\u0119 z zmian lub skrypt\u00f3w, kt\u00f3re nale\u017cy zastosowa\u0107 na docelowym serwerze, oraz plik\u00f3w konfiguracyjnych, kt\u00f3re okre\u015blaj\u0105, w jakiej kolejno\u015bci i z jakimi parametrami nale\u017cy zastosowa\u0107 te zmiany. <\/p>\n<p>Na poziomie bazy danych tworzona jest specjalna tabela, w kt\u00f3rej Liquibase przechowuje logi migracji. Ka\u017cda zmiana ma obliczony hash, kt\u00f3ry jest por\u00f3wnywany pomi\u0119dzy projektem a stanem w bazie. Dzi\u0119ki Liquibase \u0142atwo wprowadzamy zmiany w naszym systemie na dowolnym \u015brodowisku. Testy automatyczne s\u0105 aktualnie uruchamiane na testowych i produkcyjnych \u015brodowiskach, a tak\u017ce na kontenerach (osobistych \u015brodowiskach programist\u00f3w).<\/li>\n<\/ol>\n<p><img decoding=\"async\" alt=\"Testy jednostkowe w bazach danych \u2014 jak to robimy w Sportmasterze, cz\u0119\u015b\u0107 druga\" src=\"\/wp-content\/uploads\/2019\/09\/4306f6c33543d38f5d8b77f67e22e247.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nZatem porozmawiajmy o wynikach stosowania naszego systemu test\u00f3w jednostkowych. <\/p>\n<ol>\n<li>Przede wszystkim jeste\u015bmy przekonani, \u017ce zacz\u0119li\u015bmy rozwija\u0107 oprogramowanie o wy\u017cszej jako\u015bci. Testy automatyczne s\u0105 uruchamiane codziennie i podczas wyda\u0144 wykrywaj\u0105 dziesi\u0105tki b\u0142\u0119d\u00f3w. Cz\u0119\u015b\u0107 z tych b\u0142\u0119d\u00f3w jest jedynie po\u015brednio zwi\u0105zana z funkcjonalno\u015bciami, kt\u00f3re naprawd\u0119 chcieli\u015bmy zmieni\u0107. Mamy powa\u017cne w\u0105tpliwo\u015bci, \u017ce te b\u0142\u0119dy zosta\u0142yby wykryte podczas test\u00f3w manualnych. <\/li>\n<li>Zesp\u00f3\u0142 zyska\u0142 pewno\u015b\u0107, \u017ce konkretna funkcjonalno\u015b\u0107 dzia\u0142a poprawnie\u2026 Dotyczy to w pierwszej kolejno\u015bci naszych kluczowych proces\u00f3w. Na przyk\u0142ad, w ci\u0105gu ostatnich sze\u015bciu miesi\u0119cy nie mieli\u015bmy problem\u00f3w z przydzielaniem zni\u017cek i bonus\u00f3w do paragon\u00f3w, pomimo comiesi\u0119cznych zmian, chocia\u017c w poprzednich okresach b\u0142\u0119dy pojawia\u0142y si\u0119 z pewn\u0105 regularno\u015bci\u0105.<\/li>\n<li>Uda\u0142o nam si\u0119 skr\u00f3ci\u0107 liczb\u0119 iteracji testowania. Dzi\u0119ki temu, \u017ce testy automatyczne s\u0105 pisane dla nowej funkcjonalno\u015bci, do analityk\u00f3w oraz jednocze\u015bnie tester\u00f3w trafia kod o wy\u017cszej jako\u015bci, poniewa\u017c by\u0142 ju\u017c sprawdzony.<\/li>\n<li>Cz\u0119\u015b\u0107 osi\u0105gni\u0119\u0107 w automatyzacji test\u00f3w jest wykorzystywana przez programist\u00f3w. Na przyk\u0142ad dane testowe w kontenerach s\u0105 generowane przy u\u017cyciu modu\u0142u generowania obiekt\u00f3w.<\/li>\n<li>Nie bez znaczenia jest tak\u017ce to, \u017ce w\u015br\u00f3d programist\u00f3w uwidoczni\u0142o si\u0119 \"przyj\u0119cie\" systemu automatyzacji test\u00f3w. Jest zrozumienie, \u017ce to wa\u017cne i przydatne. Z do\u015bwiadczenia mog\u0119 powiedzie\u0107, \u017ce to wcale nie jest takie proste. Testy automatyczne trzeba pisa\u0107, nale\u017cy je utrzymywa\u0107 i rozwija\u0107, analizowa\u0107 wyniki, a cz\u0119sto te czasoch\u0142onne zadania po prostu nie s\u0105 tego warte. Du\u017co \u0142atwiej jest i\u015b\u0107 na produkcj\u0119 i tam rozwi\u0105zywa\u0107 problemy. U nas programi\u015bci ustawiaj\u0105 si\u0119 w kolejce i prosz\u0105 o obj\u0119cie ich funkcjonalno\u015bci testami automatycznymi.<\/li>\n<\/ol>\n<h2>Co dalej<\/h2>\n<p>\n<img decoding=\"async\" alt=\"Testy jednostkowe w bazach danych \u2014 jak to robimy w Sportmasterze, cz\u0119\u015b\u0107 druga\" src=\"\/wp-content\/uploads\/2019\/09\/a11596618e97c0afaa9f5f25b613575e.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nPorozmawiajmy o planach rozwoju projektu automatyzacji testowania.<\/p>\n<p>Bez w\u0105tpienia, dop\u00f3ki system lojalno\u015bci Sportmastera jest \u017cywy i rozwija si\u0119, mo\u017cna r\u00f3wnie\u017c praktycznie w niesko\u0144czono\u015b\u0107 rozwija\u0107 automatyczne testy. Dlatego g\u0142\u00f3wnym kierunkiem rozwoju jest poszerzenie strefy pokrycia.<\/p>\n<p>W miar\u0119 jak liczba automatycznych test\u00f3w b\u0119dzie ros\u0142a, ca\u0142kowity czas ich pracy b\u0119dzie nieuchronnie wzrasta\u0142, i zn\u00f3w b\u0119dziemy musieli wr\u00f3ci\u0107 do kwestii wydajno\u015bci. Najprawdopodobniej rozwi\u0105zaniem b\u0119dzie zwi\u0119kszenie liczby r\u00f3wnoleg\u0142ych w\u0105tk\u00f3w.<\/p>\n<p>Jednak to s\u0105 oczywiste \u015bcie\u017cki rozwoju. Je\u015bli chodzi o co\u015b bardziej nietypowego, wyr\u00f3\u017cniamy nast\u0119puj\u0105ce:<\/p>\n<ol>\n<li>Obecnie zarz\u0105dzanie automatycznymi testami odbywa si\u0119 na poziomie bazy danych, tzn. wymagana jest znajomo\u015b\u0107 PL\/SQL do skutecznej pracy. W razie potrzeby mo\u017cna wydzieli\u0107 jak\u0105\u015b administracj\u0119, np. wykorzystuj\u0105c Jenkins lub co\u015b podobnego.<\/li>\n<li>Wszyscy lubi\u0105 ilo\u015bciowe i jako\u015bciowe wska\u017aniki. Dla automatycznego testowania takim uniwersalnym wska\u017anikiem jest Code Coverage, czyli metryka pokrycia kodu. Dzi\u0119ki temu wska\u017anikowi mo\u017cemy okre\u015bli\u0107, jaki procent kodu naszego testowanego systemu jest pokrywany przez automatyczne testy. Od wersji 12.2 Oracle udost\u0119pnia mo\u017cliwo\u015bci obliczania tej metryki i proponuje u\u017cywa\u0107 standardowego pakietu DBMS_PLSQL_CODE_COVERAGE.\n<p>Nasz system automatycznego testowania ma nieco ponad rok i by\u0107 mo\u017ce teraz jest najlepszy czas na ocen\u0119 pokrycia. W moim poprzednim projekcie (projekt nie by\u0142 zwi\u0105zany ze Sportmasterem) tak w\u0142a\u015bnie si\u0119 sta\u0142o. Po roku pracy nad automatycznymi testami kierownictwo postawi\u0142o zadanie oceni\u0107, jaki procent kodu pokrywamy. Przy pokryciu powy\u017cej 1% kierownictwo by\u0142oby szcz\u0119\u015bliwe. My, programi\u015bci, oczekiwali\u015bmy wyniku w okolicach 10%. Przykr\u0119cili\u015bmy pokrycie kodu, zmierzyli\u015bmy i uzyskali\u015bmy 20%. Z rado\u015bci poszli\u015bmy po premi\u0119, ale jak j\u0105 zdobyli\u015bmy i dok\u0105d p\u00f3\u017aniej poszli\u015bmy, to ju\u017c zupe\u0142nie inna historia.<\/li>\n<li>Automatyczne testy mog\u0105 sprawdza\u0107 wystawione us\u0142ugi internetowe. Oracle spokojnie na to pozwala, a my ju\u017c nie napotkamy szeregu problem\u00f3w. <\/li>\n<li>Oczywi\u015bcie, nasz system automatyzacji test\u00f3w mo\u017ce by\u0107 zastosowany w innym projekcie. Uzyskane przez nas rozwi\u0105zanie jest uniwersalne i wymaga jedynie u\u017cycia Oracle. S\u0142ysza\u0142em, \u017ce w innych projektach Sportmaster jest zainteresowanie automatycznym testowaniem i by\u0107 mo\u017ce si\u0119 do nich wybierzemy.<\/li>\n<\/ol>\n<p><\/p>\n<h2>Wnioski<\/h2>\n<p>\nPodsumujmy. W projekcie systemu lojalno\u015bci w Sportmasterze uda\u0142o nam si\u0119 wprowadzi\u0107 system automatyzacji test\u00f3w. Jego podstaw\u0105 jest rozwi\u0105zanie utPLSQL od Stevena Feuersteina. Wok\u00f3\u0142 utPLSQL umieszczony jest kod test\u00f3w automatycznych i pomocnicze samodzielne modu\u0142y: modu\u0142 uruchamiania, modu\u0142 generacji danych i inne. Testy automatyczne s\u0105 uruchamiane codziennie i, co najwa\u017cniejsze, dzia\u0142aj\u0105 i przynosz\u0105 korzy\u015bci. Wierzymy, \u017ce zacz\u0119li\u015bmy wydawa\u0107 oprogramowanie o wy\u017cszej jako\u015bci. Przy tym uzyskane rozwi\u0105zanie jest uniwersalne i mo\u017ce by\u0107 swobodnie stosowane w ka\u017cdym projekcie, gdzie konieczna jest automatyzacja test\u00f3w na systemie baz danych Oracle.<\/p>\n<p><i>P.S. Artyku\u0142 ten jest do\u015b\u0107 ma\u0142o konkretny: jest tu du\u017co tekstu i prawie brak przyk\u0142ad\u00f3w technicznych. Je\u015bli temat jest og\u00f3lnie interesuj\u0105cy, to jeste\u015bmy gotowi go kontynuowa\u0107 i wr\u00f3ci\u0107 z kontynuacj\u0105, w kt\u00f3rej opowiemy, co si\u0119 zmieni\u0142o w ci\u0105gu ostatnich sze\u015bciu miesi\u0119cy i przedstawimy przyk\u0142ady kodu.<\/p>\n<p>Piszczie komentarze, je\u015bli s\u0105 kwestie, na kt\u00f3re warto zwr\u00f3ci\u0107 uwag\u0119 w przysz\u0142o\u015bci, lub pytania, kt\u00f3re wymagaj\u0105 rozwini\u0119cia.<\/i><\/p>\n<p class=\"for_users_only_msg\">Tylko zarejestrowani u\u017cytkownicy mog\u0105 bra\u0107 udzia\u0142 w ankiecie. <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/auth\/login\/\">Zaloguj si\u0119<\/a><\/noindex>, prosz\u0119.<\/p>\n<h2 class=\"default-block__polling-title\">Pisz\u0105 czy o tym?<\/h2>\n<ul class=\"content-list content-list_polling\">\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    Tak, oczywi\u015bcie<\/p>\n<\/li>\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    Nie, dzi\u0119kuj\u0119<\/p>\n<\/li>\n<\/ul>\n<p>    12 u\u017cytkownik\u00f3w zag\u0142osowa\u0142o. 4 u\u017cytkownik\u00f3w wstrzyma\u0142o si\u0119 od g\u0142osu.<br \/>\n<br \/>\u0179r\u00f3d\u0142o: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/sportmaster_lab\/blog\/465047\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u041f\u0435\u0440\u0432\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u2014 \u0437\u0434\u0435\u0441\u044c. \u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u044c\u0442\u0435 \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u044e. \u041f\u0435\u0440\u0435\u0434 \u0432\u0430\u043c\u0438 \u0441\u0442\u043e\u0438\u0442 \u0437\u0430\u0434\u0430\u0447\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043d\u043e\u0432\u043e\u0433\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u0430. \u0423 \u0432\u0430\u0441 \u0435\u0441\u0442\u044c \u043d\u0430\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043e\u0442 \u0432\u0430\u0448\u0438\u0445 \u043f\u0440\u0435\u0434\u0448\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u0438\u043a\u043e\u0432. \u0415\u0441\u043b\u0438 \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u043e\u0436\u0438\u0442\u044c, \u0447\u0442\u043e \u0432\u044b \u043d\u0438\u043a\u0430\u043a\u0438\u0445 \u043c\u043e\u0440\u0430\u043b\u044c\u043d\u044b\u0445 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u0441\u0442\u0432 \u043d\u0435 \u0438\u043c\u0435\u0435\u0442\u0435, \u0442\u043e \u043a\u0430\u043a \u0431\u044b \u0432\u044b \u043f\u043e\u0441\u0442\u0443\u043f\u0438\u043b\u0438? \u0427\u0430\u0449\u0435 \u0432\u0441\u0435\u0433\u043e \u0432\u0441\u0435 \u0441\u0442\u0430\u0440\u044b\u0435 \u043d\u0430\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043f\u043e\u0434\u0432\u0435\u0440\u0433\u0430\u044e\u0442\u0441\u044f \u0437\u0430\u0431\u0432\u0435\u043d\u0438\u044e \u0438 \u0432\u0441\u0451 \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0441\u044f \u0441\u043d\u0430\u0447\u0430\u043b\u0430. \u0412 \u0447\u0443\u0436\u043e\u043c \u043a\u043e\u0434\u0435 \u043a\u043e\u043f\u0430\u0442\u044c\u0441\u044f \u043d\u0438\u043a\u0442\u043e \u043d\u0435 \u043b\u044e\u0431\u0438\u0442, \u0430 \u043f\u0440\u0438 \u043d\u0430\u043b\u0438\u0447\u0438\u0438 [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":28269,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-37666","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.1.1 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u041f\u0435\u0440\u0432\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u2014 \u0437\u0434\u0435\u0441\u044c.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/unit-testy-v-subd-kak-my-delaem-eto-v-sportmastere-chast-vtoraya\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.1.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"pl_PL\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47Unit-\u0442\u0435\u0441\u0442\u044b \u0432 \u0421\u0423\u0411\u0414 \u2014 \u043a\u0430\u043a \u043c\u044b \u0434\u0435\u043b\u0430\u0435\u043c \u044d\u0442\u043e \u0432 \u0421\u043f\u043e\u0440\u0442\u043c\u0430\u0441\u0442\u0435\u0440\u0435, \u0447\u0430\u0441\u0442\u044c \u0432\u0442\u043e\u0440\u0430\u044f | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u041f\u0435\u0440\u0432\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u2014 \u0437\u0434\u0435\u0441\u044c.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/unit-testy-v-subd-kak-my-delaem-eto-v-sportmastere-chast-vtoraya\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2019-10-31T19:18:55+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2019-10-31T19:18:55+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Testy jednostkowe w systemie baz danych \u2014 jak to robimy w Sportmasterze, cz\u0119\u015b\u0107 druga | ProHoster","description":"Pierwsza cz\u0119\u015b\u0107 \u2014 tutaj.","canonical_url":"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/unit-testy-v-subd-kak-my-delaem-eto-v-sportmastere-chast-vtoraya","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"pl_PL","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47Unit-\u0442\u0435\u0441\u0442\u044b \u0432 \u0421\u0423\u0411\u0414 \u2014 \u043a\u0430\u043a \u043c\u044b \u0434\u0435\u043b\u0430\u0435\u043c \u044d\u0442\u043e \u0432 \u0421\u043f\u043e\u0440\u0442\u043c\u0430\u0441\u0442\u0435\u0440\u0435, \u0447\u0430\u0441\u0442\u044c \u0432\u0442\u043e\u0440\u0430\u044f | ProHoster","og:description":"\u041f\u0435\u0440\u0432\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u2014 \u0437\u0434\u0435\u0441\u044c.","og:url":"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/unit-testy-v-subd-kak-my-delaem-eto-v-sportmastere-chast-vtoraya","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2019-10-31T19:18:55+00:00","article:modified_time":"2019-10-31T19:18:55+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"37666","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":"2026-01-23 18:48:19","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-03-01 01:23:06","updated":"2026-01-23 18:48:19","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/posts\/37666","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/comments?post=37666"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/posts\/37666\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/media\/28269"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/media?parent=37666"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/categories?post=37666"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/tags?post=37666"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}