Nette Documentation Preview

syntax
アサーション
******

.[perex]
アサーションは、実際の値が期待値に対応することを確認するために使用されます。これらは `Tester\Assert` クラスのメソッドです。

最も適切なアサーションを選択してください。`Assert::same($a, $b)` は `Assert::true($a === $b)` よりも優れています。なぜなら、失敗した場合に意味のあるエラーメッセージが表示されるからです。2 番目のケースでは、`false should be true` のみが表示され、変数 `$a` と `$b` の内容については何もわかりません。

ほとんどのアサーションには、オプションの `$description` パラメータを含めることもできます。これは、期待が失敗した場合にエラーメッセージに表示されます。

例では、エイリアスが作成されていることを前提としています。

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


Assert::same($expected, $actual, ?string $description=null) .[method]
---------------------------------------------------------------------
`$expected` は `$actual` と同一でなければなりません。PHP 演算子 `===` と同じです。


Assert::notSame($expected, $actual, ?string $description=null) .[method]
------------------------------------------------------------------------
`Assert::same()` の逆。つまり、PHP 演算子 `!==` と同じです。


Assert::equal($expected, $actual, ?string $description=null, bool $matchOrder=false, bool $matchIdentity=false) .[method]
-------------------------------------------------------------------------------------------------------------------------
`$expected` は `$actual` と同じでなければなりません。`Assert::same()` とは異なり、オブジェクトの同一性、配列内のキー => 値ペアの順序、およびわずかに異なる 10 進数は無視されます。これは `$matchIdentity` と `$matchOrder` を設定することで変更できます。

次のケースは `equal()` の観点からは同じですが、`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],
);
```

ただし、注意してください。配列 `[1, 2]` と `[2, 1]` は同じではありません。なぜなら、キー => 値ペアではなく、値の順序のみが異なるからです。配列 `[1, 2]` は `[0 => 1, 1 => 2]` と書くこともでき、したがって `[1 => 2, 0 => 1]` が同じと見なされます。

さらに、`$expected` でいわゆる [#期待値] を使用できます。


Assert::notEqual($expected, $actual, ?string $description=null) .[method]
-------------------------------------------------------------------------
`Assert::equal()` の逆。


Assert::contains($needle, string|array $actual, ?string $description=null) .[method]
------------------------------------------------------------------------------------
`$actual` が文字列の場合、部分文字列 `$needle` を含まなければなりません。配列の場合、要素 `$needle` を含まなければなりません(厳密に比較されます)。


Assert::notContains($needle, string|array $actual, ?string $description=null) .[method]
---------------------------------------------------------------------------------------
`Assert::contains()` の逆。


Assert::hasKey(string|int $needle, array $actual, ?string $description=null) .[method]{data-version:2.4}
--------------------------------------------------------------------------------------------------------
`$actual` は配列でなければならず、キー `$needle` を含まなければなりません。


Assert::notHasKey(string|int $needle, array $actual, ?string $description=null) .[method]{data-version:2.4}
-----------------------------------------------------------------------------------------------------------
`$actual` は配列でなければならず、キー `$needle` を含んではいけません。


Assert::true($value, ?string $description=null) .[method]
---------------------------------------------------------
`$value` は `true` でなければなりません。つまり、`$value === true` です。


Assert::truthy($value, ?string $description=null) .[method]
-----------------------------------------------------------
`$value` は真でなければなりません。つまり、条件 `if ($value) ...` を満たします。


Assert::false($value, ?string $description=null) .[method]
----------------------------------------------------------
`$value` は `false` でなければなりません。つまり、`$value === false` です。


Assert::falsey($value, ?string $description=null) .[method]
-----------------------------------------------------------
`$value` は偽でなければなりません。つまり、条件 `if (!$value) ...` を満たします。


Assert::null($value, ?string $description=null) .[method]
---------------------------------------------------------
`$value` は `null` でなければなりません。つまり、`$value === null` です。


Assert::notNull($value, ?string $description=null) .[method]
------------------------------------------------------------
`$value` は `null` であってはなりません。つまり、`$value !== null` です。


Assert::nan($value, ?string $description=null) .[method]
--------------------------------------------------------
`$value` は Not a Number でなければなりません。NAN 値のテストには、`Assert::nan()` のみを使用してください。NAN 値は非常に特殊であり、アサーション `Assert::same()` または `Assert::equal()` は予期せず動作する可能性があります。


Assert::count($count, Countable|array $value, ?string $description=null) .[method]
----------------------------------------------------------------------------------
`$value` 内の要素の数は `$count` でなければなりません。つまり、`count($value) === $count` と同じです。


Assert::type(string|object $type, $value, ?string $description=null) .[method]
------------------------------------------------------------------------------
`$value` は指定された型でなければなりません。`$type` として文字列を使用できます。
- `array`
- `list` - ゼロから始まる昇順の数値キーでインデックス付けされた配列
- `bool`
- `callable`
- `float`
- `int`
- `null`
- `object`
- `resource`
- `scalar`
- `string`
- クラス名または直接オブジェクト。その場合、`$value instanceof $type` でなければなりません。


Assert::exception(callable $callable, string $class, ?string $message=null, $code=null) .[method]
-------------------------------------------------------------------------------------------------
`$callable` を呼び出すと、クラス `$class` の例外がスローされなければなりません。`$message` を指定した場合、例外メッセージも [パターンに一致 |#Assert::match] しなければならず、`$code` を指定した場合、コードも厳密に一致しなければなりません。

次のテストは、例外メッセージが一致しないため失敗します。

```php
Assert::exception(
	fn() => throw new App\InvalidValueException('ゼロ値'),
	App\InvalidValueException::class,
	'値が低すぎます',
);
```

`Assert::exception()` はスローされた例外を返します。したがって、ネストされた例外もテストできます。

```php
$e = Assert::exception(
	fn() => throw new MyException('何かが間違っています', 0, new RuntimeException),
	MyException::class,
	'何かが間違っています',
);

Assert::type(RuntimeException::class, $e->getPrevious());
```


Assert::error(callable $callable, int|string|array $type, ?string $message=null) .[method]
------------------------------------------------------------------------------------------
関数 `$callable` が期待されるエラー(つまり、警告、通知など)を生成したことを確認します。`$type` として、`E_...` 定数の 1 つ、たとえば `E_WARNING` を指定します。そして、`$message` を指定した場合、エラーメッセージも [パターンに一致 |#Assert::match] しなければなりません。例:

```php
Assert::error(
	fn() => $i++,
	E_NOTICE,
	'未定義の変数: i',
);
```

コールバックが複数のエラーを生成する場合、それらすべてを正確な順序で期待する必要があります。その場合、`$type` に配列を渡します。

```php
Assert::error(function () {
	$a++;
	$b++;
}, [
	[E_NOTICE, '未定義の変数: a'],
	[E_NOTICE, '未定義の変数: b'],
]);
```

.[note]
`$type` としてクラス名を指定した場合、`Assert::exception()` と同じように動作します。


Assert::noError(callable $callable) .[method]
---------------------------------------------
関数 `$callable` が警告、エラー、または例外を生成しなかったことを確認します。他のアサーションがないコード片をテストする場合に役立ちます。


Assert::match(string $pattern, $actual, ?string $description=null) .[method]
----------------------------------------------------------------------------
`$actual` はパターン `$pattern` に一致しなければなりません。2 つのバリアントのパターンを使用できます:正規表現またはワイルドカード。

`$pattern` として正規表現を渡す場合、その区切り文字として `~` または `#` を使用する必要があります。他の区切り文字はサポートされていません。たとえば、$var が 16 進数のみを含む必要がある場合のテスト:

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

2 番目のバリアントは通常の文字列比較に似ていますが、`$pattern` でさまざまなワイルドカードを使用できます。

- `%a%` 1 つ以上の文字、改行文字を除く
- `%a?%` ゼロ個以上の文字、改行文字を除く
- `%A%` 1 つ以上の文字、改行文字を含む
- `%A?%` ゼロ個以上の文字、改行文字を含む
- `%s%` 1 つ以上の空白文字、改行文字を除く
- `%s?%` ゼロ個以上の空白文字、改行文字を除く
- `%S%` 1 つ以上の空白文字以外の文字
- `%S?%` ゼロ個以上の空白文字以外の文字
- `%c%` 任意の 1 文字、改行文字を除く
- `%d%` 1 つ以上の数字
- `%d?%` ゼロ個以上の数字
- `%i%` 符号付き整数値
- `%f%` 浮動小数点数
- `%h%` 1 つ以上の 16 進数
- `%w%` 1 つ以上の英数字
- `%%` % 文字

例:

```php
# 再び 16 進数のテスト
Assert::match('%h%', $var);

# ファイルパスと行番号の一般化
Assert::match('ファイル %a% の %i% 行目でエラー', $errorMessage); // 'Error in file %a% on line %i%' を日本語に
```


Assert::matchFile(string $file, $actual, ?string $description=null) .[method]
-----------------------------------------------------------------------------
アサーションは [#Assert::match()] と同じですが、パターンはファイル `$file` から読み込まれます。これは、非常に長い文字列をテストする場合に役立ちます。テストファイルは明確なままです。


Assert::fail(string $message, $actual=null, $expected=null) .[method]
---------------------------------------------------------------------
このアサーションは常に失敗します。時にはそれが役立ちます。オプションで、期待値と実際の値を指定することもできます。


期待値
---
非定数要素を持つより複雑な構造を比較したい場合、上記のアサーションでは不十分な場合があります。たとえば、新しいユーザーを作成し、その属性を配列として返すメソッドをテストします。パスワードハッシュの値はわかりませんが、それが 16 進文字列でなければならないことはわかっています。そして、別の要素については、それが `DateTime` オブジェクトでなければならないことしかわかりません。

これらの状況では、`Assert::equal()` および `Assert::notEqual()` メソッドの `$expected` パラメータ内で `Tester\Expect` を使用できます。これにより、構造を簡単に記述できます。

```php
use Tester\Expect;

Assert::equal([
	'id' => Expect::type('int'),                   # 整数を期待します
	'username' => 'milo',
	'password' => Expect::match('%h%'),            # パターンに一致する文字列を期待します
	'created_at' => Expect::type(DateTime::class), # クラスのインスタンスを期待します
], User::create(123, 'milo', 'RandomPaSsWoRd'));
```

`Expect` を使用すると、`Assert` とほぼ同じアサーションを実行できます。つまり、メソッド `Expect::same()`、`Expect::match()`、`Expect::count()` などが利用可能です。さらに、それらを連鎖させることができます。

```php
Expect::type(MyIterator::class)->andCount(5);  # MyIterator と要素数 5 を期待します
```

または、独自のアサーションハンドラを作成することもできます。

```php
Expect::that(function ($value) {
	# 期待が失敗した場合に false を返します
});
```


失敗したアサーションの調査
-------------
アサーションが失敗すると、Tester は何が間違っているかを出力します。より複雑な構造を比較する場合、Tester は比較された値のダンプを作成し、それらを `output` ディレクトリに保存します。たとえば、架空のテスト `Arrays.recursive.phpt` が失敗した場合、ダンプは次のように保存されます。

```
app/
└── tests/
	├── output/
	│   ├── Arrays.recursive.actual    # 実際の値
	│   └── Arrays.recursive.expected  # 期待値
	│
	└── Arrays.recursive.phpt          # 失敗したテスト
```

ディレクトリ名は `Tester\Dumper::$dumpDir` を介して変更できます。

アサーション

アサーションは、実際の値が期待値に対応することを確認するために使用されます。これらは Tester\Assert クラスのメソッドです。

最も適切なアサーションを選択してください。Assert::same($a, $b)Assert::true($a === $b) よりも優れています。なぜなら、失敗した場合に意味のあるエラーメッセージが表示されるからです。2 番目のケースでは、false should be true のみが表示され、変数 $a$b の内容については何もわかりません。

ほとんどのアサーションには、オプションの $description パラメータを含めることもできます。これは、期待が失敗した場合にエラーメッセージに表示されます。

例では、エイリアスが作成されていることを前提としています。

use Tester\Assert;

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

$expected$actual と同一でなければなりません。PHP 演算子 === と同じです。

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

Assert::same() の逆。つまり、PHP 演算子 !== と同じです。

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

$expected$actual と同じでなければなりません。Assert::same() とは異なり、オブジェクトの同一性、配列内のキー ⇒ 値ペアの順序、およびわずかに異なる 10 進数は無視されます。これは $matchIdentity$matchOrder を設定することで変更できます。

次のケースは equal() の観点からは同じですが、same() の観点からは同じではありません。

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

ただし、注意してください。配列 [1, 2][2, 1] は同じではありません。なぜなら、キー ⇒ 値ペアではなく、値の順序のみが異なるからです。配列 [1, 2][0 => 1, 1 => 2] と書くこともでき、したがって [1 => 2, 0 => 1] が同じと見なされます。

さらに、$expected でいわゆる 期待値 を使用できます。

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

Assert::equal() の逆。

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

$actual が文字列の場合、部分文字列 $needle を含まなければなりません。配列の場合、要素 $needle を含まなければなりません(厳密に比較されます)。

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

Assert::contains() の逆。

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

$actual は配列でなければならず、キー $needle を含まなければなりません。

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

$actual は配列でなければならず、キー $needle を含んではいけません。

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

$valuetrue でなければなりません。つまり、$value === true です。

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

$value は真でなければなりません。つまり、条件 if ($value) ... を満たします。

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

$valuefalse でなければなりません。つまり、$value === false です。

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

$value は偽でなければなりません。つまり、条件 if (!$value) ... を満たします。

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

$valuenull でなければなりません。つまり、$value === null です。

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

$valuenull であってはなりません。つまり、$value !== null です。

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

$value は Not a Number でなければなりません。NAN 値のテストには、Assert::nan() のみを使用してください。NAN 値は非常に特殊であり、アサーション Assert::same() または Assert::equal() は予期せず動作する可能性があります。

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

$value 内の要素の数は $count でなければなりません。つまり、count($value) === $count と同じです。

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

$value は指定された型でなければなりません。$type として文字列を使用できます。

  • array
  • list – ゼロから始まる昇順の数値キーでインデックス付けされた配列
  • bool
  • callable
  • float
  • int
  • null
  • object
  • resource
  • scalar
  • string
  • クラス名または直接オブジェクト。その場合、$value instanceof $type でなければなりません。

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

$callable を呼び出すと、クラス $class の例外がスローされなければなりません。$message を指定した場合、例外メッセージも パターンに一致 しなければならず、$code を指定した場合、コードも厳密に一致しなければなりません。

次のテストは、例外メッセージが一致しないため失敗します。

Assert::exception(
	fn() => throw new App\InvalidValueException('ゼロ値'),
	App\InvalidValueException::class,
	'値が低すぎます',
);

Assert::exception() はスローされた例外を返します。したがって、ネストされた例外もテストできます。

$e = Assert::exception(
	fn() => throw new MyException('何かが間違っています', 0, new RuntimeException),
	MyException::class,
	'何かが間違っています',
);

Assert::type(RuntimeException::class, $e->getPrevious());

Assert::error(callable $callable, int|string|array $type, ?string $message=null)

関数 $callable が期待されるエラー(つまり、警告、通知など)を生成したことを確認します。$type として、E_... 定数の 1 つ、たとえば E_WARNING を指定します。そして、$message を指定した場合、エラーメッセージも パターンに一致 しなければなりません。例:

Assert::error(
	fn() => $i++,
	E_NOTICE,
	'未定義の変数: i',
);

コールバックが複数のエラーを生成する場合、それらすべてを正確な順序で期待する必要があります。その場合、$type に配列を渡します。

Assert::error(function () {
	$a++;
	$b++;
}, [
	[E_NOTICE, '未定義の変数: a'],
	[E_NOTICE, '未定義の変数: b'],
]);

$type としてクラス名を指定した場合、Assert::exception() と同じように動作します。

Assert::noError(callable $callable)

関数 $callable が警告、エラー、または例外を生成しなかったことを確認します。他のアサーションがないコード片をテストする場合に役立ちます。

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

$actual はパターン $pattern に一致しなければなりません。2 つのバリアントのパターンを使用できます:正規表現またはワイルドカード。

$pattern として正規表現を渡す場合、その区切り文字として ~ または # を使用する必要があります。他の区切り文字はサポートされていません。たとえば、$var が 16 進数のみを含む必要がある場合のテスト:

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

2 番目のバリアントは通常の文字列比較に似ていますが、$pattern でさまざまなワイルドカードを使用できます。

  • %a% 1 つ以上の文字、改行文字を除く
  • %a?% ゼロ個以上の文字、改行文字を除く
  • %A% 1 つ以上の文字、改行文字を含む
  • %A?% ゼロ個以上の文字、改行文字を含む
  • %s% 1 つ以上の空白文字、改行文字を除く
  • %s?% ゼロ個以上の空白文字、改行文字を除く
  • %S% 1 つ以上の空白文字以外の文字
  • %S?% ゼロ個以上の空白文字以外の文字
  • %c% 任意の 1 文字、改行文字を除く
  • %d% 1 つ以上の数字
  • %d?% ゼロ個以上の数字
  • %i% 符号付き整数値
  • %f% 浮動小数点数
  • %h% 1 つ以上の 16 進数
  • %w% 1 つ以上の英数字
  • %% % 文字

例:

# 再び 16 進数のテスト
Assert::match('%h%', $var);

# ファイルパスと行番号の一般化
Assert::match('ファイル %a% の %i% 行目でエラー', $errorMessage); // 'Error in file %a% on line %i%' を日本語に

Assert::matchFile(string $file, $actual, ?string $description=null)

アサーションは Assert::match() と同じですが、パターンはファイル $file から読み込まれます。これは、非常に長い文字列をテストする場合に役立ちます。テストファイルは明確なままです。

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

このアサーションは常に失敗します。時にはそれが役立ちます。オプションで、期待値と実際の値を指定することもできます。

期待値

非定数要素を持つより複雑な構造を比較したい場合、上記のアサーションでは不十分な場合があります。たとえば、新しいユーザーを作成し、その属性を配列として返すメソッドをテストします。パスワードハッシュの値はわかりませんが、それが 16 進文字列でなければならないことはわかっています。そして、別の要素については、それが DateTime オブジェクトでなければならないことしかわかりません。

これらの状況では、Assert::equal() および Assert::notEqual() メソッドの $expected パラメータ内で Tester\Expect を使用できます。これにより、構造を簡単に記述できます。

use Tester\Expect;

Assert::equal([
	'id' => Expect::type('int'),                   # 整数を期待します
	'username' => 'milo',
	'password' => Expect::match('%h%'),            # パターンに一致する文字列を期待します
	'created_at' => Expect::type(DateTime::class), # クラスのインスタンスを期待します
], User::create(123, 'milo', 'RandomPaSsWoRd'));

Expect を使用すると、Assert とほぼ同じアサーションを実行できます。つまり、メソッド Expect::same()Expect::match()Expect::count() などが利用可能です。さらに、それらを連鎖させることができます。

Expect::type(MyIterator::class)->andCount(5);  # MyIterator と要素数 5 を期待します

または、独自のアサーションハンドラを作成することもできます。

Expect::that(function ($value) {
	# 期待が失敗した場合に false を返します
});

失敗したアサーションの調査

アサーションが失敗すると、Tester は何が間違っているかを出力します。より複雑な構造を比較する場合、Tester は比較された値のダンプを作成し、それらを output ディレクトリに保存します。たとえば、架空のテスト Arrays.recursive.phpt が失敗した場合、ダンプは次のように保存されます。

app/
└── tests/
	├── output/
	│   ├── Arrays.recursive.actual    # 実際の値
	│   └── Arrays.recursive.expected  # 期待値
	│
	└── Arrays.recursive.phpt          # 失敗したテスト

ディレクトリ名は Tester\Dumper::$dumpDir を介して変更できます。