-
-
Notifications
You must be signed in to change notification settings - Fork 71
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
24 changed files
with
3,468 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{{composer: nette/tester}} | ||
{{maintitle: Nette Tester – pohodové testování v PHP}} | ||
{{description: Nette Tester je jednoduchý a přitom velmi šikovný nástroj na testování PHP kódu.}} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
- [Začínáme s Nette Tester |guide] | ||
- [Psaní testů |writing-tests] | ||
- [Spouštění testů |running-tests] | ||
|
||
- [Aserce |assertions] | ||
- [Anotace testů |test-annotations] | ||
- [TestCase] | ||
- [Pomocné třídy |helpers] | ||
|
||
- [Průběžné testování s Travis |testing-with-travis] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
- [Úvod |@home] | ||
- [Dokumentace |guide] | ||
- "GitHub .[link-external]":https://github.com/nette/tester |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,280 @@ | ||
Aserce | ||
****** | ||
|
||
.[perex] | ||
Aserce se používají k potvrzení, že skutečná hodnota odpovídá očekávané hodnotě. Jde o metody třídy `Tester\Assert`. | ||
|
||
Vybírejte co nejvhodnější aserce. Je lepší `Assert::same($a, $b)` než `Assert::true($a === $b)`, protože při selhání zobrazí smysluplnou chybovou zprávu. Ve druhém případě pouze `false should be true` což nám o obsahu proměnných `$a` a `$b` nic neříká. | ||
|
||
Většina assercí také může mít volitelnou popisku v parametru `$description`, která se zobrazí v chybové hlášce, pokud očekávání selže. | ||
|
||
Příklady předpokládají vytvořený alias: | ||
|
||
```php | ||
use Tester\Assert; | ||
``` | ||
|
||
|
||
Assert::same($expected, $actual, string $description = null) .[method] | ||
---------------------------------------------------------------------- | ||
`$expected` musí být totožný s `$actual`. To samé jako PHP operátor `===`. | ||
|
||
|
||
Assert::notSame($expected, $actual, string $description = null) .[method] | ||
------------------------------------------------------------------------- | ||
Opak `Assert::same()`, tedy to samé jako PHP operátor `!==`. | ||
|
||
|
||
Assert::equal($expected, $actual, string $description = null) .[method] | ||
----------------------------------------------------------------------- | ||
`$expected` musí být stejný s `$actual`. Na rozdíl od `Assert::same()` se ignoruje identita objektů, pořadí dvojic klíčů => hodnota v polích a marginálně odlišná desetinná čísla. | ||
|
||
Následující případy jsou shodné z pohledu `equal()`, ale nikoliv `same()`: | ||
|
||
```php | ||
Assert::equal(0.3, 0.1 + 0.2); | ||
Assert::equal($obj, clone $obj); | ||
Assert::equal( | ||
['first' => 11, 'second' => 22], | ||
['second' => 22, 'first' => 11] | ||
); | ||
``` | ||
|
||
Ovšem pozor, pole `[1, 2]` a `[2, 1]` stejné nejsou, protože se liší jen pořadí hodnot, nikoliv dvojic klíč => hodnota. Pole `[1, 2]` lze zapsat také jako `[0 => 1, 1 => 2]` a za stejné se proto bude považovat `[1 => 2, 0 => 1]`. | ||
|
||
Dále lze v `$expected` použít tzv. [#očekávání]. | ||
|
||
|
||
Assert::notEqual($expected, $actual, string $description = null) .[method] | ||
-------------------------------------------------------------------------- | ||
Opak `Assert::equal()`. | ||
|
||
|
||
Assert::contains($needle, string|array $actual, string $description = null) .[method] | ||
------------------------------------------------------------------------------------- | ||
Pokud je `$actual` řetězec, musí obsahovat podřetězec `$needle`. Pokud je pole, musí obsahovat prvek `$needle` (porovnává se striktně). | ||
|
||
|
||
Assert::notContains($needle, string|array $actual, string $description = null) .[method] | ||
---------------------------------------------------------------------------------------- | ||
Opak `Assert::contains()`. | ||
|
||
|
||
Assert::hasKey(string|int $needle, array $actual, string $description = null) .[method]{data-version:2.4} | ||
--------------------------------------------------------------------------------------------------------- | ||
`$actual` musí být pole a musí obsahovat klíč `$needle`. | ||
|
||
|
||
Assert::notHasKey(string|int $needle, array $actual, string $description = null) .[method]{data-version:2.4} | ||
------------------------------------------------------------------------------------------------------------ | ||
`$actual` musí být pole a nesmí obsahovat klíč `$needle`. | ||
|
||
|
||
Assert::true($value, string $description = null) .[method] | ||
---------------------------------------------------------- | ||
`$value` musí být `true`, tedy `$value === true`. | ||
|
||
|
||
Assert::truthy($value, string $description = null) .[method] | ||
------------------------------------------------------------ | ||
`$value` musí být pravdivý, tedy splní podmínku `if ($value) ...`. | ||
|
||
|
||
Assert::false($value, string $description = null) .[method] | ||
----------------------------------------------------------- | ||
`$value` musí být `false`, tedy `$value === false`. | ||
|
||
|
||
Assert::falsey($value, string $description = null) .[method] | ||
------------------------------------------------------------ | ||
`$value` musí být nepravdivý, tedy splní podmínku `if (!$value) ...`. | ||
|
||
|
||
Assert::null($value, string $description = null) .[method] | ||
---------------------------------------------------------- | ||
`$value` musí být `null`, tedy `$value === null`. | ||
|
||
|
||
Assert::notNull($value, string $description = null) .[method] | ||
------------------------------------------------------------- | ||
`$value` nesmí být `null`, tedy `$value !== null`. | ||
|
||
|
||
Assert::nan($value, string $description = null) .[method] | ||
--------------------------------------------------------- | ||
`$value` musí být Not a Number. Pro testování NAN hodnoty používejte vyhradně `Assert::nan()`. Hodnota NAN je velmi specifická a aserce `Assert::same()` nebo `Assert::equal()` mohou fungovat neočekávaně. | ||
|
||
|
||
Assert::count($count, Countable|array $value, string $description = null) .[method] | ||
----------------------------------------------------------------------------------- | ||
Počet prvků ve `$value` musí být `$count`. Tedy to samé jako `count($value) === $count`. | ||
|
||
|
||
Assert::type(string|object $type, $value, string $description = null) .[method] | ||
------------------------------------------------------------------------------- | ||
`$value` musí být daného typu. Jako `$type` můžeme použít řetězec: | ||
- `array` | ||
- `list` - pole indexované podle vzestupné řady numerických klíčů od nuly | ||
- `bool` | ||
- `callable` | ||
- `float` | ||
- `int` | ||
- `null` | ||
- `object` | ||
- `resource` | ||
- `scalar` | ||
- `string` | ||
- název třídy nebo přímo objekt, potom musí být `$value instanceof $type` | ||
|
||
|
||
Assert::exception(callable $callable, string $class, string $message = null, $code = null) .[method] | ||
---------------------------------------------------------------------------------------------------- | ||
Při zavolání `$callable` musí být vyhozena výjimka třídy `$class`. Pokud uvedeme `$message`, musí [odpovídat vzoru|#assert-match] i zpráva výjimky a pokud uvedeme `$code`, musí se striktně shodovat i kódy. | ||
|
||
Následující test selže, protože neodpovídá zpráva výjimky: | ||
|
||
```php | ||
Assert::exception(function () { | ||
throw new App\InvalidValueException('Zero value'); | ||
}, App\InvalidValueException::class, 'Value is to low'); | ||
``` | ||
|
||
`Assert::exception()` vrací vyhozenou výjimku, lze tak otestovat i výjimku zahnízděnou. | ||
|
||
```php | ||
$e = Assert::exception(function () { | ||
throw new MyException('Something is wrong', 0, new RuntimeException); | ||
}, MyException::class, 'Something is wrong'); | ||
|
||
Assert::type(RuntimeException::class, $e->getPrevious()); | ||
``` | ||
|
||
|
||
Assert::error(string $callable, int|string|array $type, string $message = null) .[method] | ||
----------------------------------------------------------------------------------------- | ||
Kontroluje, že funkce `$callable` vygenerovala očekávané chyby (tj. varování, notices atd). Jako `$type` uvedeme jednu z konstant `E_...`, tedy například `E_WARNING`. A pokud uvedeme `$message`, musí [odpovídat vzoru|#assert-match] i chybová zpráva. Například: | ||
|
||
```php | ||
Assert::error(function () { | ||
$i++; | ||
}, E_NOTICE, 'Undefined variable: i'); | ||
``` | ||
|
||
Pokud callback vygeneruje více chyb, musíme je všechny očekávat v přesném pořadí. V takovém případě předáme v `$type` pole: | ||
|
||
```php | ||
Assert::error(function () { | ||
$a++; | ||
$b++; | ||
}, [ | ||
[E_NOTICE, 'Undefined variable: a'], | ||
[E_NOTICE, 'Undefined variable: b'], | ||
]); | ||
``` | ||
|
||
.[note] | ||
Pokud jako `$type` uvedete název třídy, chová se stejně jako `Assert::exception()`. | ||
|
||
|
||
Assert::noError(callable $callable) .[method] | ||
--------------------------------------------- | ||
Kontroluje, že funkce `$callable` nevygenerovala žádné varování, chybu nebo výjimku. Hodí se pro testování kousků kódu, kde není žádná další aserce. | ||
|
||
|
||
Assert::match(string $pattern, $actual, string $description = null) .[method] | ||
----------------------------------------------------------------------------- | ||
`$actual` musí vyhovět vzoru `$pattern`. Můžeme použít dvě varianty vzorů: regulární výrazy nebo zástupné znaky. | ||
|
||
Pokud jako `$pattern` předáme regulární výraz, k jeho ohraničení musíme použít `~` nebo `#`, jiné oddělovače nejsou podporovány. Například test, kdy `$var` musí obsahovat pouze hexadecimální číslice: | ||
|
||
```php | ||
Assert::match('#^[0-9a-f]$#i', $var); | ||
``` | ||
|
||
Druhá varianta je podobná běžnému porovnání řetězců, ale v `$pattern` můžeme použít různé zástupné znaky: | ||
|
||
- `%a%` jeden nebo více znaků, kromě znaků konce řádku | ||
- `%a?%` žádný nebo více znaků, kromě znaků konce řádku | ||
- `%A%` jeden nebo více znaků, včetně znaků konce řádku | ||
- `%A?%` žádný nebo více znaků, včetně znaků konce řádku | ||
- `%s%` jeden nebo více bílých znaků, kromě znaků konce řádku | ||
- `%s?%` žádný nebo více bílých znaků, kromě znaků konce řádku | ||
- `%S%` jeden nebo více znaků, kromě bílých znaků | ||
- `%S?%` žádný nebo více znaků, kromě bílých znaků | ||
- `%c%` jakýkoli jeden znak, kromě znaku konce řádku | ||
- `%d%` jedna nebo více číslic | ||
- `%d?%` žádná nebo více číslic | ||
- `%i%` znaménková celočíselná hodnota | ||
- `%f%` číslo s desetinnou čárkou | ||
- `%h%` jedna nebo více hexadecimálních číslic | ||
- `%w%` jeden nebo více alfanumerických znaků | ||
- `%%` znak % | ||
|
||
Příklady: | ||
|
||
```php | ||
# Opět test na hexadecimální číslo | ||
Assert::match('%h%', $var); | ||
|
||
# Zobecnění cesty k souboru a čísla řádky | ||
Assert::match('Error in file %a% on line %i%', $errorMessage); | ||
``` | ||
|
||
|
||
Assert::matchFile(string $file, $actual, string $description = null) .[method] | ||
------------------------------------------------------------------------------ | ||
Aserce je totožná s [Assert::match() |#assert-match], ale vzor se načítá ze souboru `$file`. To je užitečné pro testování velmi dlouhých řetězců. Soubor s testem zůstane přehledný. | ||
|
||
|
||
Assert::fail(string $message, $actual = null, $expected = null) .[method] | ||
------------------------------------------------------------------------- | ||
Tato aserce vždy selže. Někdy se to prostě hodí. Volitelně můžeme uvést i očekávanou a aktuální hodnotu. | ||
|
||
|
||
Očekávání | ||
--------- | ||
Když chceme porovnat složitější struktury s nekonstantními prvky, nemusí být výše uvedené aserce dostatečné. Například testujeme metodu, která vytváří nového uživatele a vrací jeho atributy jako pole. Hodnotu hashe hesla neznáme, ale víme, to že musí být hexadecimální řetězec. A o dalším prvku víme jen, že to musí být objekt `DateTime`. | ||
|
||
V těchto situacích můžeme použít `Tester\Expect` uvnitř `$expected` parametru metod `Assert::equal()` a `Assert::notEqual()`, pomocí kterých lze strukturu snadno popsat. | ||
|
||
```php | ||
use Tester\Expect; | ||
|
||
Assert::equal([ | ||
'id' => Expect::type('int'), # očekáváme celé číslo | ||
'username' => 'milo', | ||
'password' => Expect::match('%h%'), # očekáváme řetězec vyhovující vzoru | ||
'created_at' => Expect::type(DateTime::class), # očekáváme instanci třídy | ||
], User::create(123, 'milo', 'RandomPaSsWoRd')); | ||
``` | ||
|
||
S `Expect` můžeme provádět téměř stejné aserce jako s `Assert`. Tedy jsou nám k dispozici metody `Expect::same()`, `Expect::match()`, `Expect::count()` atd. Navíc je můžeme zřetězit: | ||
|
||
```php | ||
Expect::type(MyIterator::class)->andCount(5); # očekáváme MyIterator a počet prvků 5 | ||
``` | ||
|
||
Anebo můžeme psát vlastní handlery asercí. | ||
|
||
```php | ||
Expect::that(function ($value) { | ||
# vrátíme false, pokud očekávání selže | ||
}); | ||
``` | ||
|
||
|
||
Zkoumání chybných asercí | ||
------------------------ | ||
Když aserce selže, Tester vypíše, v čem je chyba. Pokud porovnáváme složitější struktury, Tester vytvoří dumpy porovnávaných hodnot a uloží je do adresáře `output`. Například při selhání smyšleného testu `Arrays.recursive.phpt` budou dumpy uloženy následovně: | ||
|
||
``` | ||
app/ | ||
└── tests/ | ||
├── output/ | ||
│ ├── Arrays.recursive.actual # aktuální hodnota | ||
│ └── Arrays.recursive.expected # očekávaná hodnota | ||
│ | ||
└── Arrays.recursive.phpt # selhávající test | ||
``` | ||
|
||
Název adresáře můžeme změnit přes `Tester\Dumper::$dumpDir`. |
Oops, something went wrong.