Testování v PHP: asserty a constraints

V dnešním díle si podrobně představíme asserty, které PHPUnit nabízí, a zkusíme si napsat vlastní constraint.

Seriál: Testování a tvorba testovatelného kódu v PHP (13 dílů)

  1. Testování a tvorba testovatelného kódu v PHP 13.8.2012
  2. Testování v PHP: Instalace a základy PHPUnit 27.8.2012
  3. Testování v PHP: asserty a constraints 10.9.2012
  4. Testování v PHP: praktický příklad 1.10.2012
  5. Testování v PHP: anotace 8.10.2012
  6. Testování v PHP: odstiňujeme závislosti 22.10.2012
  7. Testování v PHP: odstiňujeme závislosti II. 5.11.2012
  8. Testování v PHP: testy integrace s databází 19.11.2012
  9. Testování v PHP: testy integrace s databází II. 3.12.2012
  10. Testování v PHP: řízení běhu pomocí parametrů 7.1.2013
  11. Testování v PHP: XML konfigurace PHPUnit 21.1.2013
  12. Testování v PHP: tvorba testovatelného kódu 18.2.2013
  13. Testování v PHP: tvorba testovatelného kódu II. 11.3.2013

Asserty

minulém díle našeho seriálu o testování v PHP jsme si ukázali jak PHPUnit nainstalovat a také jsme si zkusili napsat první, jednoduchý, test. V testu jsme použili assert assertEquals a krátce jsme se seznámili s jeho striktnější obdobou: assertSame.

V dnešním díle si podrobně představíme všechny asserty, které PHPUnit nabízí, včetně již uvedených assertEquals a as­sertSame. Zdrojové kódy s jednoduchými příklady všech assertů, na kterých si vše můžete vyzkoušet, najdete na mém Githubu:

https://github.com/josefzamrzla/serial-testovani-v-php

Assert vs. constraint

Ještě než se vrhnete do zkoumání jednotlivých assertů, je dobré si ujasnit rozdíl mezi pojmy assert a constraint. Je to prosté – assert zjišťuje, zda zkoumaná hodnota vyhovuje uvedenému omezení (constraint). Neboli v pseudokódu:

assertThat(constraint->matches(value) )

Toto je základem všech assertů (nebo asertačních metod, chcete-li) v PHPUnit a umožňuje nám napsat si i vlastní constraints, což si ukážeme v závěru dnešního dílu.

tl;dr

Následuje referenční popis assertů, platný k verzi 3.6.11. Víceméně stejný popis naleznete i v originální dokumentaci, ale ta ne vždy odráží realitu a mnohdy vás může docela zmást. Proto doporučuji níže uvedený přehled alespoň rychle prolétnout, budu upozorňovat na všechny „špeky“, které jsou mi do dnešního dne známy.

Přehled assertů v PHPUnit

Testování shody

assertEquals

assertEquals($expected, $actual[, $message = '', $delta = 0, $maxDepth = 10, $canonicalize = FALSE, $ignoreCase = FALSE])

Základní assert, který je ostatními constraints interně hojně využíván. Ověřuje prostou shodu předpokladu ($expected) se skutečnou hodnotou ($actual). Prostou shodou je myšlena shoda bez typové kontroly, tedy stejně jako v případě operátoru: ==.

Třetím, nepovinným, parametrem může být textová zpráva, která se zobrazí v případě selhání testu. Tento parametr se vyskytuje u všech ostatních assertů, proto jej už nebudu popisovat. Další nepovinné parametry:

  • $delta – pokud jsou obě testované hodnoty (předpoklad i skutečná hodnota) numerické, pak je možné tímto parametrem definovat maximální přípustný rozdíl.
  • $maxDepth – historický parametr, v PHPUnit už není používán.
  • $canonicalize – pokud jsou oběma vstupy (předpoklad i skutečná hodnota) pole a tento parametr je nastaven na bool(true), pak jsou pole nejprve seřazena a teprve potom porovnána.
  • $ignoreCase – pokud je parametr bool(true), jsou oba vstupy porovnávány jako lower-case. Platí i v případě pole řetězců.

assertSame

assertSame($expected, $actual, $message = '')

Striktně ověřuje předpoklad se skutečnou hodnotou. Ověřuje i typovou shodu, v případě asociativních polí záleží i na pořadí prvků.

assertNull

assertNull($actual, $message = '')

Striktně ověřuje, zda skutečná hodnota je NULL.

assertTrue

assertTrue($condition, $message = '')

Striktně ověřuje, zda je výsledek podmínky bool(true).

assertFalse

assertFalse($condition, $message = '')

Striktně ověřuje, zda je výsledek podmínky bool(false).

assertEmpty

assertEmpty($actual, $message = '')

Ověřuje, zda je skutečná hodnota prázdná. K ověření používá funkci empty a jako „prázdné“ označuje: bool(false), null, prázdný řetězec, prázdné pole apod.

Testování větší/menší než

assertGreaterThan

assertGreaterThan($expected, $actual, $message = '')

Ověřuje, zda skutečná hodnota je větší než předpoklad. Je možné použít i pro porovnání řetězců.

assertGreaterThanOrEqual

assertGreaterThanOrEqual($expected, $actual, $message = '')

Ověřuje, zda skutečná hodnota je větší než nebo rovna předpokladu. Je možné použít i pro porovnání řetězců.

assertLessThan, assertLessThanOrEqual

    assertLessThan($expected, $actual, $message = '')
assertLessThanOrEqual($expected, $actual, $message = '')

Opačné varianty předchozích dvou assertů, tedy: menší a menší nebo rovno.

Testování obsahu

assertArrayHasKey

assertArrayHasKey($key, array $array, $message = '')

Ověřuje, zda pole obsahuje očekávaný klíč. Assert pracuje pouze s typem: array.

assertContains

assertContains($needle, $haystack, $message = '', $ignoreCase = FALSE, $checkForObjectIdentity = TRUE)

Ověřuje, zda kolekce $haystack obsahuje předpokládaný prvek. Assert pracuje s typy: array, string a Traversable (iterovatelné objekty). Dalšími parametry jsou:

  • $ignoreCase – při porovnání je ignorována velikost písmen. Má význam pouze u typu: string.
  • $checkForObjectIdentity – použít striktní porovnání. Má význam pouze u typů: Traversable.

assertContainsOnly

assertContainsOnly($type, $haystack, $isNativeType = NULL, $message = '')

Ověřuje, zda kolekce $haystack obsahuje pouze prvky očekávaného typu. Assert pracuje pouze s typy: array a Traversable. Třetím parametrem $isNativeType určujeme, zda očekáváme nativní PHP typ nebo vlastní typ.

assertCount

assertCount($expectedCount, $haystack, $message = '')

Ověřuje, zda kolekce $haystack obsahuje očekávaný počet prvků. Assert pracuje s typy: array, Countable a Iterator.

assertRegExp

assertRegExp($pattern, $string, $message = '')

Ověřuje, zda řetězec $string vyhovuje očekávanému regulárnímu výrazu. Používá PCRE výrazy (funkci preg_match).

assertStringStartsWith, assertStringEndsWith

assertStringStartsWith($prefix, $string, $message = '')
assertStringEndsWith($suffix, $string, $message = '')

Ověřují, zda řetězec začíná nebo končí očekávaným řetězcem.

assertStringEqualsFile

assertStringEqualsFile($expectedFile, $actualString, $message = '', $canonicalize = FALSE, $ignoreCase = FALSE)

Ověřuje, zda obsah řetězce $actualString odpovídá očekávanému řetězci, uloženému v souboru $expectedFile. Assert je vhodný např. pro ověřování (porovnávání) dlouhých řetězců. Volitelné parametry odpovídají stejnojmenným parametrům assertEquals.

assertStringMatchesFormat

assertStringMatchesFormat($format, $string, $message = '')

Ověřuje, zda obsah řetězce $string odpovídá očekávanému formátu. Pro zápis formátu je možné použít následující značky:

  • %e: oddělovač adresářů, např. „/“ v Unix-based operačních systémech.
  • %s: Alespoň jeden jakýkoli znak, kromě znaku konce řádku.
  • %S: Žádný nebo jakýkoli znak, kromě znaku konce řádku.
  • %a: Alespoň jeden jakýkoli znak, včetně znaku konce řádku.
  • %A: Žádný nebo jakýkoli znak, včetně znaku konce řádku.
  • %w: Jakýkoli počet netisknutelných znaků.
  • %i: Jakékoli číslo typu integer se znaménkem, např. +3142, –3142.
  • %d: Jakékoli číslo typu integer bez znaménka, např. 123456.
  • %x: Jakýkoli hexadecimální znak, tzn. 0–9, a-f, A-F.
  • %f: Jakékoli desetinné číslo, např. 3.142, –3.142, 3.142E-10, 3.142e+10.
  • %c: Jakýkoli jeden znak.

assertStringMatchesFormatFile

assertStringMatchesFormatFile($formatFile, $string, $message = '')

Pracuje stejně jako předchozí assert, jen s tím rozdílem, že očekávaný formát je uložen v souboru $formatFile.

assertFileEquals

assertFileEquals($expected, $actual, $message = '', $canonicalize = FALSE, $ignoreCase = FALSE)

Ověřuje, zda jsou obsahy dvou souborů shodné. Volitelné parametry odpovídají stejnojmenným parametrům assertEquals.

assertFileExists

assertFileExists($filename, $message = '')

Ověřuje, zda soubor existuje.

assertInstanceOf

assertInstanceOf($expected, $actual, $message = '')

Ověřuje, zda proměnná $actual je instancí očekávaného typu.

assertInternalType

assertInternalType($expected, $actual, $message = '')

Ověřuje, zda proměnná $actual je očekávaného typu.

Reflexe

assertClassHasAttribute

assertClassHasAttribute($attributeName, $className, $message = '')

Pomocí reflexe ověřuje, zda třída obsahuje očekávaný atribut bez ohledu na to, zda je statický nebo instanční.

assertClassHasStaticAttribute

assertClassHasStaticAttribute($attributeName, $className, $message = '')

Pomocí reflexe ověřuje, zda třída obsahuje očekávaný statický atribut.

assertObjectHasAttribute

assertObjectHasAttribute($attributeName, $object, $message = '')

Pomocí reflexe ověřuje, zda instance obsahuje očekávaný atribut bez ohledu na to, zda je statický nebo instanční.

Kromě těchto tří assertů, pracujících s reflexí, nabízí PHPUnit obdobu téměř všech assertů, uvedených v tomto díle, v podobě assertAttribute…. Tzn. např. assertAttributeEquals, assertAttributeSame, assertAttributeContains a mnoho dalších. Jak už název napovídá, tyto asserty se používají pro testování obsahu atributů tříd nebo instancí. Jejich funkčnost je shodná s jejich předlohami, proto je nebudu explicitně popisovat.

HTML/XML

assertEqualXMLStructure

assertEqualXMLStructure(DOMElement $expectedElement, DOMElement $actualElement, $checkAttributes = FALSE, $message = '')

Ověřuje, zda je XML element $actualElement shodný s očekávaným $expectedElement. Pokud je parametr$checkAttributes nastaven na bool(true), pak je ověřována shoda včetně atributů (existence, ne hodnot!).

assertXmlFileEqualsXmlFile

assertXmlFileEqualsXmlFile($expectedFile, $actualFile, $message = '')

Ověřuje, zda je obsah XML souboru $actualFile shodný s očekávaným souborem $expectedFile.

assertXmlStringEqualsXmlFile

assertXmlStringEqualsXmlFile($expectedFile, $actualXml, $message = '')

Ověřuje, zda obsahem řetězce $actualXml je XML struktura shodná s obsahem souboru $expectedFile. Vhodný pro porovnávání větších XML struktur – očekávanou XML strukturu můžeme uložit mimo kód testu.

assertXmlStringEqualsXmlString

assertXmlStringEqualsXmlString($expectedXml, $actualXml, $message = '')

Ověřuje, zda obsahem řetězce $actualXml je XML struktura shodná s předpokládanou XML strukturou v proměnné $expectedXml.

assertTag

assertTag($matcher, $actual, $message = '', $isHtml = TRUE)

Patrně největší chameleon mezi asserty v PHPUnit. Ověřuje, zda obsah řetězce $actual vyhovuje kritériím, nastaveným v „matcheru“ $matcher. Tzv. matcher (opět se obávám, že neexistuje vhodný překlad) je asociativní pole obsahující různé sady nebo kombinace podmínek. Při prvním pohledu vás asi jejich množství vyděsí, ale opravdu to není tak hrozné. Oficiální dokumentace obsahuje příliš obecný popis a chybová zpráva „Failed asserting that false is true“ vám asi taky moc nepomůže.

Vše je o tom, že musí existovat element, o kterém platí všechny podmínky v matcheru najednou. Např. existuje element s názvem (tag) div a zároveň s atributem id=„uniqId“.

$matcher = array("tag" => "div", "id" => "uniqId");

Dalšími podmínkami potom můžeme upřesňovat výběr, včetně zanořování matcherů do sebe. Tzn. můžeme hledat element, který vyhovuje podmínkám matcheru a zároveň jeho potomek vyhovuje podmínkám jiného matcheru a zároveň jeho sourozenec vyhovuje podmínkám … atd. Protože se assertTag používá i pro testování XML, budu v dalším textu používat spíše označení element než tag. Další možnosti matcheru:

  • tag: element má požadovaný název. Ač se to na první pohled nezdá, toto je poměrně podivné omezení. Pokud jej totiž nepoužijete, tak to neznamená, že podmínce vyhovuje libovolně pojmenovaný element, ale pouze element ze skupiny: <a>, <abbr>, <acronym>, <address>, <area>, <b>, <base>, <bdo>, <big>, <blockquote>, <body>, <br>, <button>, <caption>, <cite>, <code>, <col>, <colgroup>, <dd>, <del>, <div>, <dfn>, <dl>, <dt>, <em>, <fieldset>, <form>, <frame>, <frameset>, <h1>, <h2>, <h3>, <h4>, <h5>, <h6>, <head>, <hr>, <html>, <i>, <iframe>, <img>, <input>, <ins>, <kbd>, <label>, <legend>, <li>, <link>, <map>, <meta>, <noframes>, <noscript>, <object>, <ol>, <optgroup>, <option>, <p>, <param>, <pre>, <q>, <samp>, <script>, <select>, <small>, <span>, <strong>, <style>, <sub>, <sup>, <table>, <tbody>, <td>, <textarea>, <tfoot>, <th>, <thead>, <title>, <tr>, <tt>, <ul>, <var>. To se v dokumentaci nedočtete :-)
  • id: element má požadovaný atribut ID.
  • attributes: element má požadované atributy, které odpovídají asociativnímu poli.
  • content: element má požadovaný textový obsah.
  • parent: rodičovský element odpovídá kritériím dalšího matcheru (vnořování matcherů).
  • child: alespoň jeden z přímých potomků elementu odpovídá kritériím dalšího matcheru.
  • ancestor: alespoň jeden libovolný předek odpovídá kritériím dalšího matcheru.
  • descendant: alespoň jeden libovolný potomek odpovídá kritériím dalšího matcheru.
  • children: element má seznam potomků, který odpovídá následujícím podmínkám:
    • count: počet potomků vyhovujících matcheru only je roven zadanému (není možné nastavit omezení na nulu!).
    • less_than: počet potomků vyhovujících matcheru only je menší než zadaný.
    • greater_than: počet potomků vyhovujících matcheru only je větší než zadaný.
    • only: matcher omezující potomky, kteří budou započítáni. I tady pozor – rodičovský element musí mít POUZE potomky, které tomuto matcheru odpovídají!

Dodatečný parametr $isHtml rozlišuje, zda se názvy elementů (omezení tag) budou hledat case-sensitive módu ($isHtml = false) nebo case-insensitive ($isHtml = true).

S tímto assertem si můžete užít hodně zábavy, ať už v pozitivním nebo negativním smyslu. Tak či tak, dobře se hodí pro integrační nebo akceptační testy, kdy pracujeme s finálním html výstupem aplikace.

assertSelectCount

assertSelectCount($selector, $count, $actual, $message = '', $isHtml = TRUE)

Ověřuje existenci elementu(ů) v řetězci $actual pomocí CSS selektorů. V oficiální dokumentaci je parametr $selector označen za array, ale nenechte se tím zmást, selektor se zadává jako string. V selektoru je možné používat jen základní CSS selekci:

  • libovolný potomek, např.: div div p
  • přímý potomek, např.: div > p
  • id, class, např.: div#main .content (! pouze v html módu !)
  • atributy s konkrétní hodnotou, např.: foo[bar=„123“]
  • atributy obsahující slovo, např.: foo[bar~=„word“]
  • atributy obsahující substring, např.: foo[bar*=„some substring“]. U všech atributů platí, že víceslovné hodnoty musí být uvozeny uvozovkami, ne apostrofy!

Druhým parametrem $count potom nastavujeme očekávaný počet. Může nabývat celkem tří typů:

  • boolean – očekáváme pouze exitenci (true) nebo absenci (false) elementu
  • integer – očekáváme přesný počet elementů
  • array – očekáváme počet elementů odpovídající zadanému rozsahu. Klíčemi pole jsou operátory: >, >=, <, <= , hodnotami pak krajní meze rozsahu. Např.: array(„>“ ⇒ 1, „<=“ ⇒ 10) očekává alespoň jeden, ale maximálně deset elementů.

Třetí parametr $isHtml určuje, zda chceme pracovat v HTML nebo XML módu. Zde je rozdíl např. v tom, jak hledáme elementy s parametrem ID. V HTML módu můžeme jednoduše použít selektor #, zatímco v XML módu musíme použít selektor hodnota atributu [id=„…“].

assertSelectEquals, assertSelectRegExp

assertSelectEquals($selector, $content, $count, $actual, $message = '', $isHtml = TRUE)
assertSelectRegExp($selector, $pattern, $count, $actual, $message = '', $isHtml = TRUE)

Pro tyto dva asserty platí to samé, jako pro assertSelectCount, jen můžete navíc nastavit omezení na obsah hledaných elementů.

assertSelectEquals – omezení obsahu na prostou shodu s očekávanou hodnotou $content

assertSelectRegExp – omezení obsahu na shodu vyhovující PCRE výrazu $pattern

Vlastní constraints

Jeden assert nám v seznamu ještě chybí – assertThat.

assertThat($value, PHPUnit_Framework_Constraint $constraint, $message = '')

Jak už jsem psal na začátku tohoto dílu – jde o assert, který je základem všech výše uvedených. Např. assertNull si můžeme představit jako:

    public function assertNull($actual, $message = '')
    {
        $this->assertThat($actual, new PHPUnit_Framework_Constraint_IsNull());
    }

Jde samozřejmě pouze o pseudokód, ale víceméně takto je assertNull skutečně implementován. Stejně tak i ostatní asserty. A modří už vědí – úplně stejně můžeme volat vlastní constraints.

ContainsSubstringConstraint

Předpokládejme, že chceme testovat obsah pole řetězců, ale assertContains nám nevyhovuje, protože obsahem našeho pole jsou řetězce, které jsou poměrně dlouhé a my nechceme testovat shodu na celý řetězec, stačí nám shoda se sub-řetězcem. Hledáme tedy něco jako assertContainsSubstring. Bohužel žádný takový constraint neexistuje, takže nám nezbude nic jiného, než si jej napsat. Není to nic težkého – vlastní constraint vytvoříme jako potomka třídyPHPUnit_Framework_Constraint, pojmenujeme jej třeba ContainsSubstringConstraint.

    class ContainsSubstringConstraint extends PHPUnit_Framework_Constraint
    {
        public function toString()
        {
            return "string array contains ";
        }
    }

Protože rodičovská třída PHPUnit_Framework_Con­straint implementuje rozhraníPHPUnit_Framework_Sel­fDescribing, musíme implementovat metodu toString, která náš constraint popisuje.

Budeme potřebovat porovnávat dva subjekty, proto musíme přidat konstruktor vyžadující jeden parametr – hledaný řetězec. Aby měl constraint smysl a nevracel nám falešně pozitivní shody, vložíme rovnou i omezení na parametr – musí se jednat o neprázdný řetězec nebo číslo. Nic jiného neumožníme.

    class ContainsSubstringConstraint extends PHPUnit_Framework_Constraint
    {
        private $needle;

        public function __construct($needle)
        {
            if (!((is_string($needle) || is_numeric($needle)) && strlen($needle))) {
                throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'string');
            }

            $this->needle = (string)$needle;
        }

        public function toString()
        {
            return "string array contains ";
        }
    }

Nyní už stačí jen implementovat šablonovou metodu matches($other), která je rodičovskou třídou volána, a která by měla vracet bool(true) pokud parametr $other vyhovuje podmínkám, v ostatních případech bool(false). Parametrem $other je v našem případě pole nebo iterovatelná kolekce, ve které budeme řetězec hledat.

    class ContainsSubstringConstraint extends PHPUnit_Framework_Constraint
    {
        private $needle;

        public function __construct($needle)
        {
            if (!((is_string($needle) || is_numeric($needle)) && strlen($needle))) {
                throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'string');
            }

            $this->needle = (string)$needle;
        }

        public function toString()
        {
            return "string array contains ";
        }

        protected function matches($other)
        {
            if (!(((is_array($other) && count($other))) || ($other instanceof Traversable))) {
                throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'array');
            }

            foreach ($other as $item) {
                if (is_string($item) && strstr($item, $this->needle) !== false) {
                    return true;
                }
            }

            return false;
        }
    }

Stejně jako v případě konstruktoru, i zde omezíme parametr pouze na očekávaný typ: array. Protože se nám tento constraint může v budoucnu hodit i pro iterovatelné kolekce, povolíme i instance implementující rozhraní Traversable. Zbývá už jen danou kolekci nebo pole prohledat a při prvním nálezu požadovaného řetězce vrátit bool(true).

Tím je vlastní constraint hotov. Příklad použití:

    $strings = array(
        "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse congue tincidunt mi...",
        "Maecenas euismod lorem at leo pretium vehicula. Aliquam libero nunc, blandit at accumsan ...",
        "Sed risus urna, varius ac sodales sed, sodales at erat. Sed eu tellus ac mi interdum ..."
    );

    // should be found
    $this->assertThat($strings, new ContainsSubstringConstraint("Aliquam libero nunc"));

Logická spojování constraints

Kromě takto prostého použití můžeme používat i jiné constraints, které slouží k logickému spojování jiných constraints:

  • PHPUnit_Framework_Constraint_And – součin, logické AND.
    Uvnitř constraint lze volat jako: $this->logicalAnd()
  • PHPUnit_Framework_Constraint_Or – součet, logické OR.
    Uvnitř constraint lze volat jako: $this->logicalOr()
  • PHPUnit_Framework_Constraint_Not – negace, logické NOT.
    Uvnitř constraint lze volat jako: $this->logicalNot()
  • PHPUnit_Framework_Constraint_Xor – exkluzivní součet, logické XOR.
    Uvnitř constraint lze volat jako: $this->logicalXor()

Díky těmto constraints můžeme poskládat širokou škálu různých omezení, jak ze stávajících constraints, tak z našich vlastních. Příklad 1.: zadaný řetězec nesmí být nalezen

    $strings = array(
        "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse congue tincidunt mi...",
        "Maecenas euismod lorem at leo pretium vehicula. Aliquam libero nunc, blandit at accumsan ...",
        "Sed risus urna, varius ac sodales sed, sodales at erat. Sed eu tellus ac mi interdum ..."
    );

    // tento retezec nesmi byt soucastni pole retezcum, jinak fail
    $this->assertThat($strings,
        $this->logicalNot(new ContainsSubstringConstraint("This string should not be found.")));

Příklad 2. zadaný řetězec musí být nalezen a zároveň kolekce musí mít pouze prvky typu string

    $strings = array(
        "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse congue tincidunt mi...",
        "Maecenas euismod lorem at leo pretium vehicula. Aliquam libero nunc, blandit at accumsan ...",
        "Sed risus urna, varius ac sodales sed, sodales at erat. Sed eu tellus ac mi interdum ..."
    );

    // $strings obsahuje pouze retezce a zaroven obsahuje retezec
    $this->assertThat($strings,
        $this->logicalAnd(
            new PHPUnit_Framework_Constraint_TraversableContainsOnly("string"),
            new ContainsSubstringConstraint("Aliquam libero nunc")
        )
    );

To je pro dnešek vše, minule slíbené anotace si necháme na příště, i tak se nám tento díl rozlezl víc, než jsem čekal. Stáhněte se zdrojové kódy a vše vyzkoušejte. Příště se kromě už zmíněných anotací podíváme na CLI parametry a bootstrap xml, tedy na možnosti nastavení běhu PHPUnit. Opět s řadou tipů, upozornění a vychytávek.

Josef Zamrzla pracuje jako nezávislý vývojář. Před tím působil coby software development engineer ve společnosti Skype, programátor ve společnosti LMC s.r.o. (provozovatel pracovních portálů www.jobs.cz a www.prace.cz) nebo teamleader ve společnosti Kasa.cz 

Věděli jste, že nám můžete zasílat zprávičky? (Jen pro přihlášené.)

Komentáře: 43

Přehled komentářů

jen reference Re: Testování v PHP: asserty a constraints
Josef Zamrzla Re: Testování v PHP: asserty a constraints
michal díky
vidya ehmm
prezdivka je povinna Re: ehmm
Vojtěch Modří vědí :)
jos Re: Modří vědí :)
Rexxar Testovanie
Jerry12 Re: Testovanie
vidya Re: Testovanie
arron Re: Testovanie
arron Re: Testovanie
Honza Re: Testovanie
Martin Hassman Re: Testovanie
Honza Re: Testovanie
Petr P. Re: Testovanie
Honza Re: Testovanie
Martin Hassman Re: Testovanie
Martin Hassman Re: Testovanie
Honza Re: Testovanie
Martin Hassman Re: Testovanie
Honza Re: Testovanie
Honza Re: Testovanie
Clary Re: Testovanie
Honza Re: Testovanie
Martin Hassman Re: Testovanie
Clary Re: Testovanie
Honza Re: Testovanie
arron Re: Testovanie
Honza Re: Testovanie
Josef Zamrzla Re: Testovanie
Honza Re: Testovanie
Josef Zamrzla Re: Testovanie
Martin Hassman Re: Testovanie
jos Re: Testovanie
Clary Re: Testovanie
Honza Re: Testovanie
arron Re: Testovanie
Michal Luxusni diskuze
Martin Hassman Re: Luxusni diskuze
Josef Zamrzla Re: Luxusni diskuze
omelkes Re: Luxusni diskuze
Michal Re: Luxusni diskuze
Zdroj: https://www.zdrojak.cz/?p=3706