PHPUnitの設定は正しくしよう

Posted: 2015-03-22 22:10 |  laravel PHP全般 

本題の前に一つ

Laravel5のサンプルアプリケーションですが GitHub にて公開しています。
「laravel5になって名前空間が強制される」、「移行が大変」
ネット上でよく見かけますが、全くそんなことはありません。
composerのオートローダ指定の方法が異なるだけで、根本的には全く変わりません。
公開しているサンプルアプリケーションは、
5の新機能のいくつかを使って、
・マークダウンエディター(Laravel5 + React.js)
・簡単なToDoアプリケーション(Laravel5 + React.js)
・Laravel4と同様にclassmapを指定して名前空間を利用せずに実装した簡単なフォーム
上記3つが実装してあります。
React.jsも利用して手軽に実装してありますので、そちらの興味もあれば是非学んでみてください。
では本題に

ユニットテスト正しく実行していますか?

上記のサンプルアプリですが、カバレッジはCoverage Status です。
もちろんTravisCIなどで自動テストを実行していますので、すぐに動くはず!
テストの重要性についてはみなさん十分わかっていると思いますので、
あえてここでは記述しませんので、テストに関してのエントリなどを参照ください。
PHPStormなどでテストを簡単に実行することができますね?
このテストですが、実行するだけではテストが何に対してのものなのかはわかりません。
(当然ファンクショナルテストだったりユニットテストだったり、本人にはわかりますが・・)

そんな場合は自分以外の開発者などにどこまでテストでカバーされているか=カバレッジ を示すようにしましょう
普段からユニットテストを書いてる方は常識なことですが、
Laravel関連のユーザーが作ったライブラリなどでtestがほとんど無いものや、
phpunit.xmlが間違っているものなどがあまりに多すぎるのでおさらい的な意味を込めてます。

このphpunit.xmlが間違えている場合はカバレッジが正しく計測されないのはもちろん、
テストコードがほとんど無いのにbuild passになったりするわけです。

ではこのphpunit.xmlはどう書くべきなんでしょうか?
今回はLaravelを利用したアプリケーションを取り上げてみます。
laravelに同梱されているphpunit.xmlは次のようになっています。

デフォルト

<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         bootstrap="bootstrap/autoload.php"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false"
         syntaxCheck="false">
<testsuites>
    <testsuite name="Application Test Suite">
        <directory>./tests/</directory>
    </testsuite>
</testsuites>
<php>
    <env name="APP_ENV" value="testing"/>
    <env name="CACHE_DRIVER" value="array"/>
    <env name="SESSION_DRIVER" value="array"/>
    <env name="QUEUE_DRIVER" value="sync"/>
</php>
</phpunit>
それぞれの要素については、PHPユニットマニュアル を参照してください。
デフォルトで用意されているものは、testsディレクトリ配下が対象になっています。
もちろんこれは間違いではなく、正しい指定ですが、このままではtests配下が何に対してのテストなのかがわかりません。
これにtestsが対象とするテストがどこなのかを指定します。

対象を追加

    <filter>
        <whitelist>
            <directory>./app</directory>
        </whitelist>
    </filter>
これでappディレクトリ配下がtestsでテストする対象ということになります。
次にテストコードのカバレッジを出力するようにしましょう。
ここの対象が指定されていなければカバレッジが正しく計測されません。

clover.xmlの指定

    <logging>
        <log type="coverage-clover" target="build/logs/clover.xml"/>
    </logging>
loggingでclover.xmlを生成するように指定します。
このファイルはテスト実行で、対象にしたディレクトリに対してどこまでテストコードがカバーされているか
というのを事細かに記したものです。
これを利用してカバレッジが計測されるようになっています。
上記の設定を追加してLAravelアプリケーションをデフォルトのまま実行してみてください。
インストールした初期の状態では20%も無いはずです。
サンプルで用意されているテストはコントローラのレスポンスに対してのサンプルのみです。
このレスポンスを返却するにあたって、テストコードが担保しているクラスは
コントローラーに依存しているクラスが含まれており、
ユニットテスト つまりクラス単体のテストではありませんので、これがLaravelのユニットテストだ!
と思うのは全く違います。

それは正しいユニットテストではないのです!

このあたりについてはまたそのうち詳細に書きます。

先ほどのphpunit.xmlで大体の指定はOKですが、
インターフェースなどは対象から外したり、例えば実装を記述しないプロバイダーなどは
カバレッジの計測から外したいところです。
その場合は、excludeで指定することで対象から外すことができます。
たとえば最初から用意されているミドルウェアなどを全て対象から外す場合は次のような指定になります。
    <filter>
        <whitelist>
            <directory>./app</directory>
            <exclude>
                <directory>./app/Providers</directory>
                <directory suffix="Interface.php">./app</directory>
                <file>./app/Http/Requests/Request.php</file>
                <file>./app/Http/Kernel.php</file>
                <file>./app/Http/Middleware/RedirectIfAuthenticated.php</file>
                <file>./app/Http/Middleware/Authenticate.php</file>
                <file>./app/Http/Controllers/Controller.php</file>
                <file>./app/Commands/Command.php</file>
                <file>./app/Events/Event.php</file>
            </exclude>
        </whitelist>
    </filter>
これで純粋にユーザーが実装したコードのみが対象と成ります。
まとめると以下のphpunit.xmlとなります。
<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         bootstrap="bootstrap/autoload.php"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false"
         syntaxCheck="false">
    <testsuites>
        <testsuite name="Application Test Suite">
            <directory suffix="Test.php">./tests/</directory>
        </testsuite>
    </testsuites>
    <filter>
        <whitelist>
            <directory>./app</directory>
            <exclude>
                <directory>./app/Providers</directory>
                <directory suffix="Interface.php">./app</directory>
                <file>./app/Http/Requests/Request.php</file>
                <file>./app/Http/Kernel.php</file>
                <file>./app/Http/Middleware/RedirectIfAuthenticated.php</file>
                <file>./app/Http/Middleware/Authenticate.php</file>
                <file>./app/Http/Controllers/Controller.php</file>
                <file>./app/Commands/Command.php</file>
                <file>./app/Events/Event.php</file>
            </exclude>
        </whitelist>
    </filter>
    <php>
        <env name="APP_ENV" value="testing"/>
        <env name="CACHE_DRIVER" value="array"/>
        <env name="SESSION_DRIVER" value="array"/>
    </php>
    <logging>
        <log type="coverage-clover" target="build/logs/clover.xml"/>
    </logging>
</phpunit>

最後に

カバレッジ計測で便利なライブラリを紹介します。
というか超定番です。
satooshi/php-coveralls 
これを利用すればtravisCI実行後に Coveralls でカバレッジのバッジをゲットすることができます。
公開しているLaravel5サンプルアプリケーションでももちろん利用していますので、
ぜひ参考にして利用してみてください!
 

about ytake

執筆に参加しています


Laravel お役立ち情報

share



このエントリーをはてなブックマークに追加

Categories

laravel 45

DTM 0

music 0

PHP全般 31

0

JAPAN 1

WORLD 1

javascript 4

RDBMS 1

NoSQL 1

NewSQL 1

Recent Posts

Ad

comments powered by Disqus

GitHub

Social Links

Author


クリエイティブ・コモンズ・ライセンス
Yuuki Takezawa 作『Ytake Blog』はクリエイティブ・コモンズ 表示 - 非営利 4.0 国際 ライセンス で提供されています。

© ytake/comnect All Rights Reserved. 2014