既存の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テーブルが空となり、毎回同じ条件でテストを実行できます。
メルマガ購読の申し込みはこちらから。