Nette Documentation Preview

syntax
Asercja
*******

.[perex]
Asercje są używane do potwierdzenia, że rzeczywista wartość pasuje do wartości oczekiwanej. Są to metody klasy `Tester\Assert`.

Wybierz najbardziej odpowiednie twierdzenia. Jest to lepsze `Assert::same($a, $b)` niż `Assert::true($a === $b)`, ponieważ wyświetli sensowny komunikat o błędzie, gdy się nie powiedzie. W tym drugim przypadku tylko `false should be true`, który nie mówi nam nic o zawartości zmiennych `$a` i `$b`.

Również większość asercji może mieć opcjonalną etykietę w parametrze `$description`, która zostanie wyświetlona w komunikacie o błędzie, jeśli oczekiwanie nie powiedzie się.

W przykładach założono, że alias został utworzony:

```php
use Tester\Assert;
```


Assert::same($expected, $actual, string $description=null) .[method]
--------------------------------------------------------------------
`$expected` musi być identyczny z `$actual`. Identyczny jak operator PHP `===`.


Assert::notSame($expected, $actual, string $description=null) .[method]
-----------------------------------------------------------------------
Przeciwieństwo `Assert::same()`, czyli to samo co operator PHP `!==`.


Assert::equal($expected, $actual, string $description=null, bool $matchOrder=false, bool $matchIdentity=false) .[method]
------------------------------------------------------------------------------------------------------------------------
`$expected` musi być taka sama jak `$actual`. W przeciwieństwie do `Assert::same()`, tożsamość obiektu, kolejność par kluczy => wartości w polach i marginalnie różne liczby dziesiętne są ignorowane, co można zmienić poprzez ustawienie `$matchIdentity` i `$matchOrder`.

Poniższe przypadki są identyczne z perspektywy `equal()`, ale nie `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],
);
```

Jednakże, uważaj, pole `[1, 2]` a `[2, 1]` nie są takie same, ponieważ tylko kolejność wartości jest inna, a nie pary klucz => wartość. Pole `[1, 2]` można również zapisać jako `[0 => 1, 1 => 2]` i dlatego będą uważane za takie same `[1 => 2, 0 => 1]`.

Ponadto w `$expected` można wykorzystać tzw. [oczekiwania |#Expectations].


Assert::notEqual($expected, $actual, string $description=null) .[method]
------------------------------------------------------------------------
Przeciwieństwo `Assert::equal()`.


Assert::contains($needle, string|array $actual, string $description=null) .[method]
-----------------------------------------------------------------------------------
Jeśli `$actual` jest ciągiem, musi zawierać podłańcuch `$needle`. Jeśli jest to tablica, musi zawierać element `$needle` (dopasowany ściśle).


Assert::notContains($needle, string|array $actual, string $description=null) .[method]
--------------------------------------------------------------------------------------
Przeciwieństwo `Assert::contains()`.


Assert::hasKey(string|int $needle, array $actual, string $description=null) .[method]{data-version:2.4}
-------------------------------------------------------------------------------------------------------
`$actual` musi być tablicą i musi zawierać klucz `$needle`.


Assert::notHasKey(string|int $needle, array $actual, string $description=null) .[method]{data-version:2.4}
----------------------------------------------------------------------------------------------------------
`$actual` musi być tablicą i nie może zawierać klucza `$needle`.


Assert::true($value, string $description=null) .[method]
--------------------------------------------------------
`$value` musi być `true`, czyli `$value === true`.


Assert::truthy($value, string $description=null) .[method]
----------------------------------------------------------
`$value` musi być prawdziwa, czyli spełnia warunek `if ($value) ...`.


Assert::false($value, string $description=null) .[method]
---------------------------------------------------------
`$value` musi być `false`, czyli `$value === false`.


Assert::falsey($value, string $description=null) .[method]
----------------------------------------------------------
`$value` musi być fałszywy, czyli spełnia warunek `if (!$value) ...`.


Assert::null($value, string $description=null) .[method]
--------------------------------------------------------
`$value` musi być `null`, czyli `$value === null`.


Assert::notNull($value, string $description=null) .[method]
-----------------------------------------------------------
`$value` nie może być `null`, czyli `$value !== null`.


Assert::nan($value, string $description=null) .[method]
-------------------------------------------------------
`$value` musi być "Not a Number". Do testowania wartości NAN używaj wyłącznie `Assert::nan()` Wartość NAN jest bardzo specyficzna i asercje `Assert::same()` lub `Assert::equal()` mogą działać nieoczekiwanie.


Assert::count($count, Countable|array $value, string $description=null) .[method]
---------------------------------------------------------------------------------
Liczba elementów w `$value` musi być `$count`. Zatem taka sama jak `count($value) === $count`.


Assert::type(string|object $type, $value, string $description=null) .[method]
-----------------------------------------------------------------------------
`$value` musi być danego typu. Jako `$type` możemy użyć ciągu znaków:
- `array`
- `list` - tablica indeksowana rosnącym szeregiem kluczy numerycznych od zera
- `bool`
- `callable`
- `float`
- `int`
- `null`
- `object`
- `resource`
- `scalar`
- `string`
- nazwa klasy lub samego obiektu, to musi być `$value instanceof $type`


Assert::exception(callable $callable, string $class, string $message=null, $code=null) .[method]
------------------------------------------------------------------------------------------------
Po wywołaniu `$callable` musi zostać rzucony wyjątek klasowy `$class` Jeśli podamy `$message`, komunikat wyjątku musi [pasować do wzorca |#Assert-match], a jeśli podamy `$code`, kody muszą być ściśle [dopasowane |#Assert-match].

Poniższy test kończy się niepowodzeniem, ponieważ komunikat wyjątku nie pasuje:

```php
Assert::exception(
	fn() => throw new App\InvalidValueException('Zero value'),
	App\InvalidValueException::class,
	'Value is to low',
);
```

`Assert::exception()` zwraca rzucony wyjątek, więc można przetestować zagnieżdżony wyjątek.

```php
$e = Assert::exception(
	fn() => 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]
---------------------------------------------------------------------------------------
Sprawdza, czy funkcja `$callable` wygenerowała oczekiwane błędy (tj. Ostrzeżenia, powiadomienia itp.). Jako `$type` podajemy jedną ze stałych `E_...`, czyli np. `E_WARNING`. A jeśli określimy `$message`, to komunikat o błędzie musi [pasować do wzorca |#Assert-match]. Na przykład:

```php
Assert::error(
	fn() => $i++,
	E_NOTICE,
	'Undefined variable: i',
);
```

Jeśli callback generuje wiele błędów, musimy oczekiwać ich wszystkich w dokładnej kolejności. W tym przypadku przekazujemy pole `$type`:

```php
Assert::error(function () {
	$a++;
	$b++;
}, [
	[E_NOTICE, 'Undefined variable: a'],
	[E_NOTICE, 'Undefined variable: b'],
]);
```

.[note]
Jeśli określisz nazwę klasy jako `$type`, zachowuje się ona tak samo jak `Assert::exception()`.


Assert::noError(callable $callable) .[method]
---------------------------------------------
Sprawdza, czy funkcja `$callable` nie wygenerowała żadnych ostrzeżeń, błędów lub wyjątków. Jest to przydatne do testowania fragmentów kodu, w których nie ma innej asercji.


Assert::match(string $pattern, $actual, string $description=null) .[method]
---------------------------------------------------------------------------
`$actual` musi pasować do wzorca `$pattern`. Możemy użyć dwóch wariantów wzorców: wyrażeń regularnych lub symboli wieloznacznych.

Jeśli przekażemy wyrażenie regularne jako `$pattern`, musimy użyć `~` nebo `#` do jego delimitacji, inne delimitery nie są obsługiwane. Na przykład test, w którym `$var` musi zawierać tylko cyfry szesnastkowe:

```php
Assert::match('#^[0-9a-f]$#i', $var);
```

Druga opcja jest podobna do dopasowywania ciągów regularnych, ale możemy używać różnych znaków wieloznacznych w `$pattern`:

- `%a%` jeden lub więcej znaków, z wyjątkiem znaków końca linii
- `%a?%` żaden lub więcej znaków, z wyjątkiem znaków końca linii
- `%A%` jeden lub więcej znaków, w tym znaki końca linii
- `%A?%` żaden lub więcej znaków, w tym znaki końca linii
- `%s%` jeden lub więcej białych znaków, z wyłączeniem znaków końca linii
- `%s?%` żaden lub więcej białych znaków, z wyjątkiem znaków końca linii
- `%S%` jeden lub więcej znaków, z wyłączeniem białych znaków
- `%S?%` żaden lub więcej znaków, z wyjątkiem białych znaków
- `%c%` dowolny znak, z wyjątkiem znaków przerwy w linii
- `%d%` jedna lub więcej cyfr
- `%d?%` brak lub więcej cyfr
- `%i%` podpisana wartość całkowita
- `%f%` liczba z kropką dziesiętną
- `%h%` jedna lub więcej cyfr szesnastkowych
- `%w%` jeden lub więcej znaków alfanumerycznych
- `%%` znak %

Przykłady:

```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]
----------------------------------------------------------------------------
Asercja jest identyczna jak [Assert::match() |#Assert-match], ale wzór jest odczytywany z `$file`. Jest to przydatne do testowania bardzo długich łańcuchów. Plik testowy pozostaje przezroczysty.


Assert::fail(string $message, $actual=null, $expected=null) .[method]
---------------------------------------------------------------------
To twierdzenie zawsze się nie sprawdza. Czasami po prostu się przydaje. Opcjonalnie możemy dołączyć wartość oczekiwaną i rzeczywistą.


Oczekiwania .[#toc-expectations]
--------------------------------
Gdy chcemy porównywać bardziej złożone struktury z elementami niestałymi, powyższe twierdzenia mogą okazać się niewystarczające. Na przykład testujemy metodę, która tworzy nowego użytkownika i zwraca jego atrybuty jako tablicę. Nie znamy wartości hashowej hasła, ale wiemy, że musi to być ciąg szesnastkowy. A o następnym elemencie wiemy tylko tyle, że musi to być obiekt `DateTime`.

W takich sytuacjach możemy użyć `Tester\Expect` wewnątrz parametru `$expected` metod `Assert::equal()` i `Assert::notEqual()`, za pomocą których możemy w prosty sposób opisać strukturę.

```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'));
```

Za pomocą `Expect` możemy wykonać prawie takie same asercje jak za pomocą `Assert`. Tym samym dostępne są dla nas metody `Expect::same()`, `Expect::match()`, `Expect::count()`, itd. Co więcej, możemy je konkatenować:

```php
Expect::type(MyIterator::class)->andCount(5);  # očekáváme MyIterator a počet prvků 5
```

Możemy też napisać własne assertion handlers.

```php
Expect::that(function ($value) {
	# vrátíme false, pokud očekávání selže
});
```


Badanie błędnych twierdzeń .[#toc-failed-assertions-investigation]
------------------------------------------------------------------
Kiedy asercja się nie powiedzie, Tester wymienia, co to za błąd. Przy porównywaniu bardziej złożonych struktur Tester tworzy atrapy porównywanych wartości i przechowuje je w katalogu `output`. Na przykład, jeśli test manekinów `Arrays.recursive.phpt` nie powiedzie się, manekiny zostaną zapisane w następujący sposób:

```
app/
└── tests/
	├── output/
	│   ├── Arrays.recursive.actual    # aktuální hodnota
	│   └── Arrays.recursive.expected  # očekávaná hodnota
	│
	└── Arrays.recursive.phpt          # selhávající test
```

Nazwę katalogu możemy zmienić poprzez stronę `Tester\Dumper::$dumpDir`.

Asercja

Asercje są używane do potwierdzenia, że rzeczywista wartość pasuje do wartości oczekiwanej. Są to metody klasy Tester\Assert.

Wybierz najbardziej odpowiednie twierdzenia. Jest to lepsze Assert::same($a, $b) niż Assert::true($a === $b), ponieważ wyświetli sensowny komunikat o błędzie, gdy się nie powiedzie. W tym drugim przypadku tylko false should be true, który nie mówi nam nic o zawartości zmiennych $a i $b.

Również większość asercji może mieć opcjonalną etykietę w parametrze $description, która zostanie wyświetlona w komunikacie o błędzie, jeśli oczekiwanie nie powiedzie się.

W przykładach założono, że alias został utworzony:

use Tester\Assert;

Assert::same($expected, $actual, string $description=null)

$expected musi być identyczny z $actual. Identyczny jak operator PHP ===.

Assert::notSame($expected, $actual, string $description=null)

Przeciwieństwo Assert::same(), czyli to samo co operator PHP !==.

Assert::equal($expected, $actual, string $description=null, bool $matchOrder=false, bool $matchIdentity=false)

$expected musi być taka sama jak $actual. W przeciwieństwie do Assert::same(), tożsamość obiektu, kolejność par kluczy ⇒ wartości w polach i marginalnie różne liczby dziesiętne są ignorowane, co można zmienić poprzez ustawienie $matchIdentity i $matchOrder.

Poniższe przypadki są identyczne z perspektywy equal(), ale nie same():

Assert::equal(0.3, 0.1 + 0.2);
Assert::equal($obj, clone $obj);
Assert::equal(
	['first' => 11, 'second' => 22],
	['second' => 22, 'first' => 11],
);

Jednakże, uważaj, pole [1, 2] a [2, 1] nie są takie same, ponieważ tylko kolejność wartości jest inna, a nie pary klucz ⇒ wartość. Pole [1, 2] można również zapisać jako [0 => 1, 1 => 2] i dlatego będą uważane za takie same [1 => 2, 0 => 1].

Ponadto w $expected można wykorzystać tzw. oczekiwania.

Assert::notEqual($expected, $actual, string $description=null)

Przeciwieństwo Assert::equal().

Assert::contains($needle, string|array $actual, string $description=null)

Jeśli $actual jest ciągiem, musi zawierać podłańcuch $needle. Jeśli jest to tablica, musi zawierać element $needle (dopasowany ściśle).

Assert::notContains($needle, string|array $actual, string $description=null)

Przeciwieństwo Assert::contains().

Assert::hasKey(string|int $needle, array $actual, string $description=null)

$actual musi być tablicą i musi zawierać klucz $needle.

Assert::notHasKey(string|int $needle, array $actual, string $description=null)

$actual musi być tablicą i nie może zawierać klucza $needle.

Assert::true($value, string $description=null)

$value musi być true, czyli $value === true.

Assert::truthy($value, string $description=null)

$value musi być prawdziwa, czyli spełnia warunek if ($value) ....

Assert::false($value, string $description=null)

$value musi być false, czyli $value === false.

Assert::falsey($value, string $description=null)

$value musi być fałszywy, czyli spełnia warunek if (!$value) ....

Assert::null($value, string $description=null)

$value musi być null, czyli $value === null.

Assert::notNull($value, string $description=null)

$value nie może być null, czyli $value !== null.

Assert::nan($value, string $description=null)

$value musi być „Not a Number“. Do testowania wartości NAN używaj wyłącznie Assert::nan() Wartość NAN jest bardzo specyficzna i asercje Assert::same() lub Assert::equal() mogą działać nieoczekiwanie.

Assert::count($count, Countable|array $value, string $description=null)

Liczba elementów w $value musi być $count. Zatem taka sama jak count($value) === $count.

Assert::type(string|object $type, $value, string $description=null)

$value musi być danego typu. Jako $type możemy użyć ciągu znaków:

  • array
  • list – tablica indeksowana rosnącym szeregiem kluczy numerycznych od zera
  • bool
  • callable
  • float
  • int
  • null
  • object
  • resource
  • scalar
  • string
  • nazwa klasy lub samego obiektu, to musi być $value instanceof $type

Assert::exception(callable $callable, string $class, string $message=null, $code=null)

Po wywołaniu $callable musi zostać rzucony wyjątek klasowy $class Jeśli podamy $message, komunikat wyjątku musi pasować do wzorca, a jeśli podamy $code, kody muszą być ściśle dopasowane.

Poniższy test kończy się niepowodzeniem, ponieważ komunikat wyjątku nie pasuje:

Assert::exception(
	fn() => throw new App\InvalidValueException('Zero value'),
	App\InvalidValueException::class,
	'Value is to low',
);

Assert::exception() zwraca rzucony wyjątek, więc można przetestować zagnieżdżony wyjątek.

$e = Assert::exception(
	fn() => 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)

Sprawdza, czy funkcja $callable wygenerowała oczekiwane błędy (tj. Ostrzeżenia, powiadomienia itp.). Jako $type podajemy jedną ze stałych E_..., czyli np. E_WARNING. A jeśli określimy $message, to komunikat o błędzie musi pasować do wzorca. Na przykład:

Assert::error(
	fn() => $i++,
	E_NOTICE,
	'Undefined variable: i',
);

Jeśli callback generuje wiele błędów, musimy oczekiwać ich wszystkich w dokładnej kolejności. W tym przypadku przekazujemy pole $type:

Assert::error(function () {
	$a++;
	$b++;
}, [
	[E_NOTICE, 'Undefined variable: a'],
	[E_NOTICE, 'Undefined variable: b'],
]);

Jeśli określisz nazwę klasy jako $type, zachowuje się ona tak samo jak Assert::exception().

Assert::noError(callable $callable)

Sprawdza, czy funkcja $callable nie wygenerowała żadnych ostrzeżeń, błędów lub wyjątków. Jest to przydatne do testowania fragmentów kodu, w których nie ma innej asercji.

Assert::match(string $pattern, $actual, string $description=null)

$actual musi pasować do wzorca $pattern. Możemy użyć dwóch wariantów wzorców: wyrażeń regularnych lub symboli wieloznacznych.

Jeśli przekażemy wyrażenie regularne jako $pattern, musimy użyć ~ nebo # do jego delimitacji, inne delimitery nie są obsługiwane. Na przykład test, w którym $var musi zawierać tylko cyfry szesnastkowe:

Assert::match('#^[0-9a-f]$#i', $var);

Druga opcja jest podobna do dopasowywania ciągów regularnych, ale możemy używać różnych znaków wieloznacznych w $pattern:

  • %a% jeden lub więcej znaków, z wyjątkiem znaków końca linii
  • %a?% żaden lub więcej znaków, z wyjątkiem znaków końca linii
  • %A% jeden lub więcej znaków, w tym znaki końca linii
  • %A?% żaden lub więcej znaków, w tym znaki końca linii
  • %s% jeden lub więcej białych znaków, z wyłączeniem znaków końca linii
  • %s?% żaden lub więcej białych znaków, z wyjątkiem znaków końca linii
  • %S% jeden lub więcej znaków, z wyłączeniem białych znaków
  • %S?% żaden lub więcej znaków, z wyjątkiem białych znaków
  • %c% dowolny znak, z wyjątkiem znaków przerwy w linii
  • %d% jedna lub więcej cyfr
  • %d?% brak lub więcej cyfr
  • %i% podpisana wartość całkowita
  • %f% liczba z kropką dziesiętną
  • %h% jedna lub więcej cyfr szesnastkowych
  • %w% jeden lub więcej znaków alfanumerycznych
  • %% znak %

Przykłady:

# 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)

Asercja jest identyczna jak Assert::match(), ale wzór jest odczytywany z $file. Jest to przydatne do testowania bardzo długich łańcuchów. Plik testowy pozostaje przezroczysty.

Assert::fail(string $message, $actual=null, $expected=null)

To twierdzenie zawsze się nie sprawdza. Czasami po prostu się przydaje. Opcjonalnie możemy dołączyć wartość oczekiwaną i rzeczywistą.

Oczekiwania

Gdy chcemy porównywać bardziej złożone struktury z elementami niestałymi, powyższe twierdzenia mogą okazać się niewystarczające. Na przykład testujemy metodę, która tworzy nowego użytkownika i zwraca jego atrybuty jako tablicę. Nie znamy wartości hashowej hasła, ale wiemy, że musi to być ciąg szesnastkowy. A o następnym elemencie wiemy tylko tyle, że musi to być obiekt DateTime.

W takich sytuacjach możemy użyć Tester\Expect wewnątrz parametru $expected metod Assert::equal() i Assert::notEqual(), za pomocą których możemy w prosty sposób opisać strukturę.

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'));

Za pomocą Expect możemy wykonać prawie takie same asercje jak za pomocą Assert. Tym samym dostępne są dla nas metody Expect::same(), Expect::match(), Expect::count(), itd. Co więcej, możemy je konkatenować:

Expect::type(MyIterator::class)->andCount(5);  # očekáváme MyIterator a počet prvků 5

Możemy też napisać własne assertion handlers.

Expect::that(function ($value) {
	# vrátíme false, pokud očekávání selže
});

Badanie błędnych twierdzeń

Kiedy asercja się nie powiedzie, Tester wymienia, co to za błąd. Przy porównywaniu bardziej złożonych struktur Tester tworzy atrapy porównywanych wartości i przechowuje je w katalogu output. Na przykład, jeśli test manekinów Arrays.recursive.phpt nie powiedzie się, manekiny zostaną zapisane w następujący sposób:

app/
└── tests/
	├── output/
	│   ├── Arrays.recursive.actual    # aktuální hodnota
	│   └── Arrays.recursive.expected  # očekávaná hodnota
	│
	└── Arrays.recursive.phpt          # selhávající test

Nazwę katalogu możemy zmienić poprzez stronę Tester\Dumper::$dumpDir.