PHPUnit の始め方について語りあう PHP TechCafe

PHPers NEWS

こんなテーマの座談会を社内各サービスの代表者間でやってみたい。

先日Twitterで少し話題になっていました。まだ古いPHPを使い続けている現場では役立つかも?

個人的にはリファレンスは滅べばいいのに扱いが難しいし、本当に必要な場面も少ないのでできれば避けたほうがいいと思っていますが、稀に必要になった場合の罠が軽減されるのは嬉しいです。

体系的に学ぶ 安全なWebアプリケーションの作り方(通称:徳丸本)はWebアプリケーション開発者必読・必携だが、分厚いのでまずこういった記事から入るのも良いのでは

カッチリ実装したい人にとっては嬉しい修正なのだが、既存システムに導入するのは極めて勇気が要りそう。PHP界隈でも意見が分かれていそう。
アプリケーションの状況に応じて、動的プロパティの許可/不許可を細かく制御できるのなら、ぜひ導入してほしい。

個人での利用は問題ないが、会社で使っている個人ツールはどうなんだろう

やっぱり内部ではこういう動きしていたんだねっていう実装が垣間見れます。

あまり使ったことが無いツールもありましたが、PhpStorm はやっぱり入っていました。

紹介記事

PHPUnit テストコードの書き方【入門】

テストとは

  • 品質を担保するための工程
  • プログラムが期待通りに動いているかの確認
  • たとえば
    • 正しい挙動をしているか
    • 負荷をかけた時は正常に動くか
    • 部品を合わせた時に正しく動くか

Unit テストとは

  • 単体テスト
  • クラスや関数などの単位で動作を確認するテスト
  • 画面遷移での動作確認が不要

PHPUnit とは

PHPプログラムとして作成可能なユニットテスト

PHPUnit マニュアル

その他のPHP系のユニットテストツール

入門するにあたり押さえておきたい機能

最低限の機能(参考

setUpメソッド

テストコードを実行する際に一番最初に実行されるメソッド。

テスト対象としているクラスのインスタンス化や各テストで利用する共通処理の初期化などに利用。

<?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

値の比較が可能なアサーションメソッド。(型の厳密なチェックも可能)

$this->assertSame('hoge', 'hoge'); // OK $this->assertSame('hoge', 'fuga'); // NG $this->assertSame(0, 0); // OK $this->assertSame(0, false); // NG

assertTrue

Trueが返されることを確認するアサーションメソッド。

assertSame メソッドでも同様のケースが記述できるが、テスト結果がわかりやすくなるというメリットがある

$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

データプロバイダ

テストメソッドへの引数をまとめて記載することができるメソッドを作成することができます。
データプロバイダに指定するメソッドには、アノテーション @dataProvider を指定し、配列や反復が可能な値を返すようにする必要があります。

<?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 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の場合

$ 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() を以下のように書き換えた場合。

/** * @depends testSided */ public function testRoll($dice){ $dice->roll(); $this->assertTrue(1 <= $dice->getNumber() && 0 >= $dice->getNumber()); // 6 だったものを 0 に書き換え }
$ 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 マニュアル

Select a repo