テスト
laravel5.5

LaravelでHTTPテスト

環境

Laravel : 5.5.4

参考URL

Testing: Getting Started
HTTP Tests

設定ファイル

テストを行う際に本番DBを触らないようにテスト用のDBを見るようにします。
通常DB設定は.envファイルに記述すると思うのですが
テスト用のDB設定としてLaravelプロジェクト直下に.env.testingファイルを作成すると、テストの際はそちらを見るようになります。

You may also create a .env.testing file. This file will override values from the .env file when running PHPUnit tests or executing Artisan commands with the --env=testing option.

Environment Configuration

APP_ENVに関して

When running tests via phpunit, Laravel will automatically set the configuration environment to testing because of the environment variables defined in the phpunit.xml file. Laravel also automatically configures the session and cache to the array driver while testing, meaning no session or cache data will be persisted while testing.

参考URL
Creating & Running Tests

env.testingはphpunitがAPP_ENVをtestingにするようなので、testingにしなくても大丈夫らしいです。

DB_DATABASE

本番用のDBを触らないようにテスト用のDBを作成した上でテストDB名を記述します

HTTPテストファイルを作成

参考URL
Creating & Running Tests

今回はHTTPテストを行うので

// Create a test in the Feature directory...
$ php artisan make:test Test1

上記を実行すると
Laravelプロジェクト/tests/Featureの配下にTest1.phpというファイルができます。

テストコード

Database Migration trait

前にメモとして以下でも少し書いたのですが、
Laravel DuskでDBデータが飛んだって話(メモ)

LaravelのデータベースマイグレーションのトレイトとしてDatabaseTransactionsDatabaseMigrationsがあり、Laravel5.5からRefreshDatabaseが追加され

RefreshDatabaseを使うことでテスト前にMigrationSeederが実行され、
テスト後にはテーブルのみが残ってmigrationsテーブル以外の挿入データは削除されている状態になってました。

正直この辺はあまり理解していないのですが
Laravel5.5公式の方にはDatabaseMigrationsの記述しかなく、
テスト作成コマンドで作成されるテンプレにもDatabaseMigrationsのみが書かれているので
これからはDatabaseMigrationsを使っていくのが正しいのかなって感じです

use Illuminate\Foundation\Testing\RefreshDatabase;

class Test1 extends TestCase
{
    use RefreshDatabase;

軽いサンプル

Available Assertions
軽い感じのテストサンプルを書いておこうと思います

注意 visit()は使えない

代わりにget()を使用

参考URL
Laravel5.5: 単体テストの例

URLテスト

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

異常系のテスト。エラーになるか

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

リダイレクトテスト

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

認証を利用

factoryでユーザデータを作成し、actingAs()を利用することでそのユーザデータで認証済み状態にし、通常ログイン状態でないと遷移できないページのテストを行えます。

また、actingAsの第2引数に認証用でどのguardを使うか指定することができます。

You may also specify which guard should be used to authenticate the given user by passing the guard name as the second argument to the actingAs method:

$this->actingAs($user, 'api')
Session / Authentication

デフォルトのguardだと省略できます。

guardに関しての参考URL
ユーザー認証(10)Laravel 5.2 マルチ認証

config/auth.php

/* 認証のガードを定義 */

'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],

'api' => [
'driver' => 'token',
'provider' => 'users',
],
],

上記を踏まえて

//ユーザの作成・認証
$user     = factory(User::class)->create();
$response = $this->actingAs($user);

//マイページトップ
$response -> get('/mypage')
         ->assertSuccessful();

//会員用ニュースページ
$response -> get('/mypage/news')
          ->assertSuccessful();

新規データを作成して利用

例として、新規ニュースを作成し、作成したニュースのidを取得し、遷移チェックをする
assertSuccessful()ばかり使ってたので今回はassertSee('テキスト')でチェックするページにテキスト存在するかassertさせてみます

use App\User;
use App\News;

(省略)

$data = [
    'title'       => 'テストタイトル',
    'date'        => new Carbon()
];

//ニュース
$news = News::create($data);

$response -> get('/mypage/news/'.$news->id)
            ->assertSee('会員用ニュース');

実行

実行方法ですが、公式にも特に書いておらず

Laravelプロジェクト配下に移動し

vendor/bin/phpunit

ファイルを指定してテストを行いたい場合は

vendor/bin/phpunit tests/Feature/Test1.php

何かしら間違い等がありましたらコメントして下さると助かります