Laravel ではじめる PHPUnit 入門

こんにちはー!むちょこです。

「テストコードを書いた方が良いのはわかるけど、何から始めたらいいかわからない」
「活用できるかわからないのに学習に時間をかけるのが嫌だ」

という方に向けて、低いハードルで便利さを体感できるオススメのテストをご紹介します:)

オススメはステータスコードのテスト

はじめの一歩に私がオススメしたいのは、ステータスコードのテストです!

覚えることがほんの僅かなのに、全アプリの全ページで使うことができます。

まだテストコードを書いたことがない方なら分かってくれると思うのですが、コマンド 1 つで全ページに 500 エラー(内部サーバエラー)が発生していないことが一瞬で確認できるとしたらめちゃめちゃすごいし、すべてを許されたかのような安心感がありませんか……?

実際にやってみましょう!

準備

PHP でテストコードを書くときは、 PHPUnit というテスティングフレームワークを使うことが一般的です。もちろんフルスクラッチのコードにも導入できますが、より簡単に行うために今回はベースのフレームワークに Laravel を利用します。

Laravel は初めから PHPUnit をサポートしており、さらに専用のヘルパメソッドも用意しているため、とても簡単にテストをはじめることができます。

まずは composer のインストールを行ってください(既に行っている方は不要です)。

コマンド
$ composer install

下準備はこれだけです。

Laravel には予めサンプルのテストコードが 2 つ用意されているので、一旦それが実行できるかどうかを確認してみましょう。

Laravel のプロジェクトディレクトリ下で次のコマンドを実行します。

コマンド
$ ./vendor/bin/phpunit

こんな風に OK が表示されれば成功です!

新しいテストクラスの作成

PHPUnit を正常に実行できることが確認できたので、次はステータスコードをテストするための新しいクラス(ここでは HttpStatusTest クラス)を作ります。

Laravel にはテストクラスを新規作成するためのコマンドが用意されているので、こちらを実行してください。

コマンド
$ php artisan make:test HttpStatusTest

このコマンドで生成されたファイルは tests/Feature/ ディレクトリに保存されます。

tests/Feature/HttpStatusTest.php
<?php

namespace Tests\Feature;

use Tests\TestCase;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Foundation\Testing\RefreshDatabase;

class HttpStatusTest extends TestCase
{
    /**
     * A basic test example.
     *
     * @return void
     */
    public function testExample()
    {
        $this->assertTrue(true);
    }
}

予め testExample() メソッドが用意されていますが、特に意味のないテストなので消すか無視していただいてかまいません。

新しいテストメソッドの作成

生成された HttpStatusTest クラスに、ステータスコードをテストするためのメソッドを追加します。

ルールはたったの 2 つです。

  • パブリックメソッドであること
  • メソッド名の接頭辞に “test” をつけるか、メソッドのコメントに @test アノテーションをつけること

このルールに則って、 testIndexStatus() メソッドを作ってみます。

tests/Feature/HttpStatusTest.php
/**
 * index ページのステータスコードは 200
 *
 * @return void
 */
public function testIndexStatus()
{

}

アサーションメソッドの実装

上記のルールを満たしたメソッド内にアサーションメソッドを実装することで、テストが動きます。

アサーションメソッドとは、テストコマンド実行時に期待した値と実際の値が同じになっているかどうかを確かめてくれるテスト用のメソッドです。

MEMO

※ここではステータスコードのアサーションメソッドしかご紹介していません。

「他にどんな種類があるのかな?」と気になる方は、ぜひこちらをご覧ください✨

PHPUnit 標準のアサーションメソッド一覧https://phpunit.readthedocs.io/ja/latest/assertions.html

それ以外に Laravel が提供しているアサーションメソッド一覧https://readouble.com/laravel/6.x/ja/http-tests.html#available-assertions

今回はステータスコードが 200 であることを確認するテストを書いていきましょう。テストするページは、パラメータなしの GET リクエストを受け付けるシンプルなページとします。

Laravel で GET リクエストを送り、そのレスポンスを受け取るためのコードはとてもシンプルに書くことができます。

$response = $this->get('/');

get() メソッドの引数にアプリケーションのルートを渡し、返り値でその HTTP ステータスコードやレスポンスヘッダ等を受け取ります。

また、ステータスコードのアサーションにも便利なヘルパメソッドが用意されています。

$response->assertStatus(200);

先ほど get() メソッドの返り値として受け取ったオブジェクトで、 assertStatus() メソッドを実行するだけです。引数には期待するステータスコードを渡します。

これらを先ほどの testIndexStatus() メソッドに実装するだけで、ステータスコードのテストは完成です。

tests/Feature/HttpStatusTest.php
/**
 * index ページのステータスコードは 200
 *
 * @return void
 */
public function testIndexStatus()
{
    $response = $this->get('/');
    $response->assertStatus(200);
}

テスト実行

本当にテストできるか、 phpunit コマンドで確認してみます。

コマンド
$ ./vendor/bin/phpunit

成功しました!やったー!

OK (4 tests, 4 assertions)というところで、4つのテストと4つのアサーションがクリアしたことが読み取れます。

今度は assertStatus() メソッドの引数を別の数値に変えて、わざとエラーを出してみましょう。

tests/Feature/HttpStatusTest.php
$response->assertStatus(302);
エラー文抜粋
1) Tests\Feature\HttpStatusTest::testIndexStatus
 Expected status code 302 but received 200.

エラーを読むと「HttpStatusTest クラスの testIndexStatus メソッドで、ステータスコード 302 が期待されていたけど実際には 200 を受け取ったよ!」って教えてくれています。親切ですね!

応用

同様にして他のページに GET リクエストを送ったり

$response = $this->get('/home');

適宜ステータスコードを変えたり

$response->assertStatus(301);

POST リクエストやアカウント認証等を活用することで、全ページに適用可能です✨

POST リクエストの例
$response = $this->post('/contact', [
    'email'  => '[email protected]',
    'message'=> 'hogepiyo'
]);
ログイン済みユーザとして検証する例
$user = factory(User::class)->create();
$response = $this->actingAs($user)
                 ->get('/home');

あまりの簡単さに拍子抜けした方もいるかもしれません。

この記事は「とにかくお手軽に試してほしい!」という思いから、最低限のことしか触れておりませんので、これでは物足りない、もっと詳しく知りたいという方はぜひ下記のドキュメントをご覧ください✨

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

Laravel公式ドキュメント
https://laravel.com/docs/6.x/testing

Laravel日本語ドキュメント
https://readouble.com/laravel/6.x/ja/testing.html