tanaka's Programming Memo

プログラミングについてのメモ。

Laravel5.3でSentinelを利用する(4)アクティベーション

前へ | 次へ

ユーザー登録ができたので、アクティベーションコードを確認して、ユーザーを有効にする処理を実装します。

(2016/12/21 テストにwantToを追加)


テストの作成

まずは、アクティベーションをするテストコードを作成しましょう。

  • ターミナルから以下を実行して、 ActivationUserCest.php を作成
composer exec codecept g:cest functional ActivationUser
  • tests/functional/ActivationUserCest.php をエディターで開いて、以下のコードに書き換える(2016/12/21 expectをwantToに書き換え)
<?php

class ActivationUserCest
{
    private $code = "";
    // ユーザーを登録
    private $cre = [
        'name' => 'アクティベーション',
        'email' => 'act@test.com',
        'password' => 'password'
    ];

    public function _before(FunctionalTester $I)
    {
        $user = Sentinel::register($this->cre);

        // アクティベーション作成
        $act = Activation::create($user);
        $this->code = $act->code;
    }

    public function _after(FunctionalTester $I)
    {
    }

    // tests
    public function tryToTest(FunctionalTester $I)
    {
        // コード違い
        $I->wantTo(' アクティベーションコード違いエラーの確認.');
        $url = url('activate', [base64_encode($this->cre['email']), 'error']);
        $I->amOnPage($url);
        $I->see(trans('sentinel.invalid_activation_params'), '.alert-danger');

        // 成功チェック
        $I->wantTo(' アクティベーション成功の確認.');
        $url = url('activate', [base64_encode($this->cre['email']), $this->code]);
        // リンクを amOnPage で表示
        $I->amOnPage($url);
        // 登録完了のメッセージをチェック
        $I->see(trans('sentinel.activation_done'));

        // すでにアクティベーション済みの場合は、普通にログイン画面へ
        $I->wantTo(' アクティベーション済みはログイン画面へ.');
        $url = url('activate', [base64_encode($this->cre['email']), 'no']);
        $I->amOnPage($url);
        $I->dontSee(trans('sentinel.activation_done'));
        $I->dontSee(trans('sentinel.invalid_activation_params'));

        // 失敗チェック
        $I->wantTo(' アクティベーションメールもアクティベーションコードも違う時の確認.');
        $url = url('activate', [base64_encode('nobody@test.com'), 'no']);
        $I->amOnPage($url);
        $I->see(trans('sentinel.invalid_activation_params'), '.alert-danger');
    }
}

npm test でテストを走らせるとエラーになります。これから実装を進めてテストが完了するようにします。


アクティベーション用のルートを作成

メールからは、 activate/{メールアドレス}/{アクティベーションコード} という形式でアクティベーション用のアクセスがあります。これを受け取って、処理するためのルートを追加します。

  • routes/web.php をエディターで開く
  • registerの登録の下に、以下を追加
// アクティベーション
Route::get('activate/{email}/{code}', 'Sentinel\ActivateController@activate');

アクティベーションの実行

ルートを定義したので、それを処理するコントローラーを作成します。

ルート内のパラメーター({email}と{code})は、Requestに渡されるので、$request->emailや$request->codeのようにアクセスすることができます。

  • ターミナルで以下を実行
php artisan make:controller Sentinel/ActivateController
  • app/Http/Controller/Sentinel/ActivateController.php をエディターで開く
  • ファイルの最初の方に、以下の use を追加
use Activation;
use Sentinel;
  • 以下の activate() メソッドをクラスに追加する
    /**
     * アクティベーション
     */
    protected function activate(Request $request) {
        // ユーザーを取得する
        $user = Sentinel::findByCredentials(['email' => base64_decode($request->email)]);
        if (is_null($user)) {
            return redirect('login')->with(['myerror' => trans('sentinel.invalid_activation_params')]);
        }

        // アクティベーション済みだった場合、そのまま戻る
        if (Activation::completed($user)) {
            return redirect('login');
        }

        // アクティベーションを実行する
        if (!Activation::complete($user, $request->code)) {
            return redirect('login')->with(['myerror' => trans('sentinel.invalid_activation_params')]);
        }

        return redirect('login')->with(['info' => trans('sentinel.activation_done')]);
    }

必要なメッセージの追加

アクティベーション関連のメッセージを追加します。

  • resources/lang/ja/sentinel.php をエディターで開いて、以下を追加
    // アクティベーション関連
    'invalid_activation_params' => 'アクティベーションの情報が一致しませんでした。',
    'activation_done' => 'ユーザー登録を完了しました。ログインして、サービスをご利用ください。',

以上で、アクティベーション処理は完成です。 npm test でテストを走らせると、「OK (3 tests, 14 assertions)」が表示されて成功します。

実際に動きを確認する場合は、 http://localhost:8000 を開いて、登録の流れを試してください。また、 http://localhost:8000/activate/bademail/badcode にアクセスすると、アクティベーションのパラメーターが不正である旨、表示されます。

ユーザーは有効にできましたが、まだログインが Sentinel に対応していないので、アクティベーションしたユーザーでのログインはできません。次はこれを対応させましょう。



前へ | 次へ

Laravel5.3でSentinelを利用する(3)ユーザー登録(2016/11/8更新)

前へ | 次へ

環境の構築が完了したので、実際に機能を置き換えていきます。まずはユーザー登録を対応させます。

(2016/11/8 エラーを変数でviewに渡していたのを、withErrorに変更)
(2016/12/21 HTMLのidをケバブケースに修正)
(2016/12/21 テストにwantToを追加)


方針

Sentinelのユーザー登録についての公式ドキュメントはこちら

ここでは次のことをします。

  • ユーザー名と、メールアドレスと、パスワードと、確認用のパスワードを受け付ける
  • ユーザー登録を完了するには、メールによる確認作業を必要にする
  • ユーザー名、メールアドレス、パスワードは必須
  • パスワードと確認用パスワードは一致していなければならない



ユーザー登録のテストを作成

ユーザー登録処理をSentinelに組み替えるにあたり、事前にテストコードを作成しておきます。

ボタンを確実に押すために、フォームにIDを設定します。

  • resources/views/auth/register.blade.php をエディターで開く
  • 「<form」から始まる行を見つけて、以下のようにID属性を追加する(idをケバブケースに修正 2016/12/21)
                    <form id="register-user-form" class="form-horizontal" role="form" method="POST" action="{{ url('/register') }}">

続いて、テスト用のCestファイルを作成しいます。

  • ターミナルから以下を実行して、ユーザー登録用のテストコードを生成
composer exec codecept g:cest functional RegisterUser
  • tests/functional/RegisterUserCest.php が出来上がるので、エディターで開く
  • tryToTestメソッドを以下のようにする(submitFormのidをケバブケースに修正 2016/12/21)
    // tests
    public function tryToTest(FunctionalTester $I)
    {
        // 空欄での登録試みが失敗するのを確認
        $I->wantTo(' 空欄での登録試みが失敗するのを確認.');
        $I->amOnPage('/register');
        $I->submitForm('#register-user-form', [
        ]);
        $I->seeInCurrentUrl('register');
        $I->see('name', '.help-block');
        $I->see('email', '.help-block');
        $I->see('password', '.help-block');

        // パスワードの不一致を確認
        $I->wantTo(' パスワードの不一致を確認.');
        $I->amOnPage('/register');
        $I->submitForm('#register-user-form', [
            'name' => 'テスト名前2',
            'email' => 'test2@test.com',
            'password' => 'testpass',
            'password_confirmation' => 'not'
        ]);
        $I->seeInCurrentUrl('register');
        $I->see('password', '.help-block');

        // 登録成功
        $I->wantTo(' ユーザーの登録成功を確認.');
        $I->amOnPage('/register');
        $I->submitForm('#register-user-form', [
            'name' => 'テスト名前',
            'email' => 'test@test.com',
            'password' => 'testpass',
            'password_confirmation' => 'testpass'
        ]);
        $I->seeInCurrentUrl('login');
        $I->see(trans('sentinel.after_register'));
    }

以下をテストするコードです。

  • 空欄での登録試みが失敗するのを確認
  • パスワードの不一致を確認
  • 登録成功

npm test で実行すると、エラーが発生します。まだ、ユーザー登録処理を Sentinel に入れ替えてなく、アサーションするための文字列も用意していません。このテストコードを通すことを目指して作業を進めていきます。

テストに利用できるメソッドなどはこちら → Laravel5 - Codeception - Documentation

メールのテスト環境を構築

メール送信のテスト時に、実際に本当のメールアドレスに送信すると削除するなどが面倒です。そこで、テスト用のメールサービス Mailtrap.io — Fake smtp testing server. Dummy smtp email testing を利用することにします。

MAIL_DRIVER=smtp
MAIL_HOST=mailtrap.io
MAIL_PORT=25
MAIL_USERNAME=<MailtrapのUsername>
MAIL_PASSWORD=<MailtrapのPassword>
MAIL_ENCRYPTION=null
  • 上書き保存する

以上で設定完了です。テストを実行した時のメールは、実際のメールアドレスではなく、 Mailtrap.io に届きますので、そちらで確認します。送信先に架空のメールアドレスが使えるのも便利です。


ユーザー登録コントローラーの作成

ユーザーを登録処理するコントローラーを作成します。アクティベーションが必要となるので、Laravel が事前に提供している処理は利用できません。独自のものに差し替えます。

  • app/Http/Controllers/Auth/RegisterController.php をエディターで開いて、既存のコードを削除して、以下のものに差し替える
<?php

namespace App\Http\Controllers\Auth;

use Activation;
use Mail;
use Sentinel;
use App\User;
use App\Http\Controllers\Controller;
use App\Notifications\RegisterNotify;
use Illuminate\Support\Facades\Validator;
use Illuminate\Foundation\Auth\RegistersUsers;
use Illuminate\Http\Request;

class RegisterController extends Controller
{
    /**
     * Where to redirect users after login / registration.
     *
     * @var string
     */
    protected $redirectTo = 'login';

    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware('guest');
    }

    /**
     * ユーザー登録
     */
    protected function register(Request $request)
    {
        $this->validate($request, [
            // nameは必須で、255文字まで
            'name' => 'required|max:255',
            // emailは必須で、emailの形式で、255文字までで、usersテーブル内でユニーク
            'email' => 'required|email|max:255|unique:users',
            // passwordは必須で、6文字以上255文字以下で、確認欄と一致する必要がある
            'password' => 'required|between:6,255|confirmed',
        ]);

        // 情報に問題がなければ、ユーザー登録
        $credentials = [
            'name' => $request['name'],
            'email' => $request['email'],
            'password' => $request['password'],
        ];
        $user = Sentinel::register($credentials);

        // アクティベーションを作成する
        $activation = Activation::create($user);

        // メールで送信する
        $usermodel = User::where('email', $user->email)->get()[0];
        $usermodel->notify(new RegisterNotify($activation->code));

        // メールを確認して、承認してからログインすることを表示するページへ
        return redirect($this->redirectTo)->with('info', trans('sentinel.after_register'));
    }
}
  • 上書き保存

コード内にある通知のための RegisterNotify クラスと、テスト用のメッセージがまだありません。テストコードを通すために、これらを用意します。

メッセージを作成

メッセージをハードコーディングするのを避けるために、言語ファイルを作成しておきます。

  • resources/langフォルダー内の en フォルダーを複製して、複製したフォルダー名を ja に変更
  • jaフォルダー内に sentinel.php というファイルを作成
  • sentinel.php をエディターで開いて、以下のコードを追加
<?php
return [
    // ユーザー登録関連
    'activate_title' => 'ユーザー登録を完了してください',
    'after_register' => 'ご登録いただいたメールアドレスに、登録を完了するためのリンクを書いたメールを送信しました。メールを開いて、リンクを押して、ユーザー登録を完了させたら、以下からログインしてください。',
    'register_user_title' => 'ユーザー登録',
    'register_user_name' => '',
    'register_user_intro' => 'へのユーザー登録を完了するには、以下のボタン(あるいはリンク)をクリックしてください。',
    'register_user_button' => 'ユーザーを有効にする',
    'register_user_outro' => '----',
    'notify_footer_message' => '*このメールは送信専用アドレスから送信しています。返信はできません。',
    'notify_footer_caution' => 'ボタンを押してもうまく動作しない場合は、以下のURLをコピーして、Webブラウザーのアドレス欄にペーストしてみてください。',
    'system_mail' => 'システムメール',
];
  • 英文が必要な場合は、上記と同じキーに、英語を代入したものを en フォルダーの sentinel.php に追加する
  • config/app.php をエディターで開く
  • 'locale'と'fallback_locale'の2つの値を、'en' から 'ja' に変更する

以上で完了です。以降、sentinel.phpに追加した配列を、PHPのコードからは trans('sentinel.要素名')、bladeからは@lang('sentinel.要素名')で参照できます。

通知のスタブ作成

ユーザーをアクティベーションするためのメッセージを送信させる通知を作成します。この段階では、テストを通すことを優先して中身のないスタブクラスとします。

  • ターミナルで、以下を実行して、ユーザー登録、登録完了、リマインダー、リマインダー完了の通知を作成
php artisan make:notification RegisterNotify

このままで、とりあえず指定のユーザーにメールを送信します。中身は後で実装します。

ルートの設定

コントローラーができたので、registerで呼び出したら登録するようにルートを設定します。テスト時に出てくるので、 login のルートも設定しておきます。

  • routes/web.php をエディターで開く
  • Auth::routes(); は、Laravelのauthは利用しないので削除
  • POSTメソッドのregisterで登録を発動させるので、Auth::routes() があった場所に、以下を追加(ログイン用のルートを修正 2016/11/8)
// ログイン用のルート
Route::get('login', function() {return view('auth.login', [
    'info' => session('info')
])->withErrors(session('myerror'));})->name('login');
Route::post('login', 'Auth\LoginController@login');

// ユーザー登録用のルート
Route::get('register', function() {return view('auth.register');});
Route::post('register', 'Auth\RegisterController@register');

登録後のメッセージを表示できるように、loginビューに表示領域を追加します。

  • resources/views/auth/login.blade.php をエディターで開く
  • <div class="panel-body"> という行の下に、以下を追加(エラーの部分を修正 2016/11/8)
                    @if(isset($info))
                    <div class="alert alert-info">
                        {{ $info }}
                    </div>
                    @endif

                    @include('parts.errors')

エラーのビューをJavaScriptやその他の文言に対応できるように修正します(2016/11/8追加)。

  • resources/views/parts/errors.blade.php を作成して、エディターで開く
  • 以下のコードを入力する
<!-- resources/views/parts/errors.blade.php -->

<!-- Form Error List -->
<div id="error-block" class="alert alert-danger" @if (count($errors) == 0) style="display: none;" @endif >
    <strong>以下のエラーが発生しました。</strong>
    <br>
    <ul id="error-list">
        @foreach ($errors->all() as $error)
            <li>{{ $error }}</li>
        @endforeach
    </ul>
</div>

以上で、 view から info と myerror を受け取った場合、ログイン画面にメッセージを表示します。

Registerビューの調整

必要な項目は揃っているので変更しなくても構いません。表記を変更したり、表示を日本語にしたい、独自の欄を設けたい場合などの手順です。

  • resources/views/auth/register.blade.php をエディターで開く
  • 変更したい箇所を修正する
  • 上書き保存

テスト

以上で最低限の機能が揃いました。 npm test をターミナルで実行してください。「OK (2 tests, 9 assertions)」と表示されて成功します。

また、 http://mailtrap.io に用意した Inbox の中身を確認してください。通知にあらかじめ用意されているメッセージが届きます。


アクティベーションコードを送るメール

通知時に送るメールのフォームを完成させます。すでに php artisan vendor:publish を実行しているので、必要なメールファイルが resources フォルダー内にありますので、それを編集します。

  • resources/views/vendor/notifications/email.blade.php をエディターで開いて、以下に書き換える
<!DOCTYPE html>
<html>

<head>
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

    <style type="text/css" rel="stylesheet" media="all">
        /* Media Queries */
        @media only screen and (max-width: 500px) {
            .button {
                width: 100% !important;
            }
        }
    </style>
</head>

<?php

$style = [
    /* Layout ------------------------------ */

    'body' => 'margin: 0; padding: 0; width: 100%; background-color: #F2F4F6;',
    'email-wrapper' => 'width: 100%; margin: 0; padding: 0; background-color: #F2F4F6;',

    /* Masthead ----------------------- */

    'email-masthead' => 'padding: 25px 0; text-align: center;',
    'email-masthead_name' => 'font-size: 16px; font-weight: bold; color: #2F3133; text-decoration: none; text-shadow: 0 1px 0 white;',

    'email-body' => 'width: 100%; margin: 0; padding: 0; border-top: 1px solid #EDEFF2; border-bottom: 1px solid #EDEFF2; background-color: #FFF;',
    'email-body_inner' => 'width: auto; max-width: 570px; margin: 0 auto; padding: 0;',
    'email-body_cell' => 'padding: 35px;',

    'email-footer' => 'width: auto; max-width: 570px; margin: 0 auto; padding: 0; text-align: center;',
    'email-footer_cell' => 'color: #AEAEAE; padding: 35px; text-align: center;',

    /* Body ------------------------------ */

    'body_action' => 'width: 100%; margin: 30px auto; padding: 0; text-align: center;',
    'body_sub' => 'margin-top: 25px; padding-top: 25px; border-top: 1px solid #EDEFF2;',

    /* Type ------------------------------ */

    'anchor' => 'color: #3869D4;',
    'header-1' => 'margin-top: 0; color: #2F3133; font-size: 19px; font-weight: bold; text-align: left;',
    'paragraph' => 'margin-top: 0; color: #74787E; font-size: 16px; line-height: 1.5em;',
    'paragraph-sub' => 'margin-top: 0; color: #74787E; font-size: 12px; line-height: 1.5em;',
    'paragraph-center' => 'text-align: center;',

    /* Buttons ------------------------------ */

    'button' => 'display: block; display: inline-block; width: 200px; min-height: 20px; padding: 10px;
                 background-color: #3869D4; border-radius: 3px; color: #ffffff; font-size: 15px; line-height: 25px;
                 text-align: center; text-decoration: none; -webkit-text-size-adjust: none;',

    'button--green' => 'background-color: #22BC66;',
    'button--red' => 'background-color: #dc4d2f;',
    'button--blue' => 'background-color: #3869D4;',
];
?>

<?php $fontFamily = 'font-family: Arial, \'Helvetica Neue\', Helvetica, sans-serif;'; ?>

<body style="{{ $style['body'] }}">
    <table width="100%" cellpadding="0" cellspacing="0">
        <tr>
            <td style="{{ $style['email-wrapper'] }}" align="center">
                <table width="100%" cellpadding="0" cellspacing="0">
                    <!-- Logo -->
                    <tr>
                        <td style="{{ $style['email-masthead'] }}">
                            <a style="{{ $fontFamily }} {{ $style['email-masthead_name'] }}" href="{{ url('/') }}" target="_blank">
                                {{ config('app.name') }} {{trans('sentinel.register_user_title')}}
                            </a>
                        </td>
                    </tr>

                    <!-- Email Body -->
                    <tr>
                        <td style="{{ $style['email-body'] }}" width="100%">
                            <table style="{{ $style['email-body_inner'] }}" align="center" width="570" cellpadding="0" cellspacing="0">
                                <tr>
                                    <td style="{{ $fontFamily }} {{ $style['email-body_cell'] }}">
                                        <!-- Greeting -->
                                        <h1 style="{{ $style['header-1'] }}">
                                            @if (! empty($greeting))
                                                {{ $greeting }}
                                            @else
                                                @if ($level == 'error')
                                                    Error!
                                                @else
                                                    Hello!
                                                @endif
                                            @endif
                                        </h1>

                                        <!-- Intro -->
                                        @foreach ($introLines as $line)
                                            <p style="{{ $style['paragraph'] }}">
                                                {{ $line }}
                                            </p>
                                        @endforeach

                                        <!-- Action Button -->
                                        @if (isset($actionText))
                                            <table style="{{ $style['body_action'] }}" align="center" width="100%" cellpadding="0" cellspacing="0">
                                                <tr>
                                                    <td align="center">
                                                        <?php
                                                            switch ($level) {
                                                                case 'success':
                                                                    $actionColor = 'button--green';
                                                                    break;
                                                                case 'error':
                                                                    $actionColor = 'button--red';
                                                                    break;
                                                                default:
                                                                    $actionColor = 'button--blue';
                                                            }
                                                        ?>

                                                        <a href="{{ $actionUrl }}"
                                                            style="{{ $fontFamily }} {{ $style['button'] }} {{ $style[$actionColor] }}"
                                                            class="button"
                                                            target="_blank">
                                                            {{ $actionText }}
                                                        </a>
                                                    </td>
                                                </tr>
                                            </table>
                                        @endif

                                        <!-- Outro -->
                                        @foreach ($outroLines as $line)
                                            <p style="{{ $style['paragraph'] }}">
                                                {{ $line }}
                                            </p>
                                        @endforeach

                                        <!-- Salutation -->
                                        <p style="{{ $style['paragraph'] }}">
                                            {{trans('sentinel.notify_footer_message') }}
                                        </p>

                                        <!-- Sub Copy -->
                                        @if (isset($actionText))
                                            <table style="{{ $style['body_sub'] }}">
                                                <tr>
                                                    <td style="{{ $fontFamily }}">
                                                        <p style="{{ $style['paragraph-sub'] }}">
                                                            "{{ $actionText }}"
                                                            {{trans('sentinel.notify_footer_caution')}}
                                                        </p>

                                                        <p style="{{ $style['paragraph-sub'] }}">
                                                            <a style="{{ $style['anchor'] }}" href="{{ $actionUrl }}" target="_blank">
                                                                {{ $actionUrl }}
                                                            </a>
                                                        </p>
                                                    </td>
                                                </tr>
                                            </table>
                                        @endif
                                    </td>
                                </tr>
                            </table>
                        </td>
                    </tr>

                    <!-- Footer -->
                    <tr>
                        <td>
                            <table style="{{ $style['email-footer'] }}" align="center" width="570" cellpadding="0" cellspacing="0">
                                <tr>
                                    <td style="{{ $fontFamily }} {{ $style['email-footer_cell'] }}">
                                        <p style="{{ $style['paragraph-sub'] }}">
                                            &copy; {{ date('Y') }}
                                            <a style="{{ $style['anchor'] }}" href="{{ url('/') }}" target="_blank">{{ config('app.name') }}</a>.
                                            All rights reserved.
                                        </p>
                                    </td>
                                </tr>
                            </table>
                        </td>
                    </tr>
                </table>
            </td>
        </tr>
    </table>
</body>
</html>
  • resources/views/vendor/notifications/email-plain.blade.php をエディターで開いて、以下に書き換える
<?php

if (! empty($greeting)) {
    echo $greeting, "\n\n";
} else {
    echo $level == 'error' ? 'Error!' : 'Hello!', "\n\n";
}

if (! empty($introLines)) {
    echo implode("\n", $introLines), "\n\n";
}

if (isset($actionText)) {
    echo "{$actionText}", "\n", "{$actionUrl}", "\n\n";
}

if (! empty($outroLines)) {
    echo implode("\n", $outroLines), "\n\n";
}

echo trans('sentinel.notify_footer_message'), "\n";
echo config('app.name'), trans('sentinel.system_mail'), "\n";

以上で、通知用のメール書式が設定できました。引き続き、通知を作成します。


通知(Notify)を作成

通知は、連絡先の情報を持ったモデルから notify メソッドを呼び出すことで、メッセージを送ることができる機能です。メール以外にも、データベースやSMS、Slackなどに通知ができます。通知を利用するには、該当するモデルに Notifiable トレイトを宣言します。

ユーザー登録通知を作成する

先に作成した RegisterNotify.php の中身を実装して、ユーザーに確認用のリンクを送信します。

  • app/Notifications/RegisterNotify.php を開いて、以下のようにする
<?php

namespace App\Notifications;

use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Notification;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;

class RegisterNotify extends Notification
{
    use Queueable;

    /** 認証コード*/
    private $code;

    /**
     * Create a new notification instance.
     *
     * @return void
     */
    public function __construct($code)
    {
        $this->code = $code;
    }

    /**
     * Get the notification's delivery channels.
     *
     * @param  mixed  $notifiable
     * @return array
     */
    public function via($notifiable)
    {
        return ['mail'];
    }

    /**
     * Get the mail representation of the notification.
     *
     * @param  mixed  $notifiable
     * @return \Illuminate\Notifications\Messages\MailMessage
     */
    public function toMail($notifiable)
    {
        return (new MailMessage)
            ->subject(trans('sentinel.register_user_title'))
            ->greeting($notifiable->name.trans('sentinel.register_user_name'))
            ->line(config('app.name').trans('sentinel.register_user_intro'))
            ->action(trans('sentinel.register_user_button'),
                url('activate', [base64_encode($notifiable->email), $this->code]))
            ->line(trans('sentinel.register_user_outro'));
    }
}

以上で、通知が完成です。 npm test でテストを実行して、成功することを確認してください。その後、 https://mailtrap.io を確認するとアクティベーションのためのリンクをつけたメールが届きます。HTMLとTextの中身をそれぞれ確認してみてください。



以上で、ユーザーの登録は出来上がりです。次は、アクティベーションを実装します。



前へ | 次へ

Laravel5.3でSentinelを利用する(2)MiddlewareをSentinelに対応させる

前へ | 次へ

LaravelとSentinel、Codeceptionのインストールが完了したら、次にMiddlewareをSentinelに対応させます。


はじめに

ログインなどの処理の流れは Laravel に組み込まれています。そこにSentinel用のGuardを組み込んで対応させます。

Laravelの認証は、 Guard と Provider によって実行されます。 Guard とは、ユーザーが認証済みかを判定する方法を定義するもので、 Provider は、ユーザーの情報をEloquentやデータベースなどから取り出す方法を定義するものです。

Sentinel用のこれらを作成して公開してくれていましたので、これを利用します。
GitHub - joshwhatk/sentinel-guard: Laravel Guard for Cartalyst's Sentinel

ライセンスは MIT License です。

必要なプログラムを組み込む

  • GitHub - joshwhatk/sentinel-guard: Laravel Guard for Cartalyst's Sentinel をWebブラウザーで開く
  • ウィンドウの右にある[Clone or download]をクリックして、[Download ZIP]を選択
  • ダウンロードが完了したら、ファイルを解凍する
  • Laravelのプロジェクトフォルダー内に、 app/Joshwhatk/Cent フォルダーを作成
  • 解凍したフォルダー内の src の中にある [Cent.php][CentServiceProvider.php][UserModel.php]の3つのファイルをコピーして、作成した app/Joshwhatk/Cent フォルダーに貼り付ける
  • composer.json をエディターで開く
  • "autoload"の"psr-4"の定義を以下のように修正
        "psr-4": {
            "App\\": "app/",
            "Joshwhatk\\Cent\\": "app/Joshwhatk/Cent/"
        }

以上で必要なファイルの組み込みができました。解凍したフォルダーなどは削除しても構いません。

Cent.php を5.3に対応させる

現状のままだと、いくつか機能が足りません。 GuardHelpersトレイトを Cent.php に組み込んで対応します。

  • app/Joshwhatk/Cent/Cent.php をエディターで開く
  • ファイルの上の方に、以下の use 文を追加
use Illuminate\Auth\GuardHelpers;
  • クラスの宣言内に、以下のトレイトの呼び出しを追加
    use GuardHelpers;

ユーザーモデルを作成

Sentinel のデータベースに対応したユーザーモデルを用意して、認証に組み込むための機能も追加します。

  • app/User.php をエディターで開く
  • 以下のようにコードを修正
<?php

namespace App;

use Illuminate\Notifications\Notifiable;
use Joshwhatk\Cent\UserModel;

class User extends UserModel
{
    use Notifiable;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'email',
        'password',
        'name',
        'permissions',
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'password',
    ];
}

サービスプロバイダーを登録

  • config/app.php をエディターで開く
  • $providers 配列に、以下を追加
        Joshwhatk\Cent\CentServiceProvider::class,

作成した cent という名前の Guard を設定する

  • config/auth.php を開く
  • 'guards' の定義の 'driver' を以下のように全て cent に変更する
    'guards' => [
        'web' => [
            'driver' => 'cent',
            'provider' => 'users',
        ],

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

設定を反映させる

以上、設定した内容を環境に反映させます。

  • ターミナルで以下を実行して、 composer を再構成する
composer update
  • php artisan serve でサービスを起動しているターミナルで、[control]+[C]を押して、サービスを停止
  • 改めて以下をターミナルで実行して、サービスを再開させる
php artisan serve

以上で、認証のための auth ミドルウェア が Sentinel に対応しました。 http://localhost:8000 を再読み込みして、正常に表示されることを確認してください。また、 npm test も成功します。

次は、ユーザー登録を実装します。



前へ | 次へ

Laravel5.3でSentinelを利用する(1)LaravelとSentinel、Codeceptionのインストール

次へ

完成プロジェクト→ GitHub - am1tanaka/lara5.3-sentinel at ver1.1.1


はじめに

PHPフレームワークLaravelには簡単な認証や認可ができるauthパッケージが組み込まれていますが、ユーザー登録時にメールの確認などなしにいきなり登録できてしまいます。

Sentinelは上記のような機能を持つPHPフレームワークで、Laravel5に組み込むための機能を提供してくれています。Sentinelが提供するのはロジックだけで、ビューやユーザー確認用のメールなどは自前で実装する必要がありますが、それでも手間は相当減らせます。

上記を組み合わせた環境をmac上で構築する作業メモです。完成プロジェクトはこちら→GitHub - am1tanaka/lara5.3-sentinel: Laravel5.3+Sentinelのユーザー認証サンプル


前提環境

  • Laravel5.3
  • Sentinel2.0.13以降
  • macOS Sierra 10.12.1
  • PHP5.6.19
  • MySQL5.7.16
  • composer version 1.2.1
  • Postfixを設定して、macからgmailなどを通してメール送信できる環境が構築できている
  • 記事内には登場しないが、MySQLの操作を楽にする Sequel Pro のインストールをオススメ



実装の方針

  • テスト用のフレームワーク Codeception を利用する
  • Sentinelの first_name と last_name は、 name に統一する
  • メールでの通知を Notification で実装する
  • Notification はキューに積む
    • キュードライバーは sync を使用
    • 必要になったら他のドライバーの環境を構築する方針とする
  • メール送信は、5.3の新しいMail機能を使う
    • メールドライバーは smtp を利用
    • SMTPサーバーが利用できない場合は、 Mailgun や SparkPost といったメール送信サービス用のドライバーを利用すると良い



Laravelのバージョン確認とインストール

  • macでターミナルを起動
  • プロジェクトフォルダーを作るフォルダーに移動
  • laravel -v を実行して、コマンドが見つからなかったら以下でグローバル環境にLaravelをインストールする
composer global require "laravel/installer"
  • Laravelをインストール済みだった場合、以下でバージョンを最新版にしておく
composer global update
  • 以下で、Laravelのプロジェクトを作成して、中に入る
laravel new lara5.3-sentinel
cd lara5.3-sentinel



データベースを作成する

今回のサンプルで操作するためのデータベースを作成します。

  • MySQL にログインする
mysql -u ユーザー名 -p
  • 上記でMySQLにログインできない場合は、MySQLサーバーを起動
sudo mysqld_safe
  • データベースを作成する。以下は、lara_sentinelというデータベースと、テスト用のlara_sentinel_testを作成する例
create database lara_sentinel;
create database lara_sentinel_test;
  • 操作用のユーザーを作成して、権限を与えておく。以下は、user_lara_sentというローカルホスト上のユーザーを作成する例。パスワードは任意
CREATE USER 'user_lara_sent'@'localhost' IDENTIFIED BY 'YourPassword';
  • 作成したローカルホストのuser_lara_sentユーザーに、lara_sentinelデータベースへのアクセス権限を与える
GRANT ALL PRIVILEGES ON lara_sentinel.* TO 'user_lara_sent'@'localhost';
GRANT ALL PRIVILEGES ON lara_sentinel_test.* TO 'user_lara_sent'@'localhost';
exit



Laravelの環境設定

  • Atomなどのエディターで、上記で作成したlara5.3-sentinelのプロジェクトフォルダーを開く
  • .envを開いて、各種設定を行う
    • APP_URLを、 http://localhost:8000 に変更
    • DB_DATABASEを、作成したデータベース名に変更。ここでは lara_sentinel
    • DB_USERNAMEを、作成したユーザー名に変更。ここでは、 user_lara_sent
    • DB_PASSWORDを、設定したパスワードに変更。任意に設定したパスワードを書く
    • メールについて設定する。macPostfixで送信できる場合は、以下のように設定。MAIL_FROM_ADDRESSとMAIL_FROM_NAMEは適した内容に変更のこと
MAIL_DRIVER=smtp
MAIL_HOST=localhost
MAIL_PORT=25
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS=hello@example.com
MAIL_FROM_NAME=ExampleFrom
  • config/mail.php を開く
    • 以下のように書き換え
    'from' => [
        'address' => env('MAIL_FROM_ADDRESS', 'hello@example.com'),
        'name' => env('MAIL_FROM_NAME', 'Example'),
    ],



起動テスト

Laravelの起動を試します。

  • ターミナルで、プロジェクトフォルダーから以下を実行
php artisan serve

Webブラウザーから http://localhost:8000 にアクセスして「Laravel」と表示されたら成功です。


Sentinelをインストール

Sentinel の公式ページのインストール手順に従います。

  • Laravelプロジェクトを起動し続ける場合、新しいターミナルを開いて、プロジェクトフォルダーを開く
  • プロジェクトフォルダー内から以下を実行してインストールする
composer require cartalyst/sentinel
  • インストールが完了したら、 config/app.php を開く
  • providers の配列を探して、その中に以下の行を加える
        /*
         * Sentinel Service Providers...
         */
        Cartalyst\Sentinel\Laravel\SentinelServiceProvider::class,
  • その下の aliases の配列に、以下を加える
        // Sentinel Aliases
        'Activation' => Cartalyst\Sentinel\Laravel\Facades\Activation::class,
        'Reminder'   => Cartalyst\Sentinel\Laravel\Facades\Reminder::class,
        'Sentinel'   => Cartalyst\Sentinel\Laravel\Facades\Sentinel::class,
  • 上書き保存する
  • ターミナルから以下を実行して、resourcesフォルダーにvendor関連のリソースを出力する
php artisan vendor:publish

テーブルを作成するための設定ファイルが出力されたので、 users テーブルの first_name と last_name を削除して、nameにするための変更を加えます。

  • database/migrations/2014_07_02_230147_migration_cartalyst_sentinel.php を開く
  • [Schema::create('users', ]から始まるコードを探して、以下のように修正する
        Schema::create('users', function (Blueprint $table) {
            $table->increments('id');
            $table->string('email');
            $table->string('password');
            $table->text('permissions')->nullable();
            $table->timestamp('last_login')->nullable();
            $table->string('name')->nullable();  // この辺りを修正
            $table->timestamps();

            $table->engine = 'InnoDB';
            $table->unique('email');
        });

既存のユーザーテーブルは不要なので、マイグレーションで作成されないように以下のファイルを削除します。

  • database/migrations/2014_10_12_000000_create_users_table.php
  • database/migrations/2014_10_12_100000_create_password_resets_table.php

データベースを作成します。

  • 以下をターミナルで実行
php artisan migrate
  • ここでエラーが発生したら、.envを確認してデータベースの接続情報が合っているかや、MySQLサーバーが起動しているかを確認する
  • config/cartalyst.sentinel.php をエディターで開いて、 'users' の設定を以下のように修正して、ここで作成したユーザーモデルに接続する
    'users' => [

        'model' => 'App\User',

    ],

以上でSentinelの設置は完了です。 config/cartalyst.sentinel.php にSentinelの設定があるので、必要があれば変更します。

Webブラウザーhttp://localhost:8000 を再読み込みして、エラーが発生しなければここまで成功です。


認証用のビューを作る

手間を減らすために、認証関連のビューやコントローラーを既存のauth機能から取り込みます。すべて手製で作るのであればこの手順は不要です。

  • ターミナルからプロジェクトフォルダー内で以下を実行
php artisan make:auth

http://localhost:8000 を再読み込みすると、画面の右上に認証のための[LOGIN]と[REGISTER]のリンクが追加されます。現時点では Laravel の auth 機能が実装されているので、正しく動作しません。これをSentinelに差し替えていきます。


Codeception を組み込む

テスト用フレームワークのCodeceptionを組み込みます。公式サイトはこちら
Laravel5.3 テストでテスト専用のデータベースを使う - tanaka's Programming Memo に簡単な使い方をメモしています。

  • ターミナルで以下を実行
composer require codeception/codeception --dev
composer exec codecept bootstrap
composer exec codecept run

以上で、Codeceptionの組み込み、設定ファイルの展開、テスト実行が完了します。現時点ではテスト内容がないので、「No tests executed!」と表示されれば成功です。

Codeception用の設定

Codeceptionを実行するときには、テスト用のデータベースに接続したいので、以下の通りで設定を作成します。

  • ターミナルで以下を実行して、 .env.testing という設定ファイルを作成
cp .env .env.testing
  • エディターで .gitignore を開いて、以下を追加して、テスト設定をgitから外す
.env.testing
  • .env.testing をエディターで開いて、 DB_DATABASE の項目を以下のようにテスト用に変更
DB_DATABASE=lara_sentinel_test
  • ユーザーやパスワードを変更していたら、それらも修正する

次に、Laravel5でのテスト用の設定を行います。とりあえず、Functionalテストを実施する設定です。

  • tests/functional.suite.yml をエディターで開く
class_name: FunctionalTester
modules:
    enabled:
        - Laravel5:
            environment_file: .env.testing
            run_database_migrations: true
        - \Helper\Functional

以上で、 Codeception のテストが Laravel5 に対応して、テストごとにデータベースが作り直されます(migration)。

テストを準備

開発はテストコードを書きながら行います。まずはルートを呼び出すと[Laravel]と表示されるかのテストです。

  • ターミナルで以下を実行して、テスト用のCestファイルを作成
composer exec codecept g:cest functional Open
  • tests/functional/OpenCest.php ファイルが出来上がっているので、エディターで開いて、 tryToTest メソッドを以下のように書き加える
    public function tryToTest(FunctionalTester $I)
    {
        $I->amOnPage('/');
        $I->see('Laravel');
    }
  • テストを簡単に実行するために、 package.json を設定する。package.jsonを開いて、"scripts"の設定を以下のようにする
  "scripts": {
    "prod": "gulp --production",
    "dev": "gulp watch",
    "test": "composer exec codecept run"
  },
  • 以下でテストを実行できる
npm test

以上で、Codeceptionの組み込みは完了です。Codeceptionでのテストは、テスト用のデータベース上で実施され、毎回マイグレーションし直すので、まっさらな状態から開始します。

エラーが発生する場合は、データベースの設定が間違えている可能性があるので、 .env.testing のデータベース関連の設定を見直してください。



次へ

Laravel5.3 で auth を作成した時に変更される内容

Laravel5.3で php artisan make:auth を実行すると、どこが変わるかを確認しました。

routes/web.php

以下のルート設定が routes/web.php ファイルに追加されます。

Auth::routes();

Route::get('/home', 'HomeController@index');

追加されるファイル

以下のファイルがプロジェクトに追加されます。

  • app/Http/Controllers/HomeController.php
  • resources/views/auth/login.blade.php
  • resources/views/auth/passwords/email.blade.php
  • resources/views/auth/passwords/reset.blade.php
  • resources/views/auth/register.blade.php
  • resources/views/home.blade.php
  • resources/layouts/app.blade.php

まとめ

artisan の make:auth で追加されるのは、/home ページのためのルートとコントローラーと、認証関連のビューでした。ミドルウェアなどは、 auth を実行しなくても、あらかじめ Laravel5.3 をインストールした段階で、 vendorフォルダー下に作成されていました。

既存のものを書き換えるのは依存関係を追うのが大変なので、 Sentinel を組み込む場合は、新規にミドルウェアを作成した方が良さそうです。うまくいったら、追記します。

Laravel5.3 テストでテスト専用のデータベースを使う

(submitFormでは、フォームを指定すべきなのがわかりづらい例になっていたので修正 2016/11/1)

Laravelアプリの開発時に、テストする時とそうでない時で、別のデータベースを使うようにする方法です。これをやっておけば、テスト時に好き勝手にデータベースをいじれるので便利です。

PHP 用のテストフレームワークである Codeception を導入すると、テスト時に使用する環境設定ファイルを指定できるので、そこでデータベースの情報を変更できます。 Codeception は Laravel を始めとする様々なフレームワークに対応していて導入しやすく、テスト用の機能も充実しているので導入して損はありません。

Laravel5.3でプロジェクトを作成して、 Codeception を組み込んで、データベースのテストを行うまでの簡単な流れです。

前提

  • macOS Sierra 10.12
  • PHP 5.6.19
  • MySQL 5.7.16
  • Laravel 5.3
  • Componser 1.2.1

以上はインストール済みとします。


Laravelプロジェクトと Codeception の設定

  • ターミナルを起動して、プロジェクトを作成するフォルダーを開く
  • 以下で、プロジェクトを作成。プロジェクト名は適宜変更のこと
laravel new lara53-codeception
cd lara53-codeception
  • 続けて、 Codeception を組み込む
composer require codeception/codeception --dev

Codeceptionのセットアップ

以下を実行することで、Codeception のセットアップができます。

composer exec codecept bootstrap

これにより、 tests ディレクトリーと設定ファイル[codeception.yml]が作成されます。加えて、Acceptanceテスト(実際のWebブラウザーを使ったテスト), Functionalテスト(実際のWebブラウザーは使わない機能テスト), Unitテスト(単体テスト) の3つのスイート(suites)用の設定ファイルも作成されます。

この時点で、以下でテストが動きます。

composer exec codecept run

まだテスト内容がないので、「No tests executed!」と表示されます。


データベースを準備

MySQLを起動していなかったら、新しいターミナルを開いて、以下で起動します。

sudo mysqld_safe

Laravelプロジェクトのフォルダーにいるターミナルで、以下でテスト用のデータベースを2つ作成します。

  • 以下で、MySQLに接続
mysql -u root -p
  • パスワードを入力
  • 以下で、テスト用と、通常用のデータベースの2つを作成
create database lara53_codeception;
create database lara53_codeception_test;
  • それぞれのアクセス用のユーザーを作成
create user
    'lara53_code'@'localhost' identified by 'YourPassword1',
    'lara53_code_test'@'localhost' identified by 'YourPassword2';
  • それぞれのデータベースにアクセス権を設定
GRANT ALL ON lara53_codeception.* TO 'lara53_code'@'localhost';
GRANT ALL ON lara53_codeception_test.* TO 'lara53_code_test'@'localhost';

設定を作成

テスト用の環境ファイルを用意するために、以下で .env を複製します。

cp .env .env.testing

.env.testing のデータベース設定をテスト専用のものにしておけば、テスト時はテスト専用に作ったデータベース上でテストができるので、テストと他の作業のデータを切り離すことができます。

  • .gitignore を開いて、 .env.testing を追加する
  • .env をエディターで開いて、通常の利用データベースへの接続を設定する。以下、このページの例に沿った内容。適宜、自分の環境の値に変更のこと
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=lara53_codeception
DB_USERNAME=lara53_code
DB_PASSWORD=YourPassword1
  • 上書き保存する
  • .env.testing をエディターで開いて、通常の利用データベースへの接続を設定する。以下、このページの例に沿った内容。適宜、自分の環境の値に変更のこと
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=lara53_codeception_test
DB_USERNAME=lara53_code_test
DB_PASSWORD=YourPassword2
  • APP_ENV を testing にしておく
  • 上書き保存

データベースを作成

簡単に動作を試すために、ログイン機能を実装して、それでテストをしてみましょう。以下で、ユーザー登録できるようにします。

php artisan make:auth

http://localhost:8000/ をリロードしたり、開くと、右上に LOGIN と REGISTER のリンクが表示されます。続いて、以下でデータベースを作成します。

php artisan migrate

以上でできるのは、 .env で定義されたデータベースに対してです。以下で、登録状況を表示してみましょう。

mysql -u root -p
<rootのパスワードを入力>
use lara53_codeception;
show tables;

以上で、[migrations][password_resets][users]の3つのテーブルが作成されていることが確認できます。念のため、テスト用のデータベースにはまだテーブルが登録されていないことを確認しましょう。

use lara53_codeception_test;
show tables;

こちらはまだ作成していないので、「Empty set」と表示されます。 exit で mysql から抜けます。


通常のユーザーを登録しておく

  • http://localhost:8000 を開いたら、[REGISTER]を押す
  • 項目を入力して、ユーザーを登録する。メールアドレスは仮のもので良い

テスト用の設定を作成

Codeception で Laravel5 のテストが動くように設定をします。Codeception には以下のようなテスト方法があります。

  • Webブラウザーの動作を模して機能のテストを行う Functionalテスト
  • Seleniumを使って実際にWebブラウザー上で機能のテストを行う Acceptance テスト
  • PHPの関数ベースで単体テストを行う Unit テスト
  • ステータスレスのWebAPIのテストを行う API テスト
  • などなど

ここでは、 Functional テストで、テスト用のデータベースへのユーザー登録を試します。

Functionalテストの設定

Laravel5 - Codeception - Documentation を参考に設定を作成します。

  • tests/functional.suite.yml をエディターで開く
  • 以下のように設定する
class_name: FunctionalTester
modules:
    enabled:
        - Laravel5:
            environment_file: .env.testing
            run_database_migrations: true
        - \Helper\Functional
  • 上書き保存する

テストを作成する

04-FunctionalTests - Codeception - Documentation を参考にテストを作成します。

  • ターミナルから、以下を実行
composer exec codecept g:cest functional User
  • tests/functional/UserCest.php ができるので、エディターで開く(Cestとは、 Codeception のテスト用のファイルのこと)
  • tryToTest()メソッドに、以下のコードを追加
    public function tryToTest(FunctionalTester $I)
    {
        // ユーザー数が0であることを確認する
        \PHPUnit_Framework_Assert::assertEquals(0, App\User::all()->count());

        // ユーザー登録ページを表示
        $I->amOnPage('/register');
        // 必要な情報を設定して、ユーザー登録フォームのsubmitを押す(2016/11/1に変更)
        $I->submitForm('#registerUserForm', [
            'name' => 'TestUser',
            'email' => 'test@test.com',
            'password' => 'testtest',
            'password_confirmation' => 'testtest'
        ]);
        // ユーザーの登録に成功したら、以下のメッセージが表示される
        $I->see('You are logged in!');

        // ユーザー数が増えて1になっていることを確認する
        \PHPUnit_Framework_Assert::assertEquals(1, App\User::all()->count());
    }

submitFormで登録フォームを指定できるようにIDを追加します。

  • resources/views/auth/register.blade.php をエディターで開く
  • <form から始まる行を探して、以下のようにID属性を追加する
                    <form id="registerUserForm" class="form-horizontal" role="form" method="POST" action="{{ url('/register') }}">

以上で、テスト用のデータベースにユーザーを登録したことが確認できます。

通常のデータベースに変更がないことを確認する

通常のデータベースの中身を確認して、テストによる影響を受けていないことを確認します。ターミナルで以下を入力します。

mysql -u root -p
<ルートパスワードを入力>
use lara53_codeception;
select * from users;

データに変更がないことが確認できるはずです。


まとめ

以上で、 Laravel5.3 で Codeception を使ったテストが動くようになりました。Functionalテストで使える関数は以下で調べてください。

また、PHPUnitにあるアサーションは、 \PHPUnit_Framework_Assert::assertTrue(true); のようにすれば利用できます。PHPUnitアサーションは以下で調べてください。

CodeceptionのQuick Startをやってみる

PHP用のテストフレームワーク Codeception を使ってみます。Laravelのテストで .env を切り替える方法を調べると、片っ端から Codeception が使われていたので導入しようと思います。

公式ページ

Codeception

ダウンロードと設定

基本的な手順はこちらに載っています。→ Quick Start Codeception

利用したいプロジェクトフォルダーで以下を実行します。

composer require "codeception/codeception"
alias codecept='./vendor/bin/codecept'

インストール

以下で、テストに必要な環境を生成します。

codecept bootstrap

設定ファイルの codeception.yml や tests フォルダーが出来上がります。

テストの作成

最初の受け入れテスト(acceptance test)を作成しましょう。受け入れテストは、ユーザーがページを訪れる操作をエミュレートします。

codecept generate:cept acceptance Welcome

Codeceptionのシナリオテストのことを、 Cept と呼びます。

ここまで出来たら、最初のテストが実行できます。以下でテストを走らせましょう。

codecept run

最初に作成されるテストには、チェック項目がないのでテストは成功します。

テストファイルの編集

tests/acceptance/WelcomeCept.php に出力されたテストファイルを以下のように編集しましょう。

<?php
$I = new AcceptanceTester($scenario);
$I->wantTo('ページにアクセスできるか確かめます');
$I->amOnPage('/');
$I->see('tanaka\'s Programming Memo');

上書き保存をしたら、テストを動かしてみましょう。

codecept run

これは失敗します。アクセス先のURLを設定していないからです。

テストの設定ファイルを作成する

tests/acceptance.suite.yml を開いて、以下のように編集して、 URL を設定します。

class_name: AcceptanceTester
modules:
    enabled:
        - PhpBrowser:
            url: http://am1tanaka.hatenablog.com/
        - \Helper\Acceptance

保存をしてテストをしましょう。

codecept run

今度は成功します。


あとは、動かしたい環境に応じた使い方を調べていきましょう。