2022-06-23
Laravel パッケージ開発でのテスト環境整備
Laravel パッケージ開発でテストを行うための環境整備手順を紹介します。
Orchestra Testbench の導入
Orchestra Testbench を利用して Laravel のテスト環境を整備します。
基本的に最新版を入れれば問題ありませんが、古いバージョンの Laravel をベースにテスト環境を構築したい場合、それに対応するバージョンを指定する必要があります。
Laravel と Testbench のバージョン対応についてはドキュメントを参照してください。
console
composer require --dev orchestra/testbench
モジュールの中身は以下のようになっています。testbench-core/laravel
ディレクトリがテスト環境のベースとなります。
vendor/orchestra
├── testbench
└── testbench-core
├── composer.json
├── create-sqlite-db
├── drop-sqlite-db
├── laravel
│ ├── app
│ ├── bootstrap
│ ├── composer.json
│ ├── config
│ ├── database
│ ├── lang
│ ├── migrations
│ ├── public
│ ├── resources
│ ├── routes
│ ├── server.php
│ ├── storage
│ └── vendor
├── src
└── testbench
PHP Unit の導入
モジュールをインストールします。
console
composer require --dev phpunit/phpunit
以下の内容で phpunit.xml
をディレクトリ直下に配置します。
<testsuites>
および <php>
タグの内容は必要に応じて書き換え・削除してください。
phpunit.xml
<?xml version="1.0" encoding="UTF-8"?>
<phpunit
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
bootstrap="vendor/autoload.php"
backupGlobals="false"
backupStaticAttributes="false"
colors="true"
verbose="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd"
>
<coverage>
<include>
<directory suffix=".php">src/</directory>
</include>
</coverage>
<testsuites>
<testsuite name="Unit">
<directory suffix="Test.php">./tests/Unit</directory>
</testsuite>
<testsuite name="Feature">
<directory suffix="Test.php">./tests/Feature</directory>
</testsuite>
</testsuites>
<php>
<env name="DB_CONNECTION" value="testing"/>
<env name="APP_KEY" value="base64:2fl+Ktvkfl+Fuz4Qp/A75G2RTiWVA/ZoKZvp6fiiM10="/>
</php>
</phpunit>
テストディレクトリ・テストファイルの作成
ディレクトリ構成例
上述の phpunit.xml
に沿って構成すると以下のようになります。
tests
├── Feature
├── Unit
└── TestCase.php
TestCase.php を記述
namespace
およびロードする ServiceProvider
は置き換えてください。
TestCase.php
<?php
namespace Ryoluo\SailSsl\Tests;
use Ryoluo\SailSsl\SailSslServiceProvider;
class TestCase extends \Orchestra\Testbench\TestCase
{
public function setUp(): void
{
parent::setUp();
// additional setup
}
protected function getPackageProviders($app)
{
return [
SailSslServiceProvider::class,
];
}
protected function getEnvironmentSetUp($app)
{
// perform environment setup
}
protected function tearDown(): void
{
// do something before tear down
parent::tearDown();
}
}
getPackageProviders()
メソッドでパッケージのサービスプロバイダを読み込ませます。- 各テストの実行前に操作を行いたい場合、
setUp()
メソッドを利用して任意の処理を実行することができます。 - また、テスト終了後に処理を行いたい場合は
tearDown()
メソッドを利用できます。
TestCase.php の記述例
自身が開発した sail-ssl パッケージのテストでは Laravel Sail がインストールされた環境が必要であったため、テスト実行前に Laravel Sail のインストールコマンドを呼び出し、テスト実行後には生成されたファイルを削除する処理を記述しています。
任意のファサードを読み込んだり、$this->app
でテスト用の Laravel アプリにアクセスしたりすることができます。
TestCase.php
<?php
namespace Ryoluo\SailSsl\Tests;
use Ryoluo\SailSsl\SailSslServiceProvider;
use Laravel\Sail\SailServiceProvider;
use Illuminate\Support\Facades\Artisan;
class TestCase extends \Orchestra\Testbench\TestCase
{
public function setUp(): void
{
parent::setUp();
$this->generateFiles();
Artisan::call('sail:install', ['--with' => 'mysql']);
}
private function generateFiles()
{
$env = fopen($this->app->basePath('.env'), 'w');
fclose($env);
$phpunit = fopen($this->app->basePath('phpunit.xml'), 'w');
fclose($phpunit);
}
protected function getPackageProviders($app)
{
return [
SailServiceProvider::class,
SailSslServiceProvider::class,
];
}
protected function tearDown(): void
{
$this->deleteFiles();
parent::tearDown();
}
private function deleteFiles()
{
unlink($this->app->basePath('.env'));
unlink($this->app->basePath('phpunit.xml'));
if (file_exists($this->app->basePath('docker-compose.yml'))) {
unlink($this->app->basePath('docker-compose.yml'));
}
if (file_exists($this->app->basePath('nginx/templates/default.conf.template'))) {
unlink($this->app->basePath('nginx/templates/default.conf.template'));
rmdir($this->app->basePath('nginx/templates'));
rmdir($this->app->basePath('nginx'));
}
}
}
テストの記述
上述の TestCase.php
を継承します。(Laravel でのテストの書き方については割愛します)
以下はサンプルですので、namespace
等は適宜置き換えてください。
InstallCommandTest.php
<?php
namespace Ryoluo\SailSsl\Tests\Feature;
use Ryoluo\SailSsl\Tests\TestCase;
class InstallCommandTest extends TestCase
{
public function test_execute_install_command_successfully()
{
$this->artisan('sail-ssl:install')
->expectsOutput('Nginx container successfully installed in Docker Compose.')
->assertSuccessful();
$dockerCompose = file_get_contents($this->app->basePath('docker-compose.yml'));
$nginxStub = file_get_contents('stubs/nginx.stub');
$volumeStub = file_get_contents('stubs/volume.stub');
$this->assertTrue(str_contains($dockerCompose, $nginxStub));
$this->assertTrue(str_contains($dockerCompose, $volumeStub));
}
}
テストディレクトリのロード&テスト実行
最後にテストディレクトリをロードし、テストを実行します。
package.json
{
...,
"autoload": {},
"autoload-dev": {
"psr-4": {
"Ryoluo\\SailSsl\\Tests\\": "tests/"
}
}
}
console
composer dump-autoload
./vendor/bin/phpunit
パッケージを公開する場合
.gitattributes
でテスト関連ファイルを出力対象外としましょう。
.gitattributes
/tests export-ignore
phpunit.xml export-ignore
参考
- https://laravelpackage.com/
- https://github.com/orchestral/testbench
- https://laravel.com/docs/9.x/packages (https://readouble.com/laravel/9.x/ja/packages.html)