24 komentářů k článku Testování v PHP: Instalace a základy PHPUnit:

  1. Filips

    nebezpečí tearDown()

    Pokud dojde k násilnému ukončení běhu skriptu tak se sice tearDown() nezavolá ale ukončí se i celý běh phpunitu. Php pak samo uvolní všechny alokované zdroje.
    Naopak, tearDown() se velmi hodí pro uzavírání file handlerů, protože se provede vždy po každé testovací metodě i pokud její asserty selhaly. Je si totiž potřeba uvědomit, že pokud assert selže tak je vykonávání testovací metody ukončeno a tudíž se další příkazy v metodě neprovádějí.

    1. Josef ZamrzlaAutor příspěvku

      Re: nebezpečí tearDown()

      Důraz v tomto případě je kladen na fakt, že nemusí vždy dojít k provedení metody tearDown.

      1. jos

        Re: nebezpečí tearDown()

        a v čem přesně tkví to nebezpečí? jak mi pomůže umístit ten kód jinam, když výsledek bude stejnej?

          1. jos

            Re: nebezpečí tearDown()

            z článku:

            … pokud dojde během testovacího případu k násilnému ukončení běhu skriptu (např. volání nedefinované funkce), pak tato metoda samozřejmě nebude zavolána

            po volání nedefinovaný funkce po sobě neuklidí tak jako tak

            1. HosipLan

              Re: nebezpečí tearDown()

              Pointou je, že tyhle věcí se mají čistit a připravovat v setUp(), tearDown() je zbytečnost.

              1. jos

                Re: nebezpečí tearDown()

                chápu že je to seriál, ale autor si asi tuhle pointu nenechal do dalších dílů a kdyby zrovna jo, tak by to snad rovnou řekl Filipsovi (tazatel)

                čištění v setUp() mě taky napadlo, ale změnou produkčního kódu měnim i zdroje který sou ve hře, takže místo situace „občas to po sobě neuklidí => řešim špatnej zásah do produkčního kódu“ mam situaci „občas se to ne(před)uklidí dobře => řešim ukízecí mechanismus“

                co si kdo zvolí je jeho věc, obojí může ovlivnit následnej běh testu, já bych* častěji bral to první, protože si myslim že ta situace nastává řidčeji, pro tebe je to zbytečnost, takže se budeš se setUp() prodírat jinejma problémama a autor seriálu se k řešení ještě nevyjádřil, každopádně pro něj je to rovnou nebezpečný, což je dost silný slovo

                * „bych“, protože se si nemyslim že u nás tenhle „problém“ máme zapotřebí řešit, spousta věcí se vyřeší samotným zdechnutím php, do databáze nelezem a jediný co po sobě naše testy vobčas trousej sou náhodně pojmenovaný soubory a adresáře (dokonce i když testy proběhnou, pravděpodobně race condition destruktor versus antivir) a kolizí se nebojíme; ještě udělam reklamu – používáme testilenci, což je dost puristickej testovací nástroj, bohužel https://hg.sigpipe.cz/testilence/ je už dlouho down, takže v případě zájmu UTFG, nebo vydržet, znovuuvedení do provozu je slibovaný už dost dlouho

                1. jk

                  Re: nebezpečí tearDown()

                  Zajimalo by me, co nechapete na vete: tearDown nemusi byt zavovan, nespolehejte na to… Nerekl bych, ze si autor nechava dalsi vysvetleni na priste, spis nereaguje na pritrouble komentare… ;-)

                  1. jos

                    Re: nebezpečí tearDown()

                    já tu větu chápu, ale strach z toho že se nezavolá nemam, je přitroublý že chci znát nebezpečí z toho plynoucí? pod článkem pro „začátečníky“?

  2. EsoRimer

    Pěkné, jen to nefunguje :)

    Pěkný článek, ale mě to nefunguje.
    Musel jsem do zdrojáku s textem přidat requre souboru Calc.php.

    A myslím že je zbytečné, aby phpunit procházel a hledal testy v adresáři src/, tak by ho bylo lepší volat místo „phpunit .“ jako „phpunit test“.

    Každopádně se těším na další díly! :)

    1. Josef ZamrzlaAutor příspěvku

      Re: Pěkné, jen to nefunguje :)

      Příkaz „phpunit . “ samozřejmě předpokládá, že se nacházíš v adresáři test :-)

  3. lenoch

    Realny priklad

    Me se ta myslenka automatizovanych testu libi, ale nikdo mi nedokazal uvest realny priklad, chyb jake skutecne nastavaji. Vzdycky je to nejaky priklad typu kalkulacka.
    Dejme tomu ze vracim z databazove tabulky nejake objekty, podle podminky a ty pak treba aktualizuju. Pak se behem vyvoje prida nejaky parametr „skupina“ a ma se zohlednovat pri aktualizaci. A na jednom miste v aplikaci zapomenu tu podminku „skupina“ pridat, takze dojde k aktualizaci zaznamu, ktere by se aktualizovat nemely.
    Jak mi v tom pomuzou unittesty?

    1. Josef ZamrzlaAutor příspěvku

      Re: Realny priklad

      Unit (integration) testy ti v tomhle určitě pomohou, ale samozřejmě pod podmínkou, že budeš mít zmíněný kód dostatečně pokrytý testy. Sleduj seriál, určitě pro tebe bude zajímavý díl o interakci s databázemi, kromě toho, druhá část seriálu bude věnována tomu, jak psát testovatelný kód.

    2. Clary

      Re: Realny priklad

      Záleží na struktuře aplikace. Aktualizuješ přímo objekty nebo záznamy o nich v DB?
      Jakým způsobem se má parametr skupina zohleďnovat při aktualizaci? Jak má vypadat podmínka s tímto parametrem? Jak bylo řečeno v druhém komentáři od autora článku, záleží hodně na pokrytí a na tom, aby byl kód napsán jako testovatelný.

      1. lenoch

        Re: Realny priklad

        Ja to nechci nejak moc rozebirat, protoze se v problematice nevyznam. Zda se mi, ze testing je dobre mozny v pripade, kdy je aplikace napsana zpusobem output = funkcionalita(in­put) bez jakychkoli vedlejsich vlivu.

        Ale v realne aplikaci mame treba databazi, sessions, javascript na klientovi, problemy prohlizece, nastaveni serveru a php, ruzne uzivatele, kteri mohou mit zcela jine konfigurace. To vsechno tvori prostredi, ktere ovlivnuje jestli program pobezi spravne nebo ne. Me pripada, ze to vsechno by v praxi muselo vstupovat do testu, pokud by mely byt dokonale.
        A otestovat vsechny podoby tohoto prostredi se mi zda dost obtizne, kvuli mnozstvi moznosti. Proste vas nenapadne, ze chyba muze nastat pri kombinaci (x,y,u,v,w,z) a tak ji neotestujete.
        A jednoduche testy typu assert(1+1 == 2) jsou zase k nicemu.

        Ale snad se mylim, nemam v te oblasti zkusenosti – rad si prectu pokracovani.

        1. EsoRimer

          Re: Realny priklad

          Tak třeba to nastavení serveru je pěkný příklad. Vyvíjím na svém počítači, všechny testy jsou ok. Pak to dám na server někam na demo a zkusím znova testy …

          Jiný příklad: Píšu si metodu na serializaci a deserializaci objektů. Nejdřív napíšu test kde objekty serializuji, deserializuji a porovnávám výsledek s púvodním objektem. A programuji dokud test neprojde.

          A když někdy v budoucnu upravím serializaci a zapomenu na úpravu deserializace, test to odhalí.

          A ještě si můžu přidat do testu podmínku že serializovaný objekt nesmí být větší než xy bajtů, protože by mi to moc zatěžovalo síť. A když nějaký aktivista objekt nadměrně obohatí o atributy, tak to test zase odhalí.

          atd, atd.

        2. Clary

          Re: Realny priklad

          Samozřejmě testování návratové hodnoty funkce je to nejednodušší co může být, ale v praxi zase tolik takových jednoduchých věcí není. Databáze se obvykle simuluje nějakým testovacím adaptérem (např Zend_Test_DbAdapter ať navážu na zdejší seriál o Zendu), Sessions se zase bereou z nějakého jiného objektu (Environment, NetteHttpSes­sion), který se namockuje (zkráceně se vytvoří zástupný objekt mající námi požadované vlastnosti). Tyto objekty se předávají testované třídě potažmo metodě a poté můžeme testovat buď návratovou hodnotu testované metody nebo změny na těchto předaných objektech.
          Samozřejmě lze testovat i s databází, ale to už nespadá do jednotkových testů. Stejně tak existují testovací prostředky na JavaScript ať už prostřednictvím opět jednotkových testů JavaScriptu (qUnit, Mocha) nebo testů celého prostředí např. pomocí Selenia, které aplikaci proklikává v prohlížeči jako reálný uživatel.

    3. Tomáš

      Re: Realny priklad

      Vidíš to moc izolovaně. Testy jsou části vývoje a je záhodno brát je stejně vážně jako samotný kód. Testovací framework je nástroj, který tomu hodně pomáhá, ale teoreticky se bez něj obejdeš.

      Ve tvém případě si prostě uděláš test, kde si nakrmíš databázi testovacími daty a kontrolouješ, že tvoje funkce vrací, co mají vracet (a zapisují, co mají zapisovat) podle zadání. Při nějaké změně nejdřív upravíš test (mimochodem, většinou je to míň kódu, než „ostrý“ kód). Potom pustíš testy a díváš se, kde všude ti to vylítlo. Ale to už jsem zabrousil do test driven development, me všichni zajdou takhle daleko.

      1. jos

        Re: Realny priklad

        nakrmíš databázi testovacími daty

        pod článkem o PHPUnit pro začátečníky není moc vhodný psát takový věci

        1. Quark

          Re: Realny priklad

          Ale za zmínku to stálo. Myslímže když jde o testování, určitě je vhodné zmínit velení metodikou. A jestli to je TDD je zatím jedno. Aby totiž nedošlo zprvopočátku k mýlce, že testování je všehovšudy jen klikání do kalkulačky, zdali má ošetřeno dělení nulou :-)

    4. jos

      Re: Realny priklad

      <?pseudohnus
      
      iface db
      {
        query($q);
      }
      
      class db_
      implements
        db
      {
        function query($q)
        {
          ...
        }
      }
      
      class mockDb_
      implements
        db
      {
        public $qs = array();
        function query($q)
        {
          $this->qs[] = $q;
        }
      }
      
      class updated
      {
        function set($what, $val)
        {
          ...
        }
        function update(db $d)
        {
          $d->query($this->mkQuery());
        }
        ...
      }
      
      $u = new updated;
      $db = new mockDb;
      $u->set('whatever', 42);
      $u->update($db);
      assertEquals(array('update dual set whatever = 42'), $db->qs);
      $db->qs = array();
      $u->set('whatever', 42);
      $u->update($db);
      assertEquals(array(), $db->qs);

      stačí to takhle?

  4. Ondra K.

    Jen houšť

    Seriál začíná slibně, těším se na další díly. Jen doufám, že brzy půjde více do „praktické hloubky“, jako např. právě zmiňované testy metod/funkcí pracujících s databází, se soubory a s jinými zdroji, které nelze obsáhnout přímo v PHP kódu.

Napsat komentář

Tato diskuse je již příliš stará, pravděpodobně již vám nikdo neodpoví. Pokud se chcete na něco zeptat, použijte diskusní server Devel.cz

Zdroj: https://www.zdrojak.cz/?p=3699