1. Home
  2. PHP
  3. Laravel
  4. LaravelでPHPUnitを使ったユニットテストを書く為のサンプルアプリケーション作成

LaravelでPHPUnitを使ったユニットテストを書く為のサンプルアプリケーション作成

  • 公開日
  • 更新日
  • カテゴリ:Laravel
  • タグ:Laravel,PHPUnit
LaravelでPHPUnitを使ったユニットテストを書く為のサンプルアプリケーション作成

この記事は、Laravel と PHPUnit を用いてユニットテストを書く為のサンプルアプリケーションの作成記事です。

Contents

  1. 開発環境
  2. アプリケーションの作成
  3. マイグレーション作成
  4. シーダ作成
  5. マイグレーション&シーディング実行
  6. モデル作成
  7. データベース操作クラスの作成
  8. サービスプロバイダ定義
  9. コントローラ作成

開発環境

今回の開発環境は以下の通りです。

  • PHP 7.2
  • MySQL 8.0
  • Laravel 5.8
  • Composer 1.8.4

Laravel のルートディレクトリを「laravel/」とします。

アプリケーションの作成

  • 今回は名前を管理するアプリケーションを作成します。
  • テーブル名は Members とします。

マイグレーション作成

まずは DB へ、テーブル作成と共にデータを注入します。 以下の artisan コマンドを叩いてマイグレーションファイルを生成します。

# Laravel ルートディレクトリへ移動
cd /path/to/laravel

# マイグレーション生成
php artisan make:migration create_member_table  --create=member

# 実行結果
[demo@localhost laravel]$ php artisan make:migration create_member_table  --create=member
Created Migration: 2019_04_27_062511_create_member_table

laravel/database/migrations 配下に yyyy_mm_dd_HHiiss_create_members_table.php が生成されます。

laravel/
   ├─ database
       ├─ migrations
           └─ xxxx_create_member_table.php

今回は名前を持つだけのシンプルなテーブルにしました。マイグレーションは以下に定義します。

laravel/database/migrations/xxxx_create_members_table.php
<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateMemberTable extends Migration
{
    public function up()
    {
        Schema::create('member', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('name', 255)->comment('名前');
            $table->timestamps();
        });
    }

    public function down()
    {
        Schema::dropIfExists('member');
    }
}

シーダ作成

次はシーダを定義して初期投入データを作成します。 以下の artisan コマンドを叩いてシーダーファイルを生成します。

# Laravel ルートディレクトリへ移動
cd /path/to/laravel

# シーダ生成
php artisan make:seeder MembersTableSeeder

# 実行結果
[demo@localhost laravel]$ php artisan make:seeder MembersTableSeeder
Seeder created successfully.

laravel/database/seeds 配下に MembersTableSeeder.php が生成されます。

laravel/
   ├─ database
       ├─ seeds
           └─ MembersTableSeeder.php

初期データは以下のように定義しました。

laravel/database/seeds/MembersTableSeeder.php
<?php

use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;

class MembersTableSeeder extends Seeder
{
    public function run()
    {
        DB::table('members')->insert([
            [ 'name' => 'member_001' ],
            [ 'name' => 'member_002' ],
            [ 'name' => 'member_003' ],
            [ 'name' => 'member_004' ],
            [ 'name' => 'member_005' ],
            [ 'name' => 'member_006' ],
            [ 'name' => 'member_007' ],
            [ 'name' => 'member_008' ],
            [ 'name' => 'member_009' ],
            [ 'name' => 'member_010' ]
        ]);
    }
}

10 件のレコードを挿入しています。

そして、DatabaseSeeder に追加します。

laravel/database/seeds/DatabaseSeeder.php
<?php

use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    public function run()
    {
        $this->call(MembersTableSeeder::class);
    }
}

シーダを作成したら Composer のオートローダを再生成する必要があるので、以下の composer コマンドを叩きます。

# Laravel ルートディレクトリへ移動
cd /path/to/laravel

# オートローダを再生成
composer dump-autoload

# 実行結果
[demo@localhost laravel]$ composer dump-autoload
Generating optimized autoload files> Illuminate\Foundation\ComposerScripts::postAutoloadDump
> @php artisan package:discover --ansi
Discovered Package: beyondcode/laravel-dump-server
Discovered Package: fideloper/proxy
Discovered Package: laravel/tinker
Discovered Package: nesbot/carbon
Discovered Package: nunomaduro/collision
Package manifest generated successfully.
Generated optimized autoload files containing 3521 classes

マイグレーション&シーディング実行

データ部分の定義が完了したので、マイグレーションとシーディングを実行します。

# Laravel ルートディレクトリへ移動
cd /path/to/laravel

# マイグレーションとシーディングを実行
php artisan migrate:refresh --seed

# 実行結果
[demo@localhost laravel]$ php artisan migrate:refresh --seed
Migrating: xxxx_create_members_table
Migrated:  xxxx_create_members_table
Seeding: MembersTableSeeder
Database seeding completed successfully.

MySQL にログインしてテーブルの作成・データの挿入を確認できました。

mysql> select id,name from members;
+----+------------+
| id | name       |
+----+------------+
|  1 | member_001 |
|  2 | member_002 |
|  3 | member_003 |
|  4 | member_004 |
|  5 | member_005 |
|  6 | member_006 |
|  7 | member_007 |
|  8 | member_008 |
|  9 | member_009 |
| 10 | member_010 |
+----+------------+

モデル作成

今回は操作に EloquentORM を用いるのでモデルを生成します。 以下の artisan コマンドを叩いてモデルクラスを生成します。

# Laravel ルートディレクトリへ移動
cd /path/to/laravel

# モデル生成
php artisan make:model Member

# 実行結果
[demo@localhost laravel]$ php artisan make:model Member
Model created successfully.

laravel/app 配下に Member.php が生成されます。

laravel/
   ├─ app
       └─ Member.php

今回は生成されたデフォルトのままで使用するのでモデルクラスはこのままで OK です。

データベース操作クラスの作成

実際に DB とやり取りをしてデータベースを操作するクラス(DAO)を作成します。 Repository パターンで作成していきます。

laravel/app 配下に repositories ディレクトリを作成し、その中にクラスを作成します。

まずはインターフェイスを作成します。

laravel/app/repositories/MembersRepositoryInterface.php
<?php
declare(strict_types=1);

namespace App\Repositories;

interface MembersRepositoryInterface
{
    public function all(): array;

    public function get(int $id): array;

    public function insert(string $name): void;

    public function update(int $id, string $name): void;

    public function delete(int $id): void;
}

データベース操作の基本 CRUD を定義しています。 今回は Eloquent を使いこそしますが Repository パターンで運用するので、SELECT 系はモデルやコレクション等では返さず、 純粋な配列で返すように制約を設けています。

次に、このインターフェイスを実装します。

laravel/app/repositories/MembersEloquentRepository.php
<?php
declare(strict_types=1);

namespace App\Repositories;

use App\Member;

class MembersEloquentRepository implements MembersRepositoryInterface
{
    public function all(): array
    {
        return Member::All()->toArray();
    }

    public function get(int $id): array
    {
        return Member::where('id', $id)->first()->toArray();
    }

    public function insert(string $name): void
    {
        $member = new Member;
        $member->name = $name;
        $member->save();
    }

    public function update(int $id, string $name): void
    {
        $member = Member::find($id);
        $member->name = $name;
        $member->save();
    }

    public function delete(int $id): void
    {
        $member = Member::find($id);
        $member->delete();
    }
}

サービスプロバイダ定義

データベース操作クラスを DI(依存性の注入)できるようにします。 以下の artisan コマンドを叩いてサービスプロパイダを生成します。

# Laravel ルートディレクトリへ移動
cd /path/to/laravel

# サービスプロパイダ生成
php artisan make:provider RepositoryServiceProvider

# 実行結果
[demo@localhost laravel]$ php artisan make:provider RepositoryServiceProvider
Provider created successfully.

laravel/app/Providers 配下に RepositoryServiceProvider.php が生成されます。

laravel/
   ├─ app
       ├─ Providers
           ├─ RepositoryServiceProvider.php

これを以下に定義します。

laravel/app/Providers/RepositoryServiceProvider.php
<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;

class RepositoryServiceProvider extends ServiceProvider
{
    public function register()
    {
        $this->app->bind(
            \App\Repositories\MembersRepositoryInterface::class,
            \App\Repositories\MembersEloquentRepository::class
        );
    }

    public function boot()
    {
        //
    }
}

最後に、サービスプロパイダを登録します。

laravel/config/app.php
'providers' => [
    /*
     ...(省略)...
     */

    // 追加
    App\Providers\RepositoryServiceProvider::class,

],

コントローラ作成

コントローラを作成します。以下の artisan コマンドを叩いてコントローラを生成します。

# Laravel ルートディレクトリへ移動
cd /path/to/laravel

# コントローラ生成
php artisan make:controller SampleController

# 実行結果
[demo@localhost laravel]$ php artisan make:controller SampleController
Controller created successfully.

コントローラを以下に定義します。

laravel/app/Http/Controllers/SampleController.php
<?php
declare(strict_types=1);

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Repositories\MembersRepositoryInterface AS MembersRepository;

class SampleController extends Controller
{
    protected $Members;

    public function __construct(MembersRepository $Members)
    {
        $this->Members = $Members;
    }

    public function index()
    {
        // $this->Members->all()
        // $this->Members->get(1)
        // $this->Members->insert('member_011');
        // $this->Members->update(11, 'member_11');
        // $this->Members->delete(11);
    }
}

最後に、ルーティングを記述します。

laravel/Routes/web.php
Route::get('/sample', 'SampleController@index');

まずはここまでです。
コントローラの index メソッド内にあるコメントアウトを外せばデータベース操作が行われます。
あとは記事の進行とともにここのソースや手順も追加していきます。

[Github]ソースコード

Author

rito

  • Backend Engineer
  • Tokyo, Japan
  • PHP 5 技術者認定上級試験 認定者
  • 統計検定 3 級