既存のDBのそれぞれのテーブルにおいて、migrationファイルやfactoryファイルが揃ったところで、phpunitのテストを作成して実行してみましょう。
テストDBの作成
テストDBは、phpunitのためだけのDBとなるゆえに、ブラウザでアクセスする本DBとは違うDBを作成します。つまり、開発サイトでは、プロジェクト1つに対して2つのDBを持つことになります。
本DBは、mysqlで、テストのDBには、sqliteという設定がドキュメントでも一般のLaravelの記事でも書かれていますが、私はテストといえども、本DBもテストDBも同じmysqlを使用することを勧めます。条件をまったく同じとしたいからです。
まず、mysqlのコマンドで、テストDB(demo_test)を作成します。
$ echo "create database demo_test" | mysql -u root -p Query OK, 1 row affected (0.00 sec)
次に、config/database.phpをエディターで開いて、mysqlのコネクションをコピーして、mysql_testのコネクションを作成します。
use Illuminate\Support\Str;
return [
....
'connections' => [
...
'mysql' => [
'driver' => 'mysql',
'url' => env('DATABASE_URL'),
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', '3306'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'unix_socket' => env('DB_SOCKET', ''),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'prefix_indexes' => true,
'strict' => true,
'engine' => null,
'options' => extension_loaded('pdo_mysql') ? array_filter([
PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
]) : [],
],
'mysql_test' => [
'driver' => 'mysql',
'url' => env('DATABASE_URL'),
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', '3306'),
'database' => 'demo_test',
'username' => 'root',
'password' => 'secret',
'unix_socket' => env('DB_SOCKET', ''),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'prefix_indexes' => true,
'strict' => true,
'engine' => null,
'options' => extension_loaded('pdo_mysql') ? array_filter([
PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
]) : [],
],
...
mysql_testにおいて編集した項目は、database、username、passwordです。env()を使用せずに、固定としています。必要なら他の項目も同様に編集してください。それから、usernameに指定するmysqlのユーザーは必ず、drop table, create table, truncateのsql文と実行できる権限を持つユーザーである必要があります。それゆえに、ここではrootのmysqlユーザーを使用しています。
次に、テーブル作成のartisanコマンドを実行して、テストDBにテーブルを作成します。前回で作成したmigrationファイルがここで役立ちます。
$ php artisan migrate:fresh --database=mysql_test Dropped all tables successfully. Migration table created successfully. Migrating: 2014_10_12_000000_create_users_table Migrated: 2014_10_12_000000_create_users_table (0.03 seconds) Migrating: 2014_10_12_100000_create_password_resets_table Migrated: 2014_10_12_100000_create_password_resets_table (0.02 seconds) Migrating: 2019_08_19_000000_create_failed_jobs_table Migrated: 2019_08_19_000000_create_failed_jobs_table (0.01 seconds)
必ず、–databaseでmysql_testのコネクションを指定ください。指定しないと、本DBの方が空となってしまうので注意を!
phpunitの設定
テストDBをテストの実行で使用するには、phpunit.xmlの編集が必要です。
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="./vendor/phpunit/phpunit/phpunit.xsd"
backupGlobals="false"
backupStaticAttributes="false"
bootstrap="vendor/autoload.php"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false">
<testsuites>
<testsuite name="Unit">
<directory suffix="Test.php">./tests/Unit</directory>
</testsuite>
<testsuite name="Feature">
<directory suffix="Test.php">./tests/Feature</directory>
</testsuite>
</testsuites>
<filter>
<whitelist processUncoveredFilesFromWhitelist="true">
<directory suffix=".php">./app</directory>
</whitelist>
</filter>
<php>
<server name="APP_ENV" value="testing"/>
<server name="BCRYPT_ROUNDS" value="4"/>
<server name="CACHE_DRIVER" value="array"/>
<server name="DB_CONNECTION" value="mysql_test"/>
<server name="MAIL_DRIVER" value="array"/>
<server name="QUEUE_CONNECTION" value="sync"/>
<server name="SESSION_DRIVER" value="array"/>
</php>
</phpunit>
DB_CONNECTIONをmysql_testと指定しています。
さて、これでphpunitを実行できます。vendor/bin/phpunitは、このプロジェクトでインストールされたバージョンのphpunitなので、必ずそのパスを使用してください。
$ vendor/bin/phpunit PHPUnit 8.5.2 by Sebastian Bergmann and contributors. .. 2 / 2 (100%) Time: 335 ms, Memory: 16.00 MB OK (2 tests, 2 assertions)
OKがテスト成功、という意味です。
RefreshDatabaseトレイト
先のphpunitの実行では、データベースのテストは含まれていません。作成してみましょう。
$php artisan make:test --unit UserTest Test created successfully.
この実行で、tests/Unit/UserTest.phpのファイルが作成されますが、それを以下のように編集します。
namespace Tests\Unit;
// use PHPUnit\Framework\TestCase // Laravel 6.xで生成されるが、コメントして以下を追加
use Tests\TestCase;
use Illuminate\Foundation\Testing\RefreshDatabase; // 追加
use App\User;
class UserTest extends TestCase
{
use RefreshDatabase;
public function test_create_a_user()
{
factory(User::class)->create(); // usersのDBテーブルにレコードを1つ作成
$this->assertCount(1, User::all()); // すべてのレコードを取得してレコード数が1であることを確認
}
}
実行してみましょう。
$ vendor/bin/phpunit --filter UserTest PHPUnit 8.5.2 by Sebastian Bergmann and contributors. . 1 / 1 (100%) Time: 511 ms, Memory: 22.00 MB OK (1 test, 1 assertion)
成功ですね。
このテストは何回実行しても成功となります。
$ vendor/bin/phpunit --filter UserTest PHPUnit 8.5.2 by Sebastian Bergmann and contributors. . 1 / 1 (100%) Time: 511 ms, Memory: 22.00 MB OK (1 test, 1 assertion) $ vendor/bin/phpunit --filter UserTest PHPUnit 8.5.2 by Sebastian Bergmann and contributors. . 1 / 1 (100%) Time: 511 ms, Memory: 22.00 MB OK (1 test, 1 assertion)
試しに、use RefershDatabaseをコメントして実行してみてください。
$ vendor/bin/phpunit --filter UserTest PHPUnit 8.5.2 by Sebastian Bergmann and contributors. . 1 / 1 (100%) Time: 511 ms, Memory: 22.00 MB OK (1 test, 1 assertion) $ vendor/bin/phpunit --filter UserTest PHPUnit 8.5.2 by Sebastian Bergmann and contributors. F 1 / 1 (100%) Time: 324 ms, Memory: 18.00 MB There was 1 failure: 1) Tests\Unit\UserTest::testExample Failed asserting that actual size 2 matches expected size 1. /vol1/usr/www/repos/repos/l6x/tests/Unit/UserTest.php:23 FAILURES! Tests: 1, Assertions: 1, Failures: 1.
1回名は成功ですが、2回目は失敗です.なぜなら、RefereshDatabaseなしではレコードは追加されていくばかりだからです。RefereshDatabaseのトレイトを使用することによりDBテーブルが空となり、毎回同じ条件でテストを実行できます。
メルマガ購読の申し込みはこちらから。