{"id":11131,"date":"2013-03-25T12:46:23","date_gmt":"2013-03-25T11:46:23","guid":{"rendered":"http:\/\/touk.pl\/blog\/?p=11131"},"modified":"2022-08-03T09:58:25","modified_gmt":"2022-08-03T07:58:25","slug":"tests-not-so-scary-as-they-used-to","status":"publish","type":"post","link":"https:\/\/touk.pl\/blog\/2013\/03\/25\/tests-not-so-scary-as-they-used-to\/","title":{"rendered":"<!--:pl-->Testy &#8211; nie takie straszne, jak je maluj\u0105<!--:--><!--:en-->Tests &#8211; not so scary as they used to<!--:-->"},"content":{"rendered":"<p><!--:pl--><\/p>\n<p><!-- p, li { white-space: pre-wrap; } --><\/p>\n<p><!--:--><\/p>\n<p><!--:en--><\/p>\n<figure id=\"attachment_11149\" aria-describedby=\"caption-attachment-11149\" style=\"width: 440px\" class=\"wp-caption alignleft\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-11149\" src=\"http:\/\/touk.pl\/blog\/wp-content\/uploads\/2013\/03\/toukArt.png\" alt=\"Java + Selenium\" width=\"440\" height=\"191\" \/><figcaption id=\"caption-attachment-11149\" class=\"wp-caption-text\">Java + Selenium<\/figcaption><\/figure>\n<p><!-- p, li { white-space: pre-wrap; } --><\/p>\n<p><strong>O czym b\u0119dzie ?<\/strong><\/p>\n<p>O testach interfejsu aplikacji WEB&#8217;owych. Temat, cho\u0107 zwi\u0105zany z programowaniem, to niezbyt popularny w\u015br\u00f3d developer\u00f3w. Pisanie test\u00f3w uchodzi za zaj\u0119cie mniej ambitne, nudne, poboczne i cz\u0119stokro\u0107 traktowane jest jako z\u0142o konieczne.<\/p>\n<p>Testy to temat rzeka. P\u0142ynie ona w wielu serwisach i blogach w internecie. Nie b\u0119d\u0119 wi\u0119c zawraca\u0142 tej rzeki i przepisywa\u0142 internet na nowo. Dolej\u0119 do niej tylko jedn\u0105 wa\u017cn\u0105 informacj\u0119 &#8211; odpowiem na pytanie, czy mo\u017cna zmieni\u0107 powszechny stereotyp na temat test\u00f3w interfejsu na przyk\u0142adzie test\u00f3w Selenium.<\/p>\n<p>Pytanie to zrodzi\u0142o si\u0119 w mojej g\u0142owie, na przestrzeni kilku ostatnich lat. Zadawa\u0142em je sobie niejednokrotnie, my\u015bl\u0105c, \u017ce odpowied\u017a jest oczywista i potwierdzaj\u0105ca stereotyp. Tak by\u0142o, dop\u00f3ki nie trafi\u0142em do du\u017cego projektu, w kt\u00f3rym kto\u015b wreszcie &#8216;odpowiednio&#8217; podszed\u0142 do tematu test\u00f3w.<\/p>\n<p><!--:--><\/p>\n<p><!--more--><\/p>\n<p><!--:pl--><\/p>\n<p><strong>My\u015blisz ze znasz Selenium ?<\/strong><\/p>\n<p>Selenium to \u015brodowisko do obs\u0142ugi test\u00f3w frontend\u00f3w aplikacji internetowych. W wi\u0119kszo\u015bci przypadk\u00f3w u\u017cywane jest wed\u0142ug scenariusza: nagraj test klikaj\u0105c po stronie, a potem odtwarzaj po ka\u017cdej zmianie w kodzie. Niby ok, ale nie do ko\u0144ca.<\/p>\n<p>Nagrane w ten spos\u00f3b testy bardzo szybko staj\u0105 si\u0119 nieutrzymywalne. Wyobra\u017amy sobie 500 test\u00f3w tego typu, a p\u00f3\u017aniej wyobra\u017amy sobie, \u017ce trzeba zmieni\u0107 interfejs aplikacji na inny. Inaczej rozmieszczone kontrolki, panele, inne ich nazwy id&#8217;ki itd. Przerobienie takiej ilo\u015bci test\u00f3w do nowej wersji aplikacji staje si\u0119 praktycznie niemo\u017cliwe, a ju\u017c na pewno nie op\u0142acalne.<\/p>\n<p>Jest kilka sposob\u00f3w by radzi\u0107 sobie z tego typu sytuacjami. Ja opisz\u0119 jedno konkretne rozwi\u0105zanie, kt\u00f3re dla mnie, z punktu widzenia osoby pisz\u0105cej w JAVIE, jest najbardziej wygodne. Testy Selenium mo\u017cna pisa\u0107 w\u0142a\u015bnie w tym j\u0119zyku. &#8216;Dok\u0142adnie&#8217; tak, jak zwyk\u0142e aplikacje. I to Dok\u0142adnie przez du\u017ce &#8216;D&#8217;, bo nie tylko korzystaj\u0105c z j\u0119zyka, ale te\u017c stosuj\u0105c wszelkie zwi\u0105zane z nim dobre praktyki, wzorce projektowe, moc i funkcjonalno\u015b\u0107 test\u00f3w jednostkowych. Nie bez znaczenia jest te\u017c to, \u017ce testy mo\u017cna pisa\u0107 i utrzymywa\u0107 w ulubionym IDE, kt\u00f3re nie tylko u\u0142atwia pisanie, ale te\u017c i utrzymanie test\u00f3w, serwuj\u0105c szereg narz\u0119dzi odpowiedzialnych za np. refaktoring, czy obs\u0142ug\u0119 wersjonowania.<\/p>\n<p><strong>Testy &#8211; jak to si\u0119 robi ?<\/strong><\/p>\n<p>Niech\u0119\u0107 do test\u00f3w bierze si\u0119 g\u0142\u00f3wnie z dw\u00f3ch powod\u00f3w: ich pisanie jest nudne i \u017cmudne. Obie opinie nie s\u0105 niestety bezpodstawne, co poka\u017c\u0119 cytuj\u0105c kod z tutoriala do Selenium+Java ze strony projektu: http:\/\/code.google.com\/p\/selenium\/wiki\/GettingStarted. Podkre\u015blam, \u017ce nie chc\u0119 nikogo obrazi\u0107 i wiem, \u017ce w poni\u017cszym kodzie jest kilka uproszcze\u0144, niemniej jednak tak w\u0142a\u015bnie wygl\u0105da wi\u0119kszo\u015b\u0107 test\u00f3w, kt\u00f3re mo\u017cna znale\u017a\u0107 w internecie. Kto nie wierzy niech sobie wygoogla fraz\u0119: selenium java. [java] \/\/ Go to the Google Suggest home page driver.get(&#8220;http:\/\/www.google.com\/webhp?complete=1&amp;hl=en&#8221;); \/\/ Enter the query string &#8220;Cheese&#8221; WebElement query = driver.findElement(By.name(&#8220;q&#8221;)); query.sendKeys(&#8220;Cheese&#8221;); \/\/ Sleep until the div we want is visible or 5 seconds is over long end = System.currentTimeMillis() + 5000; while (System.currentTimeMillis() &lt; end) { WebElement resultsDiv = driver.findElement(By.className(&#8220;gssb_e&#8221;)); \/\/ If results have been returned, the results are displayed in a drop down. if (resultsDiv.isDisplayed()) { break; } } \/\/ And now list the suggestions List allSuggestions = driver.findElements(By.xpath(&#8220;\/\/td[@class=&#8217;gssb_a gbqfsf&#8217;]&#8221;)); for (WebElement suggestion : allSuggestions) { System.out.println(suggestion.getText()); } } [\/java]\n<p>Co robi powy\u017cszy kod ? Na pierwszy rzut oka wida\u0107, \u017ce.. nic nie wida\u0107. Gdyby nie komentarze, to jego zrozumienie by\u0142oby trudne. Wymaga\u0142oby nie tylko znajomo\u015bci dzia\u0142ania strony google, ale tak\u017ce jej kodu \u017ar\u00f3d\u0142owego. Nawet wtedy jednak, zrozumienie tej instrukcji: driver.findElements(By.xpath(&#8220;\/\/td[@class=&#8217;gssb_a gbqfsf&#8217;]&#8221;)); zaje\u0142oby chwil\u0119.<\/p>\n<p><strong>Testy &#8211; jak mo\u017cna to robi\u0107 lepiej ?<\/strong><\/p>\n<p>Testy Selenium + Java wcale nie musz\u0105 by\u0107 ani nudne, ani \u017cmudne. Mog\u0105 wygl\u0105da\u0107 tak: [java] public void nieMoznaDodacEFakturyDlaPrepaida() { \/\/given StarterPrepaid starter30Minut = new StarterPrepaid30Minut(); KatalogKart karty = Sklep.otworzSklep().menuGlowne.katalogKart(); \/\/when Koszyk koszyk = karty.listaProduktow().wybierz(starter30Minut); \/\/then assertFalse(koszyk.moznaDodacEfakture()); } [\/java]\n<p>Ju\u017c na pierwszy rzut oka wida\u0107 o co chodzi w powy\u017cszym te\u015bcie. Chodzi o to, by sprawdzi\u0107, czy mo\u017cemy wybra\u0107 e-faktur\u0119 kupuj\u0105c ofert\u0119 na starter.<\/p>\n<p>Pisz\u0105c ten test, analizuj\u0105c jego dzia\u0142anie, nie musimy wiedzie\u0107, jak wygl\u0105da implementacja i kod \u017ar\u00f3d\u0142owy aplikacji. Nie obchodzi nas, kt\u00f3ry znacznik html musimy przeczyta\u0107, jakie s\u0105 id&#8217;ki kolejnych przycisk\u00f3w, kt\u00f3re trzeba klikn\u0105\u0107 itd. Test jest na innym, wy\u017cszym poziomie abstrakcji. Operuje na dzia\u0142aniach biznesowych, bezpo\u015brednio dotyczy funkcjonalno\u015bci, kt\u00f3r\u0105 testujemy.<\/p>\n<p>Tak w\u0142a\u015bnie powinny by\u0107 konstruowane testy Selenium. Najpierw nale\u017cy po\u015bwi\u0119ci\u0107 troch\u0119 czasu na napisanie odpowiedniej &#8216;domeny&#8217;, kt\u00f3ra pokryje funkcjonalno\u015b\u0107 aplikacji, a dopiero potem pisa\u0107 testy. Domena ta powinna udost\u0119pnia\u0107 metody biznesowe, takie jak: kup, wy\u015bwietl, zaloguj, dodajDoKoszyka, usunZKoszyka itd. Metody takie powinny ukrywa\u0107 bezpo\u015bredni\u0105 imlpementacje klikni\u0119\u0107, wyszuka\u0144 po XPath, czy oczekiwa\u0144 na prze\u0142adowanie strony www. Jednym s\u0142owem, m\u00f3wi\u0105c kolokwialnie, powinni\u015bmy opakowa\u0107 selenium w co\u015b bardziej wygodnego dla u\u017cytkownika naszej aplikacji.<\/p>\n<p><strong>A co z refaktoringiem ?<\/strong><\/p>\n<p>Opr\u00f3cz u\u0142atwie\u0144 dla programist\u00f3w, podniesienie test\u00f3w na wy\u017cszy poziom abstrakcji, ma jeszcze jedn\u0105, kolosaln\u0105 zalet\u0119. Umo\u017cliwia bezpo\u015brednie przeniesienie scenariuszy testowych na j\u0119zyk aplikacji. Taki test nie tylko szybko si\u0119 czyta, czy tworzy, ale bardzo \u0142atwo weryfikuje i utrzymuje.<\/p>\n<p>Na pocz\u0105tku wspomnia\u0142em o trudno\u015bciach w dostosowaniu &#8216;typowych&#8217; test\u00f3w Selenium do zmian w interfejsie aplikacji. A co z refaktoringiem, przedstawionej przeze mnie konstrukcji test\u00f3w ? Czy faktycznie jest on \u0142atwiejszy ? Wyobra\u017amy wi\u0119c sobie te 500 test\u00f3w napisanych w taki odseparowany biznesowo spos\u00f3b. \u017baden z tych test\u00f3w nie zawiera wi\u0119c odno\u015bnik\u00f3w do kodu html, nie wykorzystuje bezpo\u015brednio link\u00f3w, ani nie zawiera odwo\u0142a\u0144 do input\u00f3w, div&#8217;\u00f3w itd. W \u017cadnym z tych 500 test\u00f3w nie trzeba wi\u0119c NIC zmienia\u0107! Jedyne co trzeba zmieni\u0107, to domen\u0119, cz\u0119\u015b\u0107 wsp\u00f3ln\u0105, kt\u00f3ra bazuje bezpo\u015brednio na kodzie aplikacji. To jednak jest o niebo \u0142atwiejsze ni\u017c zmiana 500 test\u00f3w.<\/p>\n<p><strong>Czy to ju\u017c wszsystko ?<\/strong><\/p>\n<p>Tak, to ju\u017c wszystko. Celem niniejszego wpisu nie by\u0142o pokazanie gotowych rozwi\u0105za\u0144 i ich implementacji krok po kroku. Celem by\u0142o przekonanie do idei rozdzielenia test\u00f3w na dwie warstwy: biznesow\u0105 i t\u0105 zwi\u0105zan\u0105 bezpo\u015brednio z implementacj\u0105. Warto te\u017c zauwa\u017cy\u0107, \u017ce cho\u0107 takie rozwi\u0105zanie nie jest cz\u0119sto stosowane przy okazji test\u00f3w, to jednak nie jest niczym nowym. Moim zdaniem warto je stosowa\u0107, a ju\u017c na pewno warto w po\u0142\u0105czeniu Selenium + Java.<\/p>\n<p><!--:--><\/p>\n<p><!--:en--><\/p>\n<p><strong>My\u015blisz ze znasz Selenium ?<\/strong><\/p>\n<p>Selenium to \u015brodowisko do obs\u0142ugi test\u00f3w frontend\u00f3w aplikacji internetowych. W wi\u0119kszo\u015bci przypadk\u00f3w u\u017cywane jest wed\u0142ug scenariusza: nagraj test klikaj\u0105c po stronie, a potem odtwarzaj po ka\u017cdej zmianie w kodzie. Niby ok, ale nie do ko\u0144ca.<\/p>\n<p>Nagrane w ten spos\u00f3b testy bardzo szybko staj\u0105 si\u0119 nieutrzymywalne. Wyobra\u017amy sobie 500 test\u00f3w tego typu, a p\u00f3\u017aniej wyobra\u017amy sobie, \u017ce trzeba zmieni\u0107 interfejs aplikacji na inny. Inaczej rozmieszczone kontrolki, panele, inne ich nazwy id&#8217;ki itd. Przerobienie takiej ilo\u015bci test\u00f3w do nowej wersji aplikacji staje si\u0119 praktycznie niemo\u017cliwe, a ju\u017c na pewno nie op\u0142acalne.<\/p>\n<p>Jest kilka sposob\u00f3w by radzi\u0107 sobie z tego typu sytuacjami. Ja opisz\u0119 jedno konkretne rozwi\u0105zanie, kt\u00f3re dla mnie, z punktu widzenia osoby pisz\u0105cej w JAVIE, jest najbardziej wygodne. Testy Selenium mo\u017cna pisa\u0107 w\u0142a\u015bnie w tym j\u0119zyku. &#8216;Dok\u0142adnie&#8217; tak, jak zwyk\u0142e aplikacje. I to Dok\u0142adnie przez du\u017ce &#8216;D&#8217;, bo nie tylko korzystaj\u0105c z j\u0119zyka, ale te\u017c stosuj\u0105c wszelkie zwi\u0105zane z nim dobre praktyki, wzorce projektowe, moc i funkcjonalno\u015b\u0107 test\u00f3w jednostkowych. Nie bez znaczenia jest te\u017c to, \u017ce testy mo\u017cna pisa\u0107 i utrzymywa\u0107 w ulubionym IDE, kt\u00f3re nie tylko u\u0142atwia pisanie, ale te\u017c i utrzymanie test\u00f3w, serwuj\u0105c szereg narz\u0119dzi odpowiedzialnych za np. refaktoring, czy obs\u0142ug\u0119 wersjonowania.<\/p>\n<p><strong>Testy &#8211; jak to si\u0119 robi ?<\/strong><\/p>\n<p>Niech\u0119\u0107 do test\u00f3w bierze si\u0119 g\u0142\u00f3wnie z dw\u00f3ch powod\u00f3w: ich pisanie jest nudne i \u017cmudne. Obie opinie nie s\u0105 niestety bezpodstawne, co poka\u017c\u0119 cytuj\u0105c kod z tutoriala do Selenium+Java ze strony projektu: http:\/\/code.google.com\/p\/selenium\/wiki\/GettingStarted. Podkre\u015blam, \u017ce nie chc\u0119 nikogo obrazi\u0107 i wiem, \u017ce w poni\u017cszym kodzie jest kilka uproszcze\u0144, niemniej jednak tak w\u0142a\u015bnie wygl\u0105da wi\u0119kszo\u015b\u0107 test\u00f3w, kt\u00f3re mo\u017cna znale\u017a\u0107 w internecie. Kto nie wierzy niech sobie wygoogla fraz\u0119: selenium java. [java] \/\/ Go to the Google Suggest home page driver.get(&#8220;http:\/\/www.google.com\/webhp?complete=1&amp;hl=en&#8221;); \/\/ Enter the query string &#8220;Cheese&#8221; WebElement query = driver.findElement(By.name(&#8220;q&#8221;)); query.sendKeys(&#8220;Cheese&#8221;); \/\/ Sleep until the div we want is visible or 5 seconds is over long end = System.currentTimeMillis() + 5000; while (System.currentTimeMillis() &lt; end) { WebElement resultsDiv = driver.findElement(By.className(&#8220;gssb_e&#8221;)); \/\/ If results have been returned, the results are displayed in a drop down. if (resultsDiv.isDisplayed()) { break; } } \/\/ And now list the suggestions List allSuggestions = driver.findElements(By.xpath(&#8220;\/\/td[@class=&#8217;gssb_a gbqfsf&#8217;]&#8221;)); for (WebElement suggestion : allSuggestions) { System.out.println(suggestion.getText()); } } [\/java]\n<p>Co robi powy\u017cszy kod ? Na pierwszy rzut oka wida\u0107, \u017ce.. nic nie wida\u0107. Gdyby nie komentarze, to jego zrozumienie by\u0142oby trudne. Wymaga\u0142oby nie tylko znajomo\u015bci dzia\u0142ania strony google, ale tak\u017ce jej kodu \u017ar\u00f3d\u0142owego. Nawet wtedy jednak, zrozumienie tej instrukcji: driver.findElements(By.xpath(&#8220;\/\/td[@class=&#8217;gssb_a gbqfsf&#8217;]&#8221;)); zaje\u0142oby chwil\u0119.<\/p>\n<p><strong>Testy &#8211; jak mo\u017cna to robi\u0107 lepiej ?<\/strong><\/p>\n<p>Testy Selenium + Java wcale nie musz\u0105 by\u0107 ani nudne, ani \u017cmudne. Mog\u0105 wygl\u0105da\u0107 tak: [java] public void nieMoznaDodacEFakturyDlaPrepaida() { \/\/given StarterPrepaid starter30Minut = new StarterPrepaid30Minut(); KatalogKart karty = Sklep.otworzSklep().menuGlowne.katalogKart(); \/\/when Koszyk koszyk = karty.listaProduktow().wybierz(starter30Minut); \/\/then assertFalse(koszyk.moznaDodacEfakture()); } [\/java]\n<p>Ju\u017c na pierwszy rzut oka wida\u0107 o co chodzi w powy\u017cszym te\u015bcie. Chodzi o to, by sprawdzi\u0107, czy mo\u017cemy wybra\u0107 e-faktur\u0119 kupuj\u0105c ofert\u0119 na starter.<\/p>\n<p>Pisz\u0105c ten test, analizuj\u0105c jego dzia\u0142anie, nie musimy wiedzie\u0107, jak wygl\u0105da implementacja i kod \u017ar\u00f3d\u0142owy aplikacji. Nie obchodzi nas, kt\u00f3ry znacznik html musimy przeczyta\u0107, jakie s\u0105 id&#8217;ki kolejnych przycisk\u00f3w, kt\u00f3re trzeba klikn\u0105\u0107 itd. Test jest na innym, wy\u017cszym poziomie abstrakcji. Operuje na dzia\u0142aniach biznesowych, bezpo\u015brednio dotyczy funkcjonalno\u015bci, kt\u00f3r\u0105 testujemy.<\/p>\n<p>Tak w\u0142a\u015bnie powinny by\u0107 konstruowane testy Selenium. Najpierw nale\u017cy po\u015bwi\u0119ci\u0107 troch\u0119 czasu na napisanie odpowiedniej &#8216;domeny&#8217;, kt\u00f3ra pokryje funkcjonalno\u015b\u0107 aplikacji, a dopiero potem pisa\u0107 testy. Domena ta powinna udost\u0119pnia\u0107 metody biznesowe, takie jak: kup, wy\u015bwietl, zaloguj, dodajDoKoszyka, usunZKoszyka itd. Metody takie powinny ukrywa\u0107 bezpo\u015bredni\u0105 imlpementacje klikni\u0119\u0107, wyszuka\u0144 po XPath, czy oczekiwa\u0144 na prze\u0142adowanie strony www. Jednym s\u0142owem, m\u00f3wi\u0105c kolokwialnie, powinni\u015bmy opakowa\u0107 selenium w co\u015b bardziej wygodnego dla u\u017cytkownika naszej aplikacji.<\/p>\n<p><strong>A co z refaktoringiem ?<\/strong><\/p>\n<p>Opr\u00f3cz u\u0142atwie\u0144 dla programist\u00f3w, podniesienie test\u00f3w na wy\u017cszy poziom abstrakcji, ma jeszcze jedn\u0105, kolosaln\u0105 zalet\u0119. Umo\u017cliwia bezpo\u015brednie przeniesienie scenariuszy testowych na j\u0119zyk aplikacji. Taki test nie tylko szybko si\u0119 czyta, czy tworzy, ale bardzo \u0142atwo weryfikuje i utrzymuje.<\/p>\n<p>Na pocz\u0105tku wspomnia\u0142em o trudno\u015bciach w dostosowaniu &#8216;typowych&#8217; test\u00f3w Selenium do zmian w interfejsie aplikacji. A co z refaktoringiem, przedstawionej przeze mnie konstrukcji test\u00f3w ? Czy faktycznie jest on \u0142atwiejszy ? Wyobra\u017amy wi\u0119c sobie te 500 test\u00f3w napisanych w taki odseparowany biznesowo spos\u00f3b. \u017baden z tych test\u00f3w nie zawiera wi\u0119c odno\u015bnik\u00f3w do kodu html, nie wykorzystuje bezpo\u015brednio link\u00f3w, ani nie zawiera odwo\u0142a\u0144 do input\u00f3w, div&#8217;\u00f3w itd. W \u017cadnym z tych 500 test\u00f3w nie trzeba wi\u0119c NIC zmienia\u0107! Jedyne co trzeba zmieni\u0107, to domen\u0119, cz\u0119\u015b\u0107 wsp\u00f3ln\u0105, kt\u00f3ra bazuje bezpo\u015brednio na kodzie aplikacji. To jednak jest o niebo \u0142atwiejsze ni\u017c zmiana 500 test\u00f3w.<\/p>\n<p><strong>Czy to ju\u017c wszsystko ?<\/strong><\/p>\n<p>Tak, to ju\u017c wszystko. Celem niniejszego wpisu nie by\u0142o pokazanie gotowych rozwi\u0105za\u0144 i ich implementacji krok po kroku. Celem by\u0142o przekonanie do idei rozdzielenia test\u00f3w na dwie warstwy: biznesow\u0105 i t\u0105 zwi\u0105zan\u0105 bezpo\u015brednio z implementacj\u0105. Warto te\u017c zauwa\u017cy\u0107, \u017ce cho\u0107 takie rozwi\u0105zanie nie jest cz\u0119sto stosowane przy okazji test\u00f3w, to jednak nie jest niczym nowym. Moim zdaniem warto je stosowa\u0107, a ju\u017c na pewno warto w po\u0142\u0105czeniu Selenium + Java.<\/p>\n<p><!--:--><\/p>\n","protected":false},"excerpt":{"rendered":"O czym b\u0119dzie ? O testach interfejsu aplikacji WEB&#8217;owych. Temat, cho\u0107 zwi\u0105zany z programowaniem, to niezbyt popularny w\u015br\u00f3d&hellip;\n","protected":false},"author":16,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[11],"tags":[71,68,30],"_links":{"self":[{"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/posts\/11131"}],"collection":[{"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/users\/16"}],"replies":[{"embeddable":true,"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/comments?post=11131"}],"version-history":[{"count":30,"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/posts\/11131\/revisions"}],"predecessor-version":[{"id":14910,"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/posts\/11131\/revisions\/14910"}],"wp:attachment":[{"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/media?parent=11131"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/categories?post=11131"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/tags?post=11131"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}