# Laravel Test についてのメモ
Laravel 使って自動テストを行う作業があったので、メモして起きます。
tests ディレクトリの下 Feature と Unit ディレクトリにそれぞれのテストクラスを設置できます。
- Feature 機能テスト、全体テスト
/tests/Feature配下
- Unit ユニットテスト、単体テスト
/tests/Unit配下
ユニットテストは Laravel アプリケーションを起動しないため、アプリケーションのデータベースやその他のフレームワークサービスにアクセスできません。
機能テストはシステム全体が意図したとおりの機能も用いてログインした状態でアクセス時の動作テスト、検索パラメータ付けたアクセス時の動作確認ができます。
# テスト実行コマンド
# 作成
php artisan make:test UserTest
デフォルトは tests/Feature ディレクトリへ配置
--unitオプション使う場合tests/Unitディレクトリへ配置
# テスト実行コマンド
# phpunit
./vendor/bin/phpunit
# artisan
php artisan test
phpunit と Artisan の違い
- Artisan テストは詳細なテストレポートを提供
- phpunit コマンドで使用できる引数はすべて Artisan test コマンドにも渡せます。
php artisan test --testsuite=Feature --stop-on-failure
# サンプル
# テスト作る
php artisan make:test UserTest
# テストファイル編集
Faker 使ってデータ生成しながら、テストファイル編集
<?php
namespace Tests\Feature;
use Faker;
use Tests\TestCase;
class UserTest extends TestCase
{
public function test_example()
{
$response = $this->get('/');
$response->assertStatus(200);
}
public function test_login()
{
$faker = Faker\Factory::create();
$response = $this->post('/login', [
'email' => $faker->email(),
'password' => 'test',
]);
$response->assertStatus(200);
}
}
# テストコマンド実行
php artisan test
# PASS Tests\Unit\ExampleTest
# ✓ example
#
# PASS Tests\Feature\ExampleTest
# ✓ example
#
# PASS Tests\Feature\UserTest
# ✓ example
# ✓ login
#
# Tests: 4 passed
# Time: 0.78s
# テストを並列で実行 --parallel オプション
php artisan test --parallel
--parallel オプション使うことでテスト時間を大幅に削減できます。
デフォルトではマシン CPU コアの数だけプロセスを作成されますが、--processes オプション付けることでプロセス数を調整できます。
php artisan test --parallel --processes=4
.env.testing ファイルは --env=testingオプションの際に使用されます。
# Faker のよく使うメソッド
| メソッド | 説明 |
|---|---|
$faker->lastName | 姓 |
$faker->firstName | 名 |
$faker->name | 姓名 |
$faker->address | 住所 |
$faker->postcode | 郵便番号 |
$faker->phoneNumber | 電話番号 |
$faker->country | 国 |
$faker->email | メールアドレス |
$faker->safeEmail | 安全メールアドレス |
$faker->freeEmail | 無料メールアドレス |
$faker->companyEmail | 企業メールアドレス |
$faker->freeEmailDomain | 無料メールアドレスドメイン |
$faker->safeEmailDomain | 安全メールアドレスドメイン |
$faker->userName | ユーザーネーム |
$faker->password | パスワード |
$faker->domainName | ドメイン |
$faker->url | URL |
$faker->slug | スラグ文字列 |
$faker->ipv4 | ipv4 IP |
$faker->localIpv4 | ipv4 IP |
$faker->ipv6 | ipv6 IP |
$faker->macAddress | Mac アドレス |
# uploadedFile ファイルアップロードのテスト
画像ファイル
<?php
namespace Tests\Feature;
use Tests\TestCase;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;
class ExampleTest extends TestCase
{
public function testAvatarUpload()
{
Storage::fake('avatars');
$response = $this->json('POST', '/avatar', [
'avatar' => UploadedFile::fake()->image('avatar.jpg')
]);
// ファイルが保存されたことをアサートする
Storage::disk('avatars')->assertExists('avatar.jpg');
// ファイルが存在しないことをアサートする
Storage::disk('avatars')->assertMissing('missing.jpg');
}
}
# サイズ指定画像アップロード
UploadedFile::fake()->image('avatar.jpg', $width, $height)->size(100);
# PDF ファイルアップロード
UploadedFile::fake()->create('document.pdf', $sizeInKilobytes);
# エクセルファイルアップロード
$response = $this->post(route('users.excel.import.upload'), [
'users' => UploadedFile::fake()->create(
name: 'users.xlsx',
mimeType: 'application/vnd.openxmlformats-officedocument.spread'
)
]);
# CSV ファイルアップロード
$header = 'Header 1,Header 2,Header 3';
$row1 = 'value 1,value 2,value 3';
$row2 = 'value 1,value 2,value 3';
$content = implode("\n", [$header, $row1, $row2]);
$inputs = [
'csv_file' =>
UploadedFile::
fake()->
createWithContent(
'test.csv',
$content
)
];
$response = $this->postJson(
'file-upload',
$inputs
);
$response->assertOk();
# 利用可能なアサート
json、get、post、put、delete
| レスポンスアサート | ||
|---|---|---|
assertCookie | $response->assertCookie($cookieName, $value = null); | クッキー持っている |
assertCookieExpired | $response->assertCookieExpired($cookieName); | クッキー期限切れである |
assertCookieNotExpired | $response->assertCookieNotExpired($cookieName); | クッキー期限切れでない |
assertCookieMissing | $response->assertCookieMissing($cookieName); | クッキーを持っていない |
assertDontSee | $response->assertDontSee($value); | 指定した文字列がレスポンスに含まれていない |
assertDontSeeText | $response->assertDontSeeText($value); | 指定した文字列がレスポンステキストに含まれていない |
assertExactJson | $response->assertExactJson(array $data); | 指定した JSON データと完全に一致する |
assertForbidden | $response->assertForbidden(); | forbidden ステータスコードを持っている |
assertHeader | $response->assertHeader($headerName, $value = null); | 指定したヘッダが存在している |
assertHeaderMissing | $response->assertHeaderMissing($headerName); | 指定したヘッダが存在していない |
assertJson | $response->assertJson(array $data); | 指定した JSON データを持っている |
assertJsonCount | $response->assertJsonCount($count, $key = null); | 指定したキーのアイテムを、期待値分持っている |
assertJsonFragment | $response->assertJsonFragment(array $data); | 指定した JSON の一部を含んでいる |
assertJsonMissing | $response->assertJsonMissing(array $data); | 指定した JSON の一部を含んでいない |
assertJsonMissingExact | $response->assertJsonMissingExact(array $data); | JSON の一部をそのまま含んでいない |
assertJsonStructure | $response->assertJsonStructure(array $structure); | 指定した JSON の構造を持っている |
assertJsonValidationErrors | $response->assertJsonValidationErrors($keys); | 指定した JSON バリデーションエラーを持っている |
assertLocation | $response->assertLocation($uri); | Location ヘッダが、指定した URI を持っている |
assertNotFound | $response->assertNotFound(); | not found のステータスコードを持っている |
assertOk | $response->assertOk(); | 200 のステータスコードを持っている |
assertPlainCookie | $response->assertPlainCookie($cookieName, $value = null); | 指定した暗号化されていないクッキーを持っている |
assertRedirect | $response->assertRedirect($uri); | 指定した URI へリダイレクトする |
assertSee | $response->assertSee($value); | 指定した文字列がレスポンスに含まれている |
assertSeeInOrder | $response->assertSeeInOrder(array $values); | 指定した文字列が、順番通りにレスポンスに含まれている |
assertSeeText | $response->assertSeeText($value); | 指定した文字列がレスポンステキストに含まれている |
assertSeeTextInOrder | $response->assertSeeTextInOrder(array $values); | 指定した文字列が、順番通りにレンスポンステキストへ含まれている |
assertSessionHas | $response->assertSessionHas($key, $value = null); | セッションが指定したデータを持っている |
assertSessionHasAll | $response->assertSessionHasAll(array $data); | セッションが指定したリストの値を持っている |
assertSessionHasErrors | $response->assertSessionHasErrors(array $keys, $format = null, $errorBag = 'default'); | セッションが指定したフィールドに対するエラーを含んでいる |
assertSessionHasErrorsIn | $response->assertSessionHasErrorsIn($errorBag, $keys = [], $format = null); | セッションが指定したエラーを持っている |
assertSessionHasNoErrors | $response->assertSessionHasNoErrors(); | セッションがエラーを持っていない |
assertSessionMissing | $response->assertSessionMissing($key); | セッションが指定したキーを持っていない |
assertStatus | $response->assertStatus($code); | 指定したコードである |
assertSuccessful | $response->assertSuccessful(); | 成功のステータスコードである |
assertViewHas | $response->assertViewHas($key, $value = null); | 指定したデータを持っている |
assertViewHasAll | $response->assertViewHasAll(array $data); | 指定したリストのデータを持っている |
assertViewIs | $response->assertViewIs($value); | 指定したビューが返された |
assertViewMissing | $response->assertViewMissing($key); | 指定したデータを持っていない |
# 認証のアサート
| メソッド | 説明 |
|---|---|
$this->assertAuthenticated($guard = null); | ユーザーが認証されている |
$this->assertGuest($guard = null); | ユーザーが認証されていない |
$this->assertAuthenticatedAs($user, $guard = null); | 指定したユーザーが認証されている |
$this->assertCredentials(array $credentials, $guard = null); | 指定した認証情報が有効である |
$this->assertInvalidCredentials(array $credentials, $guard = null); | 指定した認証情報が無効である |