Fippiyのプログラム学習内容アウトプットBlog

日々の学習内容をアウトプットして振り返りを実施する。

Laravel開発、Userテーブルのテストをする【1】ログインをテストする

テストの準備が整ったので、具体的なテストを実施していきます。

まずは前回記事で扱っていたUserテーブルに関連するサイトからテストを行います。

今回の目的

ユーザーログインに対してのテストを実施し、正常動作を確認する

なぜやるか

テストプログラムを実行することで、正常動作の担保を行うため

やりたいこと

  • ログインが正しくできることをテストコードで実証する
  • バリデーションエラー時の対処が実施できていることを確認する

やったこと

モデルファクトリを利用してユーザーを作成する

モデルファクトリ利用によるユーザーが生成されているか検証する

ログインが成功していることをテストする

ログインが失敗していることをテストする

実施内容

ログイン機能テストの準備

まずは、ユーザーがログインする機能に対してのテストを行います。

モデルファクトリを利用する

テスト時にユーザーを任意で作成する必要性が出てくるので、予めユーザーの作成内容を記載したファクトリを準備します。

こちらを参考にさせて頂きました、ありがとうございます。

www.larajapan.com

準備といっても…UserFactoryは初めから既に用意されています。前回記事でも登場しました。

改めて内容を確認します。

 # ~/database/factories/UserFactory.php

$factory->define(User::class, function (Faker $faker) {
return [
'name' => $faker->name, // 名前を自動生成
'email' => $faker->unique()->safeEmail, // emailを自動生成、ユニーク重複なし設定付き
'email_verified_at' => now(), // verifiedの日付を現在時刻設定
'password' => bcrypt('12345678'), // ハッシュ化パスワード
'remember_token' => Str::random(10), // ランダム生成
];
});

$fakerを利用して自動生成データをnameとemailに設定しています。

emailは複数レコード作成時に重複させないオプションを使用。

パスワードは今回変更をしました。ハッシュ化設定を加え、検証用パスワードを固定して保存しています。

 

変更を加えているので、テストを動作させ全てテストが通ることを確認します。

$ vendor/bin/phpunit

問題なく動作しました。

 

作成ユーザー情報を確認する

本項は直接テストとは関係ないかもしれませんが、実際にデータが出来ていることを確認してみたかったので実施しました。

# ~/tests/Feature/UserTest.php

public function testDatabase()
{
$user = factory(User::class)->create([
'name' => 'AAA',
'email' => 'BBB@CCC.COM',
'password' => 'ABCABC',
]); // DBに配列で指定したユーザーを生成
$users_some = factory(User::class, 10)->create(); // UserFactory指定のユーザーを10レコード作成

$this->assertDatabaseHas('users', [
'name' => 'AAA',
'email' => 'BBB@CCC.COM',
'password' => 'ABCABC',
]); //DBに配列で指定したユーザーがいること
$all = User::all(); // 作成した全ユーザーを取得
eval(\Psy\sh()); // ブレークポイント
}

前回記事で作成した、ユーザーを生成しているテストコードです。

最後に作成済み全ユーザーを取得する設定を追加し、直後にデバッグ用のブレークポイントを設定しました。

  

この状態でテスト実施します。

$ vendor/bin/phpunit

PHPUnit 7.5.7 by Sebastian Bergmann and contributors.

...Psy Shell v0.9.9 (PHP 7.1.23 — cli) by Justin Hileman

From tests/Feature/UserTest.php:54:

    52|         ]); //DBに配列で指定したユーザーがいること

    53|         $all = User::all(); // 作成した全ユーザーを取得

  > 54|         eval(\Psy\sh()); // ブレークポイント

    55|     }

    56| }

テストでもブレークポイントで処理が中断できました。

 

ここで$allの中身を確認します。

>>> echo $all

[{"id":1,"name":"AAA","email":"BBB@CCC.COM","email_verified_at":"2019-04-24 14:08:55","created_at":"2019-04-24 14:08:55","updated_at":"2019-04-24 14:08:55"},{"id":2,"name":"Mr. Chance Schroeder II","email":"bartell.sven@example.com","email_verified_at":"2019-04-24 14:08:55","created_at":"2019-04-24 14:08:55","updated_at":"2019-04-24 14:08:55"},

〜省略〜

]

作成したユーザー情報が表示できました。

1つ目は個別設定したユーザー、2つ目以降はfaker利用のランダムなユーザーが作成されていることを確認できました。

 

ログインテストを実装する

正常にログインできることをテストする

まずはエラーなくログインが完了する処理を記載して、ログイン出来ていることを確認します。

 

何をもってOKとするか…

  1. ログイン検証用ユーザーを用意しておく
  2. Auth認証前の状態であること
  3. ログインフォームでメールアドレスとパスワードを入力する
  4. パスワードが登録済みレコードと一致する
  5. メールアドレスが登録済みレコードと一致する
  6. Auth認証済みであることの確認
  7. エラーメッセージがないこと
  8. Auth認証後のリダイレクト先に遷移していること

このあたりの動作が検証できれば、テストコードとして問題なくログイン出来ていると言えそうです。

ということで、条件をみたすコードを記述します。

# ~/tests/Feature/UserTest.php

// ログイン成功テスト
public function testLoginOK()
{
$user = factory(User::class)->create(); // 1.ユーザーを作成

$this->assertFalse(Auth::check()); // 2.Auth認証前であることを確認

$response = $this->post('login', [
'email' => $user->email,
'password' => '12345678'
]); // 3.ログイン実施 4.5.正しい情報のユーザー

$this->assertTrue(Auth::check()); // 6.Auth認証後であることを確認
$response->assertSessionHasNoErrors(); // 7.エラーメッセージがないこと

$response->assertRedirect('book'); // 8.ログイン後にリダイレクトされるのを確認
}

初めに検証用ユーザーを作成しておき、認証前であることを確認します。

検証ユーザーは先程のUserファクトリを利用しています。

 

そして実際にログインを行うコードを書いています。

post('login'〜として~/loginページでPostでデータを送信しています。

 

データ送信後は正常にログインできるので、Auth認証が完了していることを確認し、バリデーションエラーも発生しませんので、エラーメッセージが出力されていないことを確認します。

最後に、ログイン後はリダイレクトすることになっているので、リダイレクト先に遷移していることを確認しています。

 

以上で、正常にログインするテストは完了です。

 

ログインに失敗することをテストする

ログインできずに失敗するケースもあるので、ログインできなかったことを確認できるようにします。

何をもってNGとするか

  1. メールアドレスが未入力
  2. メールアドレスがDBと不一致
  3. パスワードが未入力
  4. パスワードがDBと不一致

エラー発生後に確認する項目

  • エラーメッセージが出力されていること
  • ログイン失敗によりAuth認証できていないことを確認

4項目についてそれぞれ検証し、結果として対応するエラーメッセージを確認し、ログインできていないことを確認すればログイン失敗としての検証ができそうです。 

 

この中から、1と4の内容について詳細を確認していきます。

内容がほぼ同じである為、2と3は割愛します。

 

1.メールアドレス未入力のケースを作成しました。

# ~/tests/Feature/UserTest.php

// ログイン失敗email未入力
public function test_login_ng_email_notInput()
{
$user = factory(User::class)->create(); // ユーザーを作成

$this->assertFalse(Auth::check()); // Auth認証前であることを確認
 
$response = $this->post('login', [
'email' => '',
'password' => '12345678'
]); // ログイン実施 名前が異なるユーザー
 
$this->assertFalse(Auth::check()); // Auth認証されていないことを確認
$response->assertSessionHasErrors(['email']); // emailエラーを確認

$this->assertEquals('メールアドレスは必須です。',
session('errors')->first('email')); // エラメッセージを確認
}

流れとしてはテストOK時と同じです。

ログイン時のメールアドレスを空欄にしました。

ログインデータ送信後は、失敗するはずなのでAuth認証されていないままであることを確認し、バリデーションエラーが発生していることを確認しています。

最後に、エラーメッセージの出力が一致していることを確認してテスト終了です。 

 

次は、4.パスワードがDB登録内容と一致しないケースです。

// ログイン失敗パスワードアンマッチ
public function test_login_ng_password_unMatch()
{
$user = factory(User::class)->create(); // ユーザーを作成

$this->assertFalse(Auth::check()); // Auth認証前であることを確認
 
$response = $this->post('login', [
'email' => $user->email,
'password' => '123456789'
]); // ログイン実施 パスワードが異なるユーザー
 
$this->assertFalse(Auth::check()); // Auth認証されていないことを確認
$test = $response->assertSessionHasErrors(['email']); // emailエラーを確認
$this->assertEquals('認証情報が記録と一致しません。',
session('errors')->first('email')); // エラメッセージを確認
}

ログイン時のパスワードが異なっています。

パスワードのエラーと思っていたのですが、実際エラーメッセージとしてはemailのエラーとして出力されましたので、emailエラーを取得してメッセージを取得しました。

 

以上で、ログインに対してのテストは完了です。

Userテーブルの中でも特にAuth機能を利用する内容を実施してきました。

Auth利用には新規登録とパスワードリセットが残っていますので、続いて実施する予定です。