我开发的Laravel 5应用程序有两套测试服:Unit
和Functional
。我在phpunit.xml
:
<testsuite name="Unit">
<directory>./tests/unit</directory>
</testsuite>
<testsuite name="Functional">
<directory>./tests/functional</directory>
</testsuite>
要使功能测试正确运行,他们需要有一个有效的数据库来对抗。这意味着在运行功能测试之前执行一些设置以迁移数据库。
通常我会在测试中使用DatabaseMigrations
特征来确保在每次测试之前迁移数据库。不幸的是,这会大大减慢我们的测试速度(我们有数百个)。我将测试切换为使用DatabaseTransactions
特征,这使得它们运行得更快,但现在在运行测试之前不迁移数据库。如果我在项目的新克隆上运行测试套件,它会失败,因为我还没有在运行功能测试套件之前迁移数据库。
明显的解决方案是将$this->artisan('migrate');
添加到setUp
的{{1}}方法中。但这有两个问题:
这导致在每次测试之前迁移数据库,这是我首先想要避免的。
这也会在运行单元测试套件时尝试迁移数据库,这显然不太理想。
对于我来说,最好的方法是确保在运行任何测试之前迁移功能测试的数据库,但仅限于功能测试?
答案 0 :(得分:1)
您可以创建一个继承自Laravel的TestCase的基础testClase类,只有您的Functional
套件类可以继承新的类,并且在您的新类中添加:
/**
* Creates the application.
*
* @return \Illuminate\Foundation\Application
*/
public function createApplication()
{
return self::initialize();
}
private static $configurationApp = null;
public static function initialize(){
if(is_null(self::$configurationApp)){
$app = require __DIR__.'/../bootstrap/app.php';
$app->loadEnvironmentFrom('.env.testing');
$app->make(Illuminate\Contracts\Console\Kernel::class)->bootstrap();
if (config('database.default') == 'sqlite') {
$db = app()->make('db');
$db->connection()->getPdo()->exec("pragma foreign_keys=1");
}
Artisan::call('migrate');
Artisan::call('db:seed');
self::$configurationApp = $app;
return $app;
}
return self::$configurationApp;
}
public function tearDown()
{
if ($this->app) {
foreach ($this->beforeApplicationDestroyedCallbacks as $callback) {
call_user_func($callback);
}
}
$this->setUpHasRun = false;
if (property_exists($this, 'serverVariables')) {
$this->serverVariables = [];
}
if (class_exists('Mockery')) {
Mockery::close();
}
$this->afterApplicationCreatedCallbacks = [];
$this->beforeApplicationDestroyedCallbacks = [];
}
即使在内存数据库中也能正常工作,它的速度提高了100倍。
PS:为Laravel而不是Lumen应用程序工作。