Skip to content

Commit

Permalink
added docs
Browse files Browse the repository at this point in the history
  • Loading branch information
dg committed Jan 19, 2023
1 parent feb9f58 commit cdf4c37
Show file tree
Hide file tree
Showing 24 changed files with 3,468 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
.github export-ignore
ncs.* export-ignore
phpstan.neon export-ignore
docs/ export-ignore
tests/ export-ignore

*.sh eol=lf
Expand Down
3 changes: 3 additions & 0 deletions docs/cs/@home.texy
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.}}
10 changes: 10 additions & 0 deletions docs/cs/@left-menu.texy
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]
3 changes: 3 additions & 0 deletions docs/cs/@menu.texy
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
280 changes: 280 additions & 0 deletions docs/cs/assertions.texy
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`.
Loading

0 comments on commit cdf4c37

Please sign in to comment.