owned this note
owned this note
Published
Linked with GitHub
PHPUnit の始め方について語りあう PHP TechCafe
===================================================
## PHPers NEWS
::: info
[level=0 から始める PHPStan(Larastan) 導入ガイド](https://blog.shin1x1.com/entry/getting-stated-with-phpstan)
:::
::: info
[「一人じゃない」と思えるチームビルディングが鍵 PHPバージョンアップのために欠かせない“精神論”](https://developers.prtimes.jp/2021/08/20/php-versionup-kickoff/)
:::
こんなテーマの座談会を社内各サービスの代表者間でやってみたい。
::: info
[PHP8.0のコードを7.1などの古いバージョンで動くようにトランスパイルするツール](https://twitter.com/sji_ch/status/1436716054940553221)
:::
先日Twitterで少し話題になっていました。まだ古いPHPを使い続けている現場では役立つかも?
::: info
[【PHP8.2?】foreachで安全にリファレンスを使えるようになるかもしれない](https://qiita.com/rana_kualu/items/717439ce16b28ba2edb6)
:::
個人的にはリファレンスは~~滅べばいいのに~~扱いが難しいし、本当に必要な場面も少ないのでできれば避けたほうがいいと思っていますが、稀に必要になった場合の罠が軽減されるのは嬉しいです。
::: info
[駆け出しエンジニアの皆さんに知ってほしい脆弱性のこと。](https://zenn.dev/ad5/articles/5e4e67c9663e4e0d0cb0)
:::
体系的に学ぶ 安全なWebアプリケーションの作り方(通称:徳丸本)はWebアプリケーション開発者必読・必携だが、分厚いのでまずこういった記事から入るのも良いのでは
::: info
[【PHP8.2?】動的プロパティが禁止されるかもしれない](https://qiita.com/rana_kualu/items/53012c8f84e0f92220c1)
:::
カッチリ実装したい人にとっては嬉しい修正なのだが、既存システムに導入するのは極めて勇気が要りそう。PHP界隈でも意見が分かれていそう。
アプリケーションの状況に応じて、動的プロパティの許可/不許可を細かく制御できるのなら、ぜひ導入してほしい。
::: info
[Docker Desktopが有料化へ](https://www.publickey1.jp/blog/21/docker_desktop250100011.html)
:::
個人での利用は問題ないが、会社で使っている個人ツールはどうなんだろう
::: info
[A look at what is coming to Laravel 9](https://laravel-news.com/laravel-9)
:::
やっぱり内部ではこういう動きしていたんだねっていう実装が垣間見れます。
::: info
[10 Best PHP Development Tools](https://dev.to/sahilsachdeva1/10-best-php-development-tools-af)
:::
あまり使ったことが無いツールもありましたが、PhpStorm はやっぱり入っていました。
## 紹介記事
[PHPUnit テストコードの書き方【入門】](https://tech-blog.rakus.co.jp/entry/20210827/phpunit)
### テストとは
* 品質を担保するための工程
* プログラムが期待通りに動いているかの確認
* たとえば...
* 正しい挙動をしているか
* 負荷をかけた時は正常に動くか
* 部品を合わせた時に正しく動くか
### Unit テストとは
* 単体テスト
* クラスや関数などの単位で動作を確認するテスト
* 画面遷移での動作確認が不要
### PHPUnit とは
PHPプログラムとして作成可能なユニットテスト
[PHPUnit マニュアル](https://phpunit.readthedocs.io/ja/latest/#)
[その他のPHP系のユニットテストツール](https://ja.wikipedia.org/wiki/%E3%83%A6%E3%83%8B%E3%83%83%E3%83%88%E3%83%86%E3%82%B9%E3%83%88%E3%83%BB%E3%83%95%E3%83%AC%E3%83%BC%E3%83%A0%E3%83%AF%E3%83%BC%E3%82%AF%E4%B8%80%E8%A6%A7#PHP)
### 入門するにあたり押さえておきたい機能
最低限の機能([参考](https://phpunit.readthedocs.io/ja/latest/writing-tests-for-phpunit.html))
### setUpメソッド
テストコードを実行する際に一番最初に実行されるメソッド。
テスト対象としているクラスのインスタンス化や各テストで利用する共通処理の初期化などに利用。
```php=
<?php declare(strict_types=1);
use PHPUnit\Framework\TestCase;
final class StackTest extends TestCase
{
private $stack;
protected function setUp(): void
{
$this->stack = [];
}
public function testEmpty(): void
{
$this->assertTrue(empty($this->stack));
}
}
```
### アサーション
値を比較、検査して想定通りの値になっているかを確認するためのメソッド。テストコードを記述する上で最も重要。
テストコードはこのアサーションメソッドを各テストメソッド内に記述していきテスト対象のクラスや共通処理が期待通りの動作になっているかを確認するイメージ。
#### assertSame
値の比較が可能なアサーションメソッド。(型の厳密なチェックも可能)
```php=
$this->assertSame('hoge', 'hoge'); // OK
$this->assertSame('hoge', 'fuga'); // NG
$this->assertSame(0, 0); // OK
$this->assertSame(0, false); // NG
```
#### assertTrue
Trueが返されることを確認するアサーションメソッド。
`assertSame` メソッドでも同様のケースが記述できるが、テスト結果がわかりやすくなるというメリットがある
```php=
$flag = FALSE;
$this->assertTrue($flag);
$this->assertSame(TRUE, $flag);
```
```
# assertTrueのメッセージ
Failed asserting that false is true.
# assertSameのメッセージ
Failed asserting that false is identical to true.
```
#### その他の詳細情報
アサーションメソッドの詳細は以前の PHP TechCafe の show note を参照
[PHPerのための「PHPUnit について語り合う」PHP TechCafe](https://hackmd.io/Wgd1DIRbQ0yruglVK5Ch2A)
### データプロバイダ
テストメソッドへの引数をまとめて記載することができるメソッドを作成することができます。
データプロバイダに指定するメソッドには、アノテーション `@dataProvider` を指定し、配列や反復が可能な値を返すようにする必要があります。
```PHP=
<?php
use PHPUnit\Framework\TestCase;
class DataTest extends TestCase
{
/**
* @dataProvider additionProvider
*/
public function testAdd($a, $b, $expected)
{
$this->assertEquals($expected, $a + $b);
}
public function additionProvider()
{
return [
[0, 0, 0],
[0, 1, 1],
[1, 0, 1],
[1, 1, 3]
];
}
}
?>
```
### アノテーション
各テストメソッドに対するメタ情報。
アノテーション自体は PHPDoc にも利用することがあるが、PHPUnit では各テストメソッドの依存関係を定義することなどが可能。
#### @depends
アノテーションが付与されたテストメソッド側で依存しているテストメソッドの戻り値を引数として受け取れる。
記述方法は以下の通り。
```
@depends + "テストメソッド名"
```
以下は PHPUnit の公式マニュアルで紹介されているサンプルコード。
```php=
<?php declare(strict_types=1);
use PHPUnit\Framework\TestCase;
final class StackTest extends TestCase
{
public function testEmpty(): array
{
$stack = [];
$this->assertEmpty($stack);
return $stack;
}
/**
* @depends testEmpty
*/
public function testPush(array $stack): array
{
array_push($stack, 'foo');
$this->assertSame('foo', $stack[count($stack)-1]);
$this->assertNotEmpty($stack);
return $stack;
}
/**
* @depends testPush
*/
public function testPop(array $stack): void
{
$this->assertSame('foo', array_pop($stack));
$this->assertEmpty($stack);
}
}
```
### モック
テスト時に、実際のオブジェクトの動作をシュミレートしてくれる模造品オブジェクトのこと。
依存するオブジェクトが何らかの理由でテスト時に利用できないときに使用する。
たとえば、
* まだ実装されていない
* APIを実行するオブジェクト
* オブジェクトの依存関係をテストで使えない
サンプルコード:
https://phpunit.readthedocs.io/ja/latest/test-doubles.html#test-doubles-mock-objects
### 結果の確認方法
**すべてOKの場合**
```bash=
$ vendor/bin/phpunit Test.php
PHPUnit 7.4.5 by Sebastian Bergmann and contributors.
.... 4 / 4 (100%)
Time: 87 ms, Memory: 4.00 MB
OK (4 tests, 10 assertions)
```
**NGがある場合**
テストコード Test.php の `testRoll()` を以下のように書き換えた場合。
```PHP=
/**
* @depends testSided
*/
public function testRoll($dice){
$dice->roll();
$this->assertTrue(1 <= $dice->getNumber()
&& 0 >= $dice->getNumber()); // 6 だったものを 0 に書き換え
}
```
```bash=
$ vendor/bin/phpunit Test.php
PHPUnit 7.4.5 by Sebastian Bergmann and contributors.
...F 4 / 4 (100%)
Time: 78 ms, Memory: 4.00 MB
There was 1 failure:
1) Test::testRoll
Failed asserting that false is true.
/var/www/html/Test.php:40
FAILURES!
Tests: 4, Assertions: 10, Failures: 1.
```
### サンプルコード
https://github.com/MasaKuuuu/dicegame
### 参考サイト
[PHPUnit マニュアル](https://phpunit.readthedocs.io/ja/latest/index.html)