言語(PHP他)PHPLaravel
更新日 : 2020年9月1日
投稿日 : 2020年6月30日

Laravel7でログイン画面を作ってPHPUnitで動作確認する

Laravel7でログイン画面を作ってPHPUnitで動作確認するの画像

こんにちわ、PHPエンジニアのエンジニア婦人(@naho_osada)です。
私はPHPエンジニアとして7年~の経験があります。WordPressは2年半~の経験があります。その他、jQuery、HTML、CSSも使用します。
ここでは主に過去に納品した案件や自サイト運営(エンジニア婦人ノート)で遭遇したことについて書いています。

今回はLaravelでログイン画面を作ってみます。

※CentOS7 LAMP環境で行っています。

※MariaDB、Laravelそのもののインストール(含むComposer)、Nodejsがインストールされている前提です。
これらのインストール手順はこちらです。

ログイン画面を作る

公式の「認証」ページに書いてあるコマンドを実行します。

composer require laravel/ui

php artisan ui vue --auth

npm install && npm run dev

これで基本的なログイン機能ができました!なんて便利なんでしょう…何回やっても便利です。

ログイン画面を表示できます。ログイン処理はまだできません。

ログイン画面

データベースとテーブルを作る

画面はできましたが、まだデータベースとの連携ができていません。必要な情報を入力してmigrateします。
データベースのユーザー、パスワード、データベースを作成しておきます。ユーザーのホストは「localhost」(ユーザー名’@’localhost)です。

.envファイルを編集する

laravelの.envファイルを開いて、データベース接続情報を入力します。

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=データベース名
DB_USERNAME=データベースのユーザー名
DB_PASSWORD=データベースのパスワード

設定後、コンソールからmigrateします。

php artisan migrate

失敗するときはエラーメッセージが出るので、それをよく読んで解決します。大体ユーザー名やパスワードが違ってログインできない、データベースがないなどが多いかと思います。

migrateからユーザー、パスワードを設定する

/database/migrationsに

  1. 2014_10_12_000000_create_users_table.php
  2. 2014_10_12_100000_create_password_resets_table.php
  3. 2019_08_19_000000_create_failed_jobs_table.php

の3ファイルができています。1番目の「2014_10_12_000000_create_users_table.php」を修正します。

up関数の中でテーブルの情報を定義しています。

public function up()
{
	Schema::create('users', function (Blueprint $table) {
	    $table->id();
	    $table->string('name');
	    $table->string('email')->unique();
	    $table->timestamp('email_verified_at')->nullable();
	    $table->string('password');
	    $table->rememberToken();
	    $table->timestamps();
	});
}

これを以下のように変更します。

public function up()
{
	Schema::create('users', function (Blueprint $table) {
	    $table->id();
	    $table->char('name', 50); // char(50)
	    $table->char('email', 250)->unique(); // char(250)
	    $table->timestamp('email_verified_at')->nullable();
	    $table->string('password');
	    $table->rememberToken();
	    $table->timestamps();
	});

	// ユーザーを追加
	DB::table('users')->insert([
	    'name' => 'test',
	    'email' => 'xxxxx@gmail.com',
	    'password' => Hash::make('test'),
	]);
	DB::table('users')->insert([
	    'name' => 'test02',
	    'email' => 'xxxxx@gmail.com',
	    'password' => Hash::make('test02'),
	]);
}

データベースの名前とメールアドレスをchar型にしました。
同時にユーザーテーブルにテストデータを格納するようにしました。

もう一度migrateしてみます。一旦ロールバック(1つ前に戻す)してからmigrateです。

php artisan migrate:rollback
php artisan migrate

データベースをphpMyAdminなどで確認すると、指定したデータが格納されていることがわかります。

ログインしてみる

いよいよログインしてみます。ログイン画面(/login)にアクセスします。

設定したメールアドレスとパスワードを入れて、ダッシュボードに来たら成功です。

デフォルトのdashboard

エラーが出た場合

「Access denied for user root@localhost」などと表示されることがあります。ユーザーが.envファイルで指定しているものと異なる場合、変更が反映されていない可能性があります。

この場合、「php artisan serve」でLaravelを再起動、または「php artisan cache:clear」でキャッシュをクリアすると解決します。

ログインテスト(PHP Unit)を書いて実行する

Laravelのコマンドで生成したものを確認するテストを書いてみます。

作ったログイン機能が正常に動作するかを確認する試験を書いてみます。LaravelはPHPUnitが同梱されているので、特別インストールする必要はありません。

テスト用の.env.testingファイルを作成する

実データでテストするよりも、テスト用のデータを使ってテストする方が安全です。万一テストでデータ破壊してしまったら…元に戻せなくなったら…考えたら恐ろしいですね。テスト用のデータベースを使用します。

テスト用のデータベースを作成し、それを指定してテスト実行時はこちらを見るようにします。

phpunit.xmlの<php></php>内にある「server name=”APP_ENV”」のvalueはデフォルトで「testing」になっています。
.envファイルはこれが「.env.testing」を参照します。なければ.envを見ます。

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=テスト用のデータベース名
DB_USERNAME=テスト用のデータベースのユーザー名
DB_PASSWORD=テスト用のデータベースのパスワード

テストファイルの作成

php artisan make:test テストクラス名

# Unitテストの場合は php artisan make:test テストクラス名 --unitを実行

実行すると以下のファイルが「/tests/Feature」内にできます。ここではクラス名をLoginにしてみました。

<?php

namespace Tests\Feature;

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

class Login extends TestCase
{
    /**
     * A basic feature test example.
     *
     * @return void
     */
    public function testExample()
    {
        $response = $this->get('/');

        $response->assertStatus(200);
    }
}

FeatureとUnitの違い

FeatureはURL単位の一連の動作、unitは関数単位の試験を書いて使い分けるようです。

ログインのテストを書く

一例を載せておきます。ざっと説明すると

  • ログイン画面を表示→表示ができること、認証されていないこと
  • 直接ダッシュボードにアクセス→ログイン画面へリダイレクト、認証されていないこと
  • ログイン処理→処理後、認証されていること
  • ログアウト→ログイン後、ログアウト処理が実行されて認証されていないこと

を確認しています。

<?php

namespace Tests\Feature;

use App\User;
use Illuminate\Foundation\Testing\WithFaker;
use Tests\TestCase;
use DatabaseMigrations; // テスト用データベースを使用
use Illuminate\Foundation\Testing\RefreshDatabase; // テスト用データを自動で元に戻す

class LoginTest extends TestCase
{
    use RefreshDatabase;

    /**
     * ログイン画面を表示
     */
    public function testLoginView()
    {
        $response = $this->get('/login');
        $response->assertStatus(200);
        // 認証されていないことを確認
        $this->assertGuest();
    }

    /**
     * ダッシュボードアクセス(ログイン画面へリダイレクト)
     */
    public function testNonloginAccess()
    {
        $response = $this->get('/home');
        $response->assertStatus(302)
                 ->assertRedirect('/login'); // リダイレクト先を確認
        // 認証されていないことを確認
        $this->assertGuest();
    }

    /**
     * ログイン処理を実行
     */
    public function testLogin()
    {
        // 認証されていないことを確認
        $this->assertGuest();
        // ダミーログイン
        $response = $this->dummyLogin();
        $response->assertStatus(200);
        // 認証を確認
        $this->assertAuthenticated();
    }

    /**
     * ログアウト処理を実行
     */
    public function testLogout()
    {
        // ダミーログイン
        $response = $this->dummyLogin();
        // 認証を確認
        $this->assertAuthenticated();
        $response = $this->post('/logout');
        // ホーム画面にリダイレクト
        $response->assertStatus(302)
                 ->assertRedirect('/'); // リダイレクト先を確認
        // 認証されていないことを確認
        $this->assertGuest();
    }

    /**
     * ダミーユーザーログイン
     */
    private function dummyLogin()
    {
        $user = factory(User::class, 'default')->create();
        return $this->actingAs($user)
                    ->withSession(['user_id' => $user->id])
                    ->get(route('home')); // homeにリダイレクト
    }
}

テストを実行する

laravelプロジェクトフォルダで実行します。

./vendor/bin/phpunit

# 上記のテストコードを実行すると以下のように返ってきます。
PHPUnit 8.5.8 by Sebastian Bergmann and contributors.

....                                                                4 / 4 (100%)

Time: 638 ms, Memory: 28.00 MB

OK (4 tests, 14 assertions)

まとめ

今回はLaravelのコマンドから管理画面を作成し、その動作を確認するPHPUnitのテストコードを書きました。

実際のテスト駆動開発の場合はPHPUnitから書いて実装していくことになりますが、今回は「Laravelのコマンドで生成したものを確認するテストを書いてみる」ということで順序が逆になっています。

まずはこうやって動くんだ!という体感を得たいときに、試してみてください(‘ω’)ノ