13
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

PHPUnitの公式ドキュメントを全部読んだので大事なところをまとめてみた

Last updated at Posted at 2022-08-26

はじめに

はじめまして株式会社ナイトレイの渡辺です。

現在私が関わっているプロダクトでPHPのユニットテストを導入した際、PHPUnitを利用するにあたって公式ドキュメントを一通り読んだので、この記事では個人的に重要な箇所を備忘録としてまとめます。

💡 本記事で記載されている内容はこちらのドキュメントから引用させていただいております

対象読者

  • 少しPHPUnitを使ったことがある
  • PHPUnitをもっと上手く使いたい

環境

PHPUnit 9.5.20

内容

PHPUnit 用のテストの書き方

この章では、PHPUnit を使ったテストを書く際の基本的な決まり事や手順を紹介しています。

最低限、PHPUnitでテストを書く上で必要な情報なので一通り目を通すことを推奨します。

https://phpunit.readthedocs.io/ja/latest/writing-tests-for-phpunit.html

フィクスチャ

テンプレートメソッド

テンプレートメソッド setUp() および tearDown() は、テストケースクラスのテストメソッドごとに (そして最初にインスタンスを作成したときに) 一度ずつ実行されます。

また、テンプレートメソッド setUpBeforeClass()および tearDownAfterClass()が存在します。 これらはそれぞれ、テストケースクラスの最初のテストメソッドの実行前と テストケースクラスの最後のテストの実行後にコールされます。

アンチパターン

Example 4.3 テストスイートの複数テスト間でのフィクスチャの共有

<?php declare(strict_types=1);
use PHPUnit\Framework\TestCase;

final class DatabaseTest extends TestCase
{
    private static $dbh;

    public static function setUpBeforeClass(): void
    {
        self::$dbh = new PDO('sqlite::memory:');
    }

    public static function tearDownAfterClass(): void
    {
        self::$dbh = null;
    }
}
🚫 複数テスト間でのフィクスチャの共有してしまっており、各オブジェクトが疎結合になっていない。

tearDown()の使い所

tearDown()を実装する必要があるのはsetUp()で外部リソース (ファイルやソケットなど) を割り当てた場合のみです。もし setUp()で単に PHP オブジェクトを作成しただけの場合は、 一般には tearDown()は必要ありません。

phpunit.xmlについて

beStrictAboutTestsThatDoNotTestAnything="false”

PHPUnit はデフォルトで、何も確かめていないテストを検出します。 このチェックを無効にするには、コマンドラインオプション --dont-report-useless-tests を使うか、あるいは PHPUnit の XML 設定ファイルで beStrictAboutTestsThatDoNotTestAnything="false" を設定します。

何もアサーションを実行していないテストは、このチェックを有効にしておくと、 危険であるとマークされます。モックオブジェクトでの例外や、 @expectedException などのアノテーションは、アサーションとみなします。

beStrictAboutOutputDuringTests="true”

PHPUnit は、テストの最中の出力を検出することができます。 このチェックを有効にするには、コマンドラインオプション --disallow-test-output を使うか、あるいは PHPUnit の XML 設定ファイルで beStrictAboutOutputDuringTests="true" を設定します。

テストコードあるいは被テストコードの中で、print などで何かを出力している場合に、 このチェックを有効にしておくと、危険であるとマークされます。

**XML 設定ファイルを用いたテストスイートの構成

PHPUnit の XML 設定ファイルを使ってテストスイートを構成することができます。
Example 5.1 で一番シンプルなphpunit.xmlファイルを示します。これは、tests ディレクトリを再帰的に探索して *Test.php というファイルにある *Test クラスをすべて追加する設定です。

Example 5.1 XML 設定ファイルを用いたテストスイートの構成

<phpunit bootstrap="src/autoload.php">
  <testsuites>
    <testsuite name="money">
      <directory>tests</directory>
    </testsuite>
  </testsuites>
</phpunit>

特定のテストスイートを実行したい場合は、--testsuite オプションを利用します。

$ phpunit --bootstrap src/autoload.php --testsuite money
PHPUnit latest.0 by Sebastian Bergmann and contributors.

..
Time: 167 ms, Memory: 3.00Mb

OK (2 test, 2 assertions)

  • -configuration が設定 されていない 場合は、現在の作業ディレクトリから phpunit.xml あるいは phpunit.xml.dist を (この順に) 探し、 見つかった場合はそれを自動的に読み込みます。

また以下のように、テストの実行順序を XML 設定ファイルで明示的に指定することもできます。

Example 5.2 XML 設定ファイルを用いたテストスイートの構成

<phpunit bootstrap="src/autoload.php">
  <testsuites>
    <testsuite name="money">
      <file>tests/IntlFormatterTest.php</file>
      <file>tests/MoneyTest.php</file>
      <file>tests/CurrencyTest.php</file>
    </testsuite>
  </testsuites>
</phpunit>

不完全なテスト・テストの省略

テストに未完成の印をつける

Example 7.1 では SampleTest というテストケースクラスを定義しています。 markTestIncomplete() をテストメソッド内でコールすることで、 このメソッドがまだ完成していないことをはっきりさせます。

Example 7.1 テストに未完成の印をつける

use PHPUnit\Framework\TestCase;

final class SampleTest extends TestCase
{
    public function testSomething(): void
    {
        // オプション: お望みなら、ここで何かのテストをしてください。
        $this->assertTrue(true, 'これは動いているはずです。');

        // ここで処理を止め、テストが未完成であるという印をつけます。
        $this->markTestIncomplete(
          'このテストは、まだ実装されていません。'
        );
    }
}

未完成のテストは、PHPUnit のコマンドライン版テストランナーでは以下のように I
 で表されます。

$ phpunit --verbose SampleTest
PHPUnit latest.0 by Sebastian Bergmann and contributors.

I

Time: 0 seconds, Memory: 3.95Mb

There was 1 incomplete test:

1) SampleTest::testSomething
このテストは、まだ実装されていません。

/home/sb/SampleTest.php:12
OK, but incomplete or skipped tests!
Tests: 1, Assertions: 1, Incomplete: 1.

アサーション

利用可能なアサーションメソッドの一覧

この章では、利用可能なアサーションメソッドの一覧が記載されています。

実際にテストを書く中で、どのような時にどのアサーションを使えばいいのかを考えるタイミングがあります。その度にこの章を見返すことで最適なアサーションを選択できるようになります。

https://phpunit.readthedocs.io/ja/latest/assertions.html

アノテーション

@testdox

アジャイルドキュメントを生成する際に使う別の説明を指定します。

@testdox アノテーションは、クラスにもテストメソッドにも指定できます。

<?php **declare**(strict_types=1);
**use** PHPUnit\Framework\TestCase;

*/**
	* @testdox A bank account
*/*
**final** **class** **BankAccountTest** **extends** TestCase
{
    */**     
			* @testdox has an initial balance of zero
		*/*
		**public** **function** balanceIsInitiallyZero(): void
    {
        $this->assertSame(0, $this->ba->getBalance());
    }
}

@dataProvider

テストメソッドには任意の引数を渡すことができます。 引数は、データプロバイダメソッド (配列の配列を返すデータプロバイダの使用 の provider()) から渡されます。 使用するデータプロバイダメソッドを指定するには @dataProvider アノテーションを使います。

詳細は データプロバイダ を参照ください。

@before

@before アノテーションを使うと、 テストケースクラス内の各テストメソッドを実行する前に呼ぶメソッドを指定できます。

<?php declare(strict_types=1);
use PHPUnit\Framework\TestCase;

final class MyTest extends TestCase
{
    /**
     * @before
     */
    public function setupSomeFixtures(): void
    {
        // ...
    }

    /**
     * @before
     */
    public function setupSomeOtherFixtures(): void
    {
        // ...
    }
}

@after

@after アノテーションを使うと、 テストケースクラス内の各テストメソッドを実行した後に呼ぶメソッドを指定できます。

最後に

私たちの会社、ナイトレイでは一緒に自社開発のWebサービスを盛り上げてくれるエンジニアメンバーを募集しています!
基本的には直接ユーザーと接することのないポジションですが、セールス部門から
「顧客の声」を教えてもらったり、希望すればユーザーとのMTGに参加することも可能です。
モチベーションの高め方はあなた次第。

このような方は是非Wantedlyからお気軽にご連絡ください(もしくはこちらまで recruit@nightley.jp

✔︎ 自社Webサービスの開発で事業の発展に携わってみたい
✔︎ 自分が開発したサービスで地域活性化に貢献したい
✔︎ 位置情報ビッグデータに興味があり、新しい活用方法を提案したい
✔︎ 地理や地図が好きで仕事中も眺めていたい

一つでも当てはまる方は是非こちらの記事をご覧ください

▼ナイトレイとは?

参考文献

https://phpunit.readthedocs.io/ja/latest/

13
12
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?