Skip to content

Commit cdf4c37

Browse files
committed
added docs
1 parent feb9f58 commit cdf4c37

24 files changed

+3468
-0
lines changed

.gitattributes

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
.github export-ignore
44
ncs.* export-ignore
55
phpstan.neon export-ignore
6+
docs/ export-ignore
67
tests/ export-ignore
78

89
*.sh eol=lf

docs/cs/@home.texy

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{{composer: nette/tester}}
2+
{{maintitle: Nette Tester – pohodové testování v PHP}}
3+
{{description: Nette Tester je jednoduchý a přitom velmi šikovný nástroj na testování PHP kódu.}}

docs/cs/@left-menu.texy

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
- [Začínáme s Nette Tester |guide]
2+
- [Psaní testů |writing-tests]
3+
- [Spouštění testů |running-tests]
4+
5+
- [Aserce |assertions]
6+
- [Anotace testů |test-annotations]
7+
- [TestCase]
8+
- [Pomocné třídy |helpers]
9+
10+
- [Průběžné testování s Travis |testing-with-travis]

docs/cs/@menu.texy

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
- [Úvod |@home]
2+
- [Dokumentace |guide]
3+
- "GitHub .[link-external]":https://github.com/nette/tester

docs/cs/assertions.texy

Lines changed: 280 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,280 @@
1+
Aserce
2+
******
3+
4+
.[perex]
5+
Aserce se používají k potvrzení, že skutečná hodnota odpovídá očekávané hodnotě. Jde o metody třídy `Tester\Assert`.
6+
7+
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á.
8+
9+
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.
10+
11+
Příklady předpokládají vytvořený alias:
12+
13+
```php
14+
use Tester\Assert;
15+
```
16+
17+
18+
Assert::same($expected, $actual, string $description = null) .[method]
19+
----------------------------------------------------------------------
20+
`$expected` musí být totožný s `$actual`. To samé jako PHP operátor `===`.
21+
22+
23+
Assert::notSame($expected, $actual, string $description = null) .[method]
24+
-------------------------------------------------------------------------
25+
Opak `Assert::same()`, tedy to samé jako PHP operátor `!==`.
26+
27+
28+
Assert::equal($expected, $actual, string $description = null) .[method]
29+
-----------------------------------------------------------------------
30+
`$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.
31+
32+
Následující případy jsou shodné z pohledu `equal()`, ale nikoliv `same()`:
33+
34+
```php
35+
Assert::equal(0.3, 0.1 + 0.2);
36+
Assert::equal($obj, clone $obj);
37+
Assert::equal(
38+
['first' => 11, 'second' => 22],
39+
['second' => 22, 'first' => 11]
40+
);
41+
```
42+
43+
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]`.
44+
45+
Dále lze v `$expected` použít tzv. [#očekávání].
46+
47+
48+
Assert::notEqual($expected, $actual, string $description = null) .[method]
49+
--------------------------------------------------------------------------
50+
Opak `Assert::equal()`.
51+
52+
53+
Assert::contains($needle, string|array $actual, string $description = null) .[method]
54+
-------------------------------------------------------------------------------------
55+
Pokud je `$actual` řetězec, musí obsahovat podřetězec `$needle`. Pokud je pole, musí obsahovat prvek `$needle` (porovnává se striktně).
56+
57+
58+
Assert::notContains($needle, string|array $actual, string $description = null) .[method]
59+
----------------------------------------------------------------------------------------
60+
Opak `Assert::contains()`.
61+
62+
63+
Assert::hasKey(string|int $needle, array $actual, string $description = null) .[method]{data-version:2.4}
64+
---------------------------------------------------------------------------------------------------------
65+
`$actual` musí být pole a musí obsahovat klíč `$needle`.
66+
67+
68+
Assert::notHasKey(string|int $needle, array $actual, string $description = null) .[method]{data-version:2.4}
69+
------------------------------------------------------------------------------------------------------------
70+
`$actual` musí být pole a nesmí obsahovat klíč `$needle`.
71+
72+
73+
Assert::true($value, string $description = null) .[method]
74+
----------------------------------------------------------
75+
`$value` musí být `true`, tedy `$value === true`.
76+
77+
78+
Assert::truthy($value, string $description = null) .[method]
79+
------------------------------------------------------------
80+
`$value` musí být pravdivý, tedy splní podmínku `if ($value) ...`.
81+
82+
83+
Assert::false($value, string $description = null) .[method]
84+
-----------------------------------------------------------
85+
`$value` musí být `false`, tedy `$value === false`.
86+
87+
88+
Assert::falsey($value, string $description = null) .[method]
89+
------------------------------------------------------------
90+
`$value` musí být nepravdivý, tedy splní podmínku `if (!$value) ...`.
91+
92+
93+
Assert::null($value, string $description = null) .[method]
94+
----------------------------------------------------------
95+
`$value` musí být `null`, tedy `$value === null`.
96+
97+
98+
Assert::notNull($value, string $description = null) .[method]
99+
-------------------------------------------------------------
100+
`$value` nesmí být `null`, tedy `$value !== null`.
101+
102+
103+
Assert::nan($value, string $description = null) .[method]
104+
---------------------------------------------------------
105+
`$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ě.
106+
107+
108+
Assert::count($count, Countable|array $value, string $description = null) .[method]
109+
-----------------------------------------------------------------------------------
110+
Počet prvků ve `$value` musí být `$count`. Tedy to samé jako `count($value) === $count`.
111+
112+
113+
Assert::type(string|object $type, $value, string $description = null) .[method]
114+
-------------------------------------------------------------------------------
115+
`$value` musí být daného typu. Jako `$type` můžeme použít řetězec:
116+
- `array`
117+
- `list` - pole indexované podle vzestupné řady numerických klíčů od nuly
118+
- `bool`
119+
- `callable`
120+
- `float`
121+
- `int`
122+
- `null`
123+
- `object`
124+
- `resource`
125+
- `scalar`
126+
- `string`
127+
- název třídy nebo přímo objekt, potom musí být `$value instanceof $type`
128+
129+
130+
Assert::exception(callable $callable, string $class, string $message = null, $code = null) .[method]
131+
----------------------------------------------------------------------------------------------------
132+
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.
133+
134+
Následující test selže, protože neodpovídá zpráva výjimky:
135+
136+
```php
137+
Assert::exception(function () {
138+
throw new App\InvalidValueException('Zero value');
139+
}, App\InvalidValueException::class, 'Value is to low');
140+
```
141+
142+
`Assert::exception()` vrací vyhozenou výjimku, lze tak otestovat i výjimku zahnízděnou.
143+
144+
```php
145+
$e = Assert::exception(function () {
146+
throw new MyException('Something is wrong', 0, new RuntimeException);
147+
}, MyException::class, 'Something is wrong');
148+
149+
Assert::type(RuntimeException::class, $e->getPrevious());
150+
```
151+
152+
153+
Assert::error(string $callable, int|string|array $type, string $message = null) .[method]
154+
-----------------------------------------------------------------------------------------
155+
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:
156+
157+
```php
158+
Assert::error(function () {
159+
$i++;
160+
}, E_NOTICE, 'Undefined variable: i');
161+
```
162+
163+
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:
164+
165+
```php
166+
Assert::error(function () {
167+
$a++;
168+
$b++;
169+
}, [
170+
[E_NOTICE, 'Undefined variable: a'],
171+
[E_NOTICE, 'Undefined variable: b'],
172+
]);
173+
```
174+
175+
.[note]
176+
Pokud jako `$type` uvedete název třídy, chová se stejně jako `Assert::exception()`.
177+
178+
179+
Assert::noError(callable $callable) .[method]
180+
---------------------------------------------
181+
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.
182+
183+
184+
Assert::match(string $pattern, $actual, string $description = null) .[method]
185+
-----------------------------------------------------------------------------
186+
`$actual` musí vyhovět vzoru `$pattern`. Můžeme použít dvě varianty vzorů: regulární výrazy nebo zástupné znaky.
187+
188+
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:
189+
190+
```php
191+
Assert::match('#^[0-9a-f]$#i', $var);
192+
```
193+
194+
Druhá varianta je podobná běžnému porovnání řetězců, ale v `$pattern` můžeme použít různé zástupné znaky:
195+
196+
- `%a%` jeden nebo více znaků, kromě znaků konce řádku
197+
- `%a?%` žádný nebo více znaků, kromě znaků konce řádku
198+
- `%A%` jeden nebo více znaků, včetně znaků konce řádku
199+
- `%A?%` žádný nebo více znaků, včetně znaků konce řádku
200+
- `%s%` jeden nebo více bílých znaků, kromě znaků konce řádku
201+
- `%s?%` žádný nebo více bílých znaků, kromě znaků konce řádku
202+
- `%S%` jeden nebo více znaků, kromě bílých znaků
203+
- `%S?%` žádný nebo více znaků, kromě bílých znaků
204+
- `%c%` jakýkoli jeden znak, kromě znaku konce řádku
205+
- `%d%` jedna nebo více číslic
206+
- `%d?%` žádná nebo více číslic
207+
- `%i%` znaménková celočíselná hodnota
208+
- `%f%` číslo s desetinnou čárkou
209+
- `%h%` jedna nebo více hexadecimálních číslic
210+
- `%w%` jeden nebo více alfanumerických znaků
211+
- `%%` znak %
212+
213+
Příklady:
214+
215+
```php
216+
# Opět test na hexadecimální číslo
217+
Assert::match('%h%', $var);
218+
219+
# Zobecnění cesty k souboru a čísla řádky
220+
Assert::match('Error in file %a% on line %i%', $errorMessage);
221+
```
222+
223+
224+
Assert::matchFile(string $file, $actual, string $description = null) .[method]
225+
------------------------------------------------------------------------------
226+
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ý.
227+
228+
229+
Assert::fail(string $message, $actual = null, $expected = null) .[method]
230+
-------------------------------------------------------------------------
231+
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.
232+
233+
234+
Očekávání
235+
---------
236+
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`.
237+
238+
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.
239+
240+
```php
241+
use Tester\Expect;
242+
243+
Assert::equal([
244+
'id' => Expect::type('int'), # očekáváme celé číslo
245+
'username' => 'milo',
246+
'password' => Expect::match('%h%'), # očekáváme řetězec vyhovující vzoru
247+
'created_at' => Expect::type(DateTime::class), # očekáváme instanci třídy
248+
], User::create(123, 'milo', 'RandomPaSsWoRd'));
249+
```
250+
251+
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:
252+
253+
```php
254+
Expect::type(MyIterator::class)->andCount(5); # očekáváme MyIterator a počet prvků 5
255+
```
256+
257+
Anebo můžeme psát vlastní handlery asercí.
258+
259+
```php
260+
Expect::that(function ($value) {
261+
# vrátíme false, pokud očekávání selže
262+
});
263+
```
264+
265+
266+
Zkoumání chybných asercí
267+
------------------------
268+
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ě:
269+
270+
```
271+
app/
272+
└── tests/
273+
├── output/
274+
│ ├── Arrays.recursive.actual # aktuální hodnota
275+
│ └── Arrays.recursive.expected # očekávaná hodnota
276+
277+
└── Arrays.recursive.phpt # selhávající test
278+
```
279+
280+
Název adresáře můžeme změnit přes `Tester\Dumper::$dumpDir`.

0 commit comments

Comments
 (0)