Skip to content

Instantly share code, notes, and snippets.

@bz0
Last active January 7, 2020 08:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bz0/ab5d8c3957c10e886bd9b8c2e2b02536 to your computer and use it in GitHub Desktop.
Save bz0/ab5d8c3957c10e886bd9b8c2e2b02536 to your computer and use it in GitHub Desktop.
PHPUnitの書き方について

PHPUnit マニュアル:
https://phpunit.readthedocs.io/ja/latest/index.html

  • ユニットテストを書く目的
    • バグの発見と修正、コードのリファクタをしやすくする為
    • テスト対象のソフトウェアのドキュメントとしての役割を果たすこと
  • これらの目的を達成するためには、 ユニットテストがプログラム内のすべてのルートをカバーしていることが理想
  • ひとつのユニットテストがカバーするのは、 通常はひとつの関数やメソッド内の特定のルートだけ
  • PHPUnit は、テストメソッド間の依存性の明示的な宣言をサポート
  • 問題の局所化を手早く行うには、失敗したテストに目を向けやすくしたい
    • あるテストが失敗したときにはそのテストに依存する他のテストの実行をスキップする
  • @depends:テストメソッド間の依存関係を表現できる
    • @dependsで指定したテストメソッドの返り値を引数として取得できる
    • https://qiita.com/kseta/items/f718ac3f964d1c0fea2c
    • 複数の @depends アノテーションを持つテスト
      • @dependsに書かれたテストメソッドの順番で引数にセットされる
  • vendor/bin/phpunit tests/StackTest
    • クラス名で実行すると「Warning: Invocation with class name is deprecated」
    • 「vendor/bin/phpunit tests/StackTest.php」とファイル名を指定して実行する
  • Example 2.6
    • additionProviderメソッドの返り値の配列分testAddメソッドにデータを渡してチェック
    • まとめてテストができるので便利
  • Example 2.7
    • 各データセットに文字列の名前をつけると分かりやすくなる
    • assertSame:2つの変数$expectedと$actual が同じ型・同じ値でない場合にエラーを報告
    • csvで最後の行が読み込めない(最終行に改行を入れておかないとダメ)=Iteratorの問題か?
    • assetSameなので同じ型でないとエラーになる、(int)$expectedと型をキャストする必要あり
  • Example 2.9
    • @dataProviderと@dependsの組み合わせ
    • @dataProviderの方が先に引数を受け取る
    • @dataProviderが複数ある場合、@dependsのデータは同じものが引数になる
  • Example 2.11
    • 例外がスローされたかのチェック:expectException()
    • expectExceptionCode()、 expectExceptionMessage()、 expectExceptionMessageRegExp()メソッドでも例外テスト可能
    • @expectedException LogicExceptionと書くよりも、テストコード内で$this->expectException(\LogicException::class)を呼ぶ方がオススメ
    • アノテーション名をtypoしたときに何も起こらないから
    • https://qiita.com/juve_534/items/b76fd7ec084d28db885c
  • Example 2.13
  • Example 2.15
    • 期待する出力内容をexpectOutputString()メソッドで設定する
    • expectOutputString():PHPの出力バッファリング 機能を使用
    • strictモードでは、出力を発生させるテストは失敗する
  • Example 4.1
    • setUp() および tearDown()はテストメソッドごとに一度ずつ実行される
    • setUp():テスト対象のオブジェクトを生成するような処理に使用
    • tearDown():テスト対象のオブジェクトの後始末などを行う
    • setUpBeforeClass() および tearDownAfterClass()はテストケースクラスの最初のテストメソッドの実行前と最後のテストの実行後にコール
  • Example 4.2
    • tearDown() を実装する必要があるのは setUp() で外部リソース (ファイルやソケットなど) を割り当てた場合のみ
    • setUp()メソッドでmust be compatible with
    • setUp()メソッドの返り値の型(void)を指定する
    • https://qiita.com/stoneBK7/items/fcc898f38ee161b38ef4
    • 実行されるメソッドの流れ:
TemplateMethodsTest::setUpBeforeClass
TemplateMethodsTest::setUp
TemplateMethodsTest::assertPreConditions
TemplateMethodsTest::testOne
TemplateMethodsTest::assertPostConditions
TemplateMethodsTest::tearDown
.
TemplateMethodsTest::setUp
TemplateMethodsTest::assertPreConditions
TemplateMethodsTest::testTwo
TemplateMethodsTest::tearDown
TemplateMethodsTest::onNotSuccessfulTest
F
TemplateMethodsTest::tearDownAfterClass
  • テストが大変
    • singleton を使用するコード
    • グローバル変数を使うコード
  • 数や組み合わせにとらわれずに好きなテストを一緒に実行できる
  • Example 7.1
    • テストケースがまだ完成していない or テストの省略
    • $this->markTestIncomplete();
    • @requiresによるテストケースのスキップ
  • テストダブルとは=テスト対象が依存しているコンポーネントを置き換える代用品
    • createMock($type) / getMockBuilder($type) = 指定したインタフェースの代用としてふるまうオブジェクトを自動生成できる
  • getMockBuilder
    • disableOriginalConstructor():元クラスのコンストラクタを無効化
    • disableOriginalClone():元クラスのクローンコンストラクタを無効化
    • https://qiita.com/tsuuuuu_san/items/46246168dc36ad2369cc
    • $stub->doSomethingの引数に指定した値を返す
      • $stub->method('doSomething')->will($this->returnArgument(0));
      • $this->assertSame('foo', $stub->doSomething('foo'));
    • willReturnで指定した値を返す
      • $stub->method('doSomething')->willReturn('foo');
      • $this->assertSame('foo', $stub->doSomething());
    • returnCallbackでコールバックからの値を返す
      • $stub->method('doSomething')->will($this->returnCallback('str_rot13'));
      • $this->assertSame('fbzrguvat', $stub->doSomething('something'));
      • $stub->doSomething($argument) = str_rot13($argument)
    • onConsecutiveCallsでリストで指定した値をその順番で返す
      • $stub->method('doSomething')->will($this->onConsecutiveCalls(2, 3, 5, 7));
      • $stub->doSomething()を繰り返すと2→3→5→7の順に返す
    • will($this->throwException(new Exception))で、例外を返す
      • $stub->method('doSomething')->will($this->throwException(new Exception));
      • $stub->doSomething(); 例外をスロー
    • expects():用意したMockオブジェクトのメソッドが実際に扱われる頻度を設定 / チェックする為に利用するメソッド
    • with():任意の数の引数を渡す
  • モックオブジェクトを利用する場合は予めテストのことを考えて設計しておく必要がある
  • is_callable:引数が、関数としてコール可能な構造であるかどうかを調べる
  • 比較
  • モックフレームワーク:https://github.com/phpspec/prophecy
  • スタブ:テストを書くときは他のオブジェクトの実装に依存しないテストを作るべき。そのために使うのがスタブ
  • モック:実際のオブジェクトを置き換えて、 (メソッドがコールされたことなどの) 期待する内容を検証するテストダブルのこと
    • 即座にエラーを検知できるため詳しい設定が可能
    • テストに先立ってテストダブルに複雑な設定を行うため、テストが読みにくくなる難点
  • スパイ:テストダブルはメソッド呼び出しを記録するようにしておき、適当に操作をして、「どんなメソッドをどういう風に呼び出されたか」を後から記録と照合する方式
    • 何も準備しなくても使えるのでテストは読みやすい傾向がある
  • trait:https://www.php.net/manual/ja/language.oop5.traits.php
    • コードを再利用するための仕組み
    • 単一継承の制約を減らすために作られた
    • トレイトとクラスを組み合わせた構文は複雑さを軽減
  • getMockForTrait():指定したトレイトを使ったモックオブジェクトを返す
  • getMockFromWsdl():ウェブサービスのスタブ、モックを作成できる
  • 参考

PHPUnitの実行

PHPUnitの実行コマンド

すべてのテストメソッド実行

# vendor/bin/phpunit tests/StackTest.php
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment