Laravel 5.の通常のように、データベース接続の詳細を含む.env
ファイルがあります。これらをテスト用にオーバーライドしたいのですが、phpunit.xml
でできます。ただし、これを行うと、環境設定、特にパスワードをコミットしないという.env
の哲学に反するようです。
.env.testing
のようなものを用意し、phpunit.xml
からそれを読み取るように指示することは可能ですか?
_.env
_を_.env.testing
_にコピーし、_.env.testing
_ファイルを編集し、_APP_ENV
_パラメーターを変更して、このように_APP_ENV=testing
_を指定します。あなたの設定はこの新しいファイルに
新しい_.env.testing
_ファイルを作成したくない場合は、必要な値を使用して、phpセクションの_phpunit.xml
_に変数を指定する必要があります。
_<php>
<env name="APP_ENV" value="testing"/>
<env name="CACHE_DRIVER" value="array"/>
<env name="SESSION_DRIVER" value="array"/>
<env name="QUEUE_DRIVER" value="sync"/>
<env name="DB_CONNECTION" value="sqlite"/>
<env name="DB_DATABASE" value="testing"/>
</php>
_
名前セクションでキー値を使用し、値セクションでそのキーの値を使用するだけです。
この例では、phpunitを指定して、testingという名前のsqliteデータベースを使用しています。
ちなみにconfig/database.phpで、この'default' => env('DB_CONNECTION', 'mysql'),
を追加して、この場合のように異なるものを指定しない限り、デフォルトでmysqlを使用します。
フレームワークがテスト用に起動されるTestCase
ファイルで使用されている.env
ファイルをオーバーライドできます。
より具体的に:
tests/TestCase.php
/**
* Creates the application.
*
* @return \Illuminate\Foundation\Application
*/
public function createApplication()
{
/* @var \Illuminate\Foundation\Application $app */
$app = require __DIR__ . '/../bootstrap/app.php';
$app->loadEnvironmentFrom('.env.testing'); // specify the file to use for environment, must be run before boostrap
$app->make('Illuminate\Contracts\Console\Kernel')->bootstrap();
return $app;
}
TestCase
を拡張するすべてのテストは、この構成ファイルを使用します。
phpunit.xml
で定義された設定は、この設定を上書きすることに注意してください。
Laravel5.4以降、createApplication
関数は tests\TestCase
にありません。 tests\CreatesApplication
traitに移動しました。
これは2019年です。
私はそれを理解することができるまで、この問題を非常に長い間抱えていました。
そして、ここに私の仮定があります:
PHPUnit.xmlを.env.testingファイルとやり取りするのが難しい場合も、PHPStormを使用している可能性があります。
これに該当する場合は、読み続けてください。
そうでない場合は、いや...これは役に立ちません。
OK...
どうぞ:
これにより、xmlファイル内のすべての変更が有効になります。それでは、先に進み、.env.testingファイルを作成し、テスト用の好みのDB構成変数を作成して...テストを再度実行してください!
開発用マシンにローカルデータベースを作成します。 「local_test_db」
新しい.env.testingファイルを作成します。
DB_DATABASE=local_test_db
DB_USERNAME=root
Phpunit.xmlファイルに少なくともこの1つのenv変数があることを確認してください。
<php>
<env name="APP_ENV" value="testing"/>
</php>
最後に、ベーステストケース(TestCase.php)で移行を実行して、dbにテーブルを追加します。
public function createApplication()
{
$app = require __DIR__.'/../bootstrap/app.php';
$app->make(Illuminate\Contracts\Console\Kernel::class)->bootstrap();
return $app;
}
public function setUp()
{
parent::setUp();
Artisan::call('migrate');
}
public function tearDown()
{
Artisan::call('migrate:reset');
parent::tearDown();
}
これから リンク
方法1
ステップ1:以下のようにDatabase/Config.phpに新しいテストデータベース接続を作成します。
return [
...
'default' => env('DB_CONNECTION', 'db'),
'connections' => [
'sqlite_testing_db' => [
'driver' => 'sqlite',
'database' => storage_path().'/testing_database.sqlite',
'prefix' => '',
],
/**************** OR ******************/
'testing_db' => [
'driver' => 'mysql',
'Host' => env('TEST_DB_Host', 'localhost'),
'database' => env('TEST_DB_DATABASE', 'forge'),
'username' => env('TEST_DB_USERNAME', 'forge'),
'password' => env('TEST_DB_PASSWORD', ''),
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
'strict' => false,
],
/** Production or database DB **/
'db' => [
'driver' => 'mysql',
'Host' => env('TEST_DB_Host', 'localhost'),
'database' => env('TEST_DB_DATABASE', 'forge'),
'username' => env('TEST_DB_USERNAME', 'forge'),
'password' => env('TEST_DB_PASSWORD', ''),
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
'strict' => false,
],
],
];
手順2:.envファイルでデータベース資格情報を指定する
TEST_DB_Host=localhost
TEST_DB_DATABASE=laravel
TEST_DB_USERNAME=root
TEST_DB_PASSWORD=rootwdp
ステップ3:phpunit.xmlで使用するテストデータベース接続を指定します。
<env name="DB_CONNECTION" value="testing_db"/>
OR Below If you prefer sqlite
<env name="DB_CONNECTION" value="sqlite_testing_db"/>
手順4:データベースをこの新しいテストデータベースに移行します-データベーストランザクションを使用してテーブルへの挿入をロールバックする場合。
php artisan migrate --database=testing_db
//If using sqlite
touch storage/testing_database.sqlite
php artisan migrate --database=sqlite_testing
ステップ5:これで、データベーストランザクションを使用した単体テストは次のようになります。
<?php
use App\User;
use Illuminate\Foundation\Testing\DatabaseTransactions;
class UserTest extends TestCase
{
use DatabaseTransactions;
/** @test */
function it_test_user_can_be_saved()
{
factory(User::class, 2)->create();
$users = User::all();
$this->assertEquals(2, $users->count());
}
}
//Run Php Unit
-> vendor/bin/phpunit --color tests/acceptance/model/UserTest.php
注:データベーストランザクションを使用しない場合は、TestCase.phpクラスのセットアップおよびティアダウンメソッドを使用して、以下のようにデータベースを移行およびロールバックできます。
<?php
use Illuminate\Support\Facades\Artisan;
class TestCase extends Illuminate\Foundation\Testing\TestCase
{
...
public function setUp()
{
parent::setUp();
Artisan::call('migrate');
}
public function tearDown()
{
Artisan::call('migrate:reset');
parent::tearDown();
}
}
@Sambhu Singhの回答のすべてのステップを実行し、彼のリンクをたどりました。しかし、L5.5では私にとっては機能しません
移行時に、職人コマンドの前の「テスト」にAPP_ENVを追加/設定するとうまくいきました:
APP_ENV=testing php artisan migrate --database=sqlite_testing
単体テストを開始する前に、一時的に.env.testingを.envに名前変更する以外の方法は考えられません。
これは、phpunitがアプリケーションをロードする前にbootstrapファイルとして使用するものです。
App.phpでDotenvセクションを変更します
$envFile = 'testing' === env('APP_ENV') ? '.env.testing' : null;
try {
(new Dotenv\Dotenv(__DIR__ . '/../', $envFile))->load();
} catch (Dotenv\Exception\InvalidPathException $e) {
//
}
これは機能するので、PHPUnitはアプリをロードする前にenvを変更します。
数か月間これに苦労していて、今日出会ったのは このGithubの問題 です。そこで提案されているソリューションから、CreatesApplication.phpファイルで行うべきことは以下のとおりです(Laravelテスト環境をロードするためにキャッシュされた構成を削除するには):
/**
* Creates the application.
*
* @return \Illuminate\Foundation\Application
*/
public function createApplication()
{
$app = require __DIR__.'/../bootstrap/app.php';
$app->make(Illuminate\Contracts\Console\Kernel::class)->bootstrap();
$this->clearCache(); // NEW LINE -- Testing doesn't work properly with cached stuff.
return $app;
}
/**
* Clears Laravel Cache.
*/
protected function clearCache()
{
$commands = ['clear-compiled', 'cache:clear', 'view:clear', 'config:clear', 'route:clear'];
foreach ($commands as $command) {
\Illuminate\Support\Facades\Artisan::call($command);
}
}
上記の変更後もこの問題が引き続き発生する場合は、次のようにアプリケーション全体を再構築することでさらに進めることができます。
public function createApplication()
{
$createApp = function() {
$app = require __DIR__.'/../bootstrap/app.php';
$app->make(Kernel::class)->bootstrap();
return $app;
};
$app = $createApp();
if ($app->environment() !== 'testing') {
$this->clearCache();
$app = $createApp();
}
return $app;
}
これは私にとってはうまく機能しています。