RitoLabo

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

  • 公開:
  • 更新:
  • カテゴリ: PHP Laravel
  • タグ: Laravel,PHPUnit

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

アジェンダ
  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]ソースコード