Help us understand the problem. What is going on with this article?

[PHP] ゼロから始める PHPUnit + CI (1. PHPUnit を導入しよう)

More than 3 years have passed since last update.

目次

  1. PHPUnit を導入しよう(本記事)
  2. CI環境を導入しよう
  3. コードカバレッジを計測しよう

はじめに

プロジェクトに入った時には既にUnitテストの環境があったり、プロジェクトのリーダー的な人が導入進めたりしていて、 ユニットテスト(とCI)はやったことあるけど環境導入までやったことある人って結構限定されるんじゃないかなーと思った。(おそらく)敷居高く感じてる人多いと思うんだけど結構簡単にできるよーってことを示せればと。

これで社内にテストコード書く文化を・・・

対象となる人

  • PHPer
  • ユニットテスト自体はやったことあるけど、環境構築までやったことない人
  • 自分のGitHubリポジトリにバッチを貼りたい人

※ ユニットテスト、CIってなんぞやってことには触れません
※ テスト技法については触れません
※ とにかく導入の敷居を下げることを目的として書いてます。

環境

  • PHP7.1
  • PHPUnit6.4.3
  • Composer
  • GitHub
  • TravisCI(CIサービス)
  • Coveralls(カバレッジレポートサービス)

サンプルプログラム

リポジトリはこちら → https://github.com/PruneMazui/phpunit-training
各リポジトリのコミットが記事の内容に紐づくようにしているので、GitHub側を見ると具体的な変更点が分かって良いと思う。

テスト導入対象のプログラムは簡略化の為、非常に単純なものにした。
初期コミットは以下のような感じ。

COMMIT: initial commit サンプルプログラム

1. PHPUnit を導入しよう

1.1 PHPUnit をインストールしよう

COMMIT: 1.1 PHPUnit をインストールしよう

Composer 使って依存関係に PHPUnit を追加(devのみ)。
Composerって何って人はこちら

composer require --dev phpunit/phpunit

しばらくするとインストールが完了する。
ちゃんとインストールされたかチェック。

$ vendor/bin/phpunit --version
PHPUnit 6.4.3 by Sebastian Bergmann and contributors.

使っているPHPのバージョンによっては別バージョンのPHPユニットがインストールされる。
(本記事ではこのバージョンで統一)

1.2 テストケースを作ろう

COMMIT: 1.2 テストケースを作ろう

テストケースの書き方は今回は触れないのでこちらを参照 → PHPUnit 用のテストの書き方

今回は tests/src/HelloWorldTest.php に非常に簡単なテストケースを一つ作成した。
後からユニットテストの環境を導入する場合、この段階でテストの網羅性を気にしていたら中々先に進まず心が折れちゃう場合があるので、まずは$this->assertEquals(2, 1+1)レベルで作ってしまうのが個人的にオススメ。

tests/src/HelloWorldTest.php
<?php
namespace PruneMazui\PhpunitTraining\Tests;

use PHPUnit\Framework\TestCase;
use PruneMazui\PhpunitTraining\HelloWorld;

class HelloWorldTest extends TestCase
{
    public function testToString()
    {
        assertEquals('Hello World!', (string)(new HelloWorld()));
    }
}

テストケースを作ったら早速 PHPUnit を実行!

$ vendor/bin/phpunit tests
PHPUnit 6.4.3 by Sebastian Bergmann and contributors.

.                                                                   1 / 1 (100%)

Time: 77 ms, Memory: 4.00MB

OK (1 test, 1 assertion)

tests ディレクトリ以下(第一引数)の ~~Test.php というファイル名(PHPUnitデフォルト値)にある、public function test~~() な(PHPUnitデフォルト値)メソッドを実行する。

1.3 PHPUnit の設定ファイルを作ろう

COMMIT: PHPUnit の設定ファイルを作ろう

実は前節まででPHPUnitを実行する環境はできているのだが、ユニットテストを置く場所なんてプロジェクト毎に大抵決まっているし実行オプション等も共有したいので、設定ファイルを作ってしまう。

phpunit.xml.dist
<?xml version="1.0"?>
<phpunit>
    <testsuite name="Application Test">
        <directory>./tests/</directory>
    </testsuite>
</phpunit>

PHPUnit実行時に自動的に上記のXMLが読み込まれ、その中にテスト対象のディレクトリが指定されているので捗る。かなり割愛して書いているがXMLの詳細はこちら → 付録C XML 設定ファイル

$ vendor/bin/phpunit
PHPUnit 6.4.3 by Sebastian Bergmann and contributors.

.                                                                   1 / 1 (100%)

Time: 77 ms, Memory: 4.00MB

OK (1 test, 1 assertion)

PHPUnit は phpunit.xmlphpunit.xml.dist の優先度で自動的にXMLファイルを読み込む。
サンプルプログラムでは phpunit.xml は個人用として .gitignore に追加した。

1.4 初期化スクリプトを作ろう

COMMIT: 初期化スクリプトを作ろう

PHPUnit がテストケース実行前に走らせるスクリプトを指定できる。使い方はご自由に。

PHPUnit には $this->assert~~()assert~~() と書ける便利なグローバル関数群が用意されているのだが、デフォルトでは読み込んでいない。サンプルプログラムではこれを読み込む初期化スクリプトを組み込んでいる。

初期化スクリプト

tests/bootstrap.php
<?php
$reflection = new \ReflectionClass(\PHPUnit\Framework\Assert::class); // PHPUnit 5系だと微妙に場所が違うので注意
require_once dirname($reflection->getFileName()) . '/Assert/Functions.php';

初期化スクリプト読み込みをXMLに追記

phpunit.xml.dist
<?xml version="1.0"?>
<phpunit
    bootstrap=".tests/bootstrap.php"
>
    <testsuite name="Application Test">
        <directory>./tests/src/</directory>
    </testsuite>
</phpunit>

テストコードでグローバル関数使用

tests/src/HelloWorldTest.php
diff --git a/tests/src/HelloWorldTest.php b/tests/src/HelloWorldTest.php
index 4b9b216..753a5cb 100644
--- a/tests/src/HelloWorldTest.php
+++ b/tests/src/HelloWorldTest.php
@@ -8,6 +8,6 @@ class HelloWorldTest extends TestCase
 {
     public function testToString()
     {
-        $this->assertEquals('Hello World!', (string)(new HelloWorld()));
+        assertEquals('Hello World!', (string)(new HelloWorld()));
     }
 }

実行結果は以下の通り。

$ vendor/bin/phpunit
PHPUnit 6.4.3 by Sebastian Bergmann and contributors.

.                                                                   1 / 1 (100%)

Time: 94 ms, Memory: 4.00MB

OK (1 test, 1 assertion)

あとがき

これでPHPUnitを使ってのユニットテスト実行環境は整ったはず。
次回は CI環境 を作っていきます。

NEXT. CI環境を導入しよう

PruneMazui
試行錯誤の毎日 割と雑食だけどよくいるのはこの辺 ⇒ アジャイル / プロジェクトマネジメント / バックエンドアーキテクチャ / OOP / FP / RDBMS
admin-guild
「Webサービスの運営に必要なあらゆる知見」を共有できる場として作られた、運営者のためのコミュニティです。
https://admin-guild.slack.com
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away