在Laravel的完整测试套件之前,如何在内存数据库中迁移和种子? 我正在尝试在我的Laravel项目中设置测试环境。 我正在使用http://packalyst.com/package/package/mayconbordin/l5-fixtures with JSON与Memory数据库中的SQLite一起播种...

问题描述 投票:0回答:4
Artisan::call('migrate'); Artisan::call('db:seed');

在我的SETUP

函数中,但这是在每个测试中都可以在该项目中生长到数千个测试之前执行的。 我尝试了
SetupbeforeClass
,但它没有用。 我认为那里是因为在每个测试中都调用了

createApplication方法,并且可以重置整个应用程序,并且也没有出于相同的原因加载JSON的固定装置。

如果别人在挣扎的情况下,这就是我的做法,我创建了一个从拉拉维尔(Laravel)那里继承的基础testClase班级,并做到了这一点: /** * 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 = []; }

php laravel phpunit laravel-5
4个回答
19
投票
createApplication()

tearDown()
方法。我更改了第一个使用相同的

$app
配置,然后卸下flush
teardown()

$this->app
的部分。 我的其他测试都必须从该测试阶段继承,仅此而已。 其他一切都没有用。即使在内存数据库中,也可以更快地使用。
如果您正在处理用户会话,一旦您记录了用户,则必须将其拆除,否则将登录用户,因为永远不会重建应用程序环境,或者您可以做类似的事情来刷新刷新每次您想要的应用程序:
protected static $applicationRefreshed = false;

/**
 * Refresh the application instance.
 *
 * @return void
 */
protected function forceRefreshApplication() {
    if (!is_null($this->app)) {
        $this->app->flush();
    }
    $this->app = null;
    self::$configurationApp = null;
    self::$applicationRefreshed = true;
    parent::refreshApplication();
}
tearDown()
之前将其添加到

$this->setUphasRun = false;

if (self::$applicationRefreshed) { self::$applicationRefreshed = false; $this->app->flush(); $this->app = null; self::$configurationApp = null; }

在您的项目中创建文件
testrunner
使用此内容(也可以使用测试环境变量准备

.env.testing

文件):
php artisan migrate:rollback --env=testing
php artisan migrate --env=testing --seed
vendor/bin/phpunit

并允许通过命令执行并通过
chmod +x testrunner
执行它。多数民众赞成:)

5
投票

eption1
如何使用迁移和种子设置数据库,然后使用数据库转换? (
https://laravel.com/docs/5.1/testing#resetting-the-database-after-each-test

我希望能够通过Artisan设置我的测试数据库:

./testrunner
您可以猜到,我正在使用mysql,但是我不明白为什么这不应该适用于sqlite。
这就是我的方式。

Config/database.php


3
投票
$ php artisan migrate --database=mysql_testing $ php artisan db:seed --database=mysql_testing

如果您这样做,请不要忘记将db_test_database添加到您的

.env文件:

'connections' => [ 'mysql' => [ 'driver' => 'mysql', 'host' => env('DB_HOST', 'localhost'), 'database' => env('DB_DATABASE', 'forge'), 'username' => env('DB_USERNAME', 'forge'), 'password' => env('DB_PASSWORD', ''), 'charset' => 'utf8', 'collation' => 'utf8_unicode_ci', 'prefix' => '', 'strict' => false, ], 'mysql_testing' => [ 'driver' => 'mysql', 'host' => env('DB_HOST', 'localhost'), 'database' => env('DB_TEST_DATABASE'), 'username' => env('DB_USERNAME', 'forge'), 'password' => env('DB_PASSWORD', ''), 'charset' => 'utf8', 'collation' => 'utf8_unicode_ci', 'prefix' => '', 'strict' => false, ], ],

phpunit.xml

在.env文件中给出的覆盖值下,在phpunit.xml文件中设置了任何值。因此,我们告诉PHPUNIT使用“ mysql_testing”数据库连接,而不是“ mySQL”数据库连接。

DB_DATABASE=abc DB_TEST_DATABASE=abc_test

测试班


我的测试课程看起来像这样:

<?xml version="1.0" encoding="UTF-8"?> <phpunit> ... <php> ... <env name="DB_CONNECTION" value="mysql_testing"/> </php>

eption2

在每个测试之前,数据库是重置的,这就是为什么我更喜欢选项1。 我以前尝试过一次,它可能对您有用。 -tests/testcase.php

扩展测试用例,加载一个新的.env文件,.env.testing

class MyTest extends \TestCase { use \Illuminate\Foundation\Testing\DatabaseTransactions; public function testSomething() {

.env.testing

创建此新的.env文件并添加数据库详细信息

<?php class TestCase extends Illuminate\Foundation\Testing\TestCase { /** * The base URL to use while testing the application. * * @var string */ protected $baseUrl = 'http://localhost'; /** * Creates the application. * * @return \Illuminate\Foundation\Application */ public function createApplication() { /** @var $app \Illuminate\Foundation\Application */ $app = require __DIR__.'/../bootstrap/app.php'; $app->loadEnvironmentFrom('.env.testing'); $app->make(Illuminate\Contracts\Console\Kernel::class)->bootstrap(); return $app; } }

测试班:

使用PDO掉落并重新创建数据库 - 比尝试截断所有内容更容易。 然后使用工匠迁移和播种数据库。

APP_ENV=testing APP_DEBUG=true APP_KEY=xxx DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_DATABASE=abc_testing DB_USERNAME=xxx DB_PASSWORD=xxx

上述解决方案中的主要方法是为所有测试运行所有迁移。我更喜欢一种指定每个测试应运行哪些迁移和种子的方法。

在大型项目上可能更值得,因为这可以将测试的时间降低约70%(使用上述已经解释的SQLite内存中DB)。对于小型项目,这可能有点太多了。但是无论如何...
将这些用在测试柜中:

class MyTest extends TestCase { public static function setUpBeforeClass() { $config = parse_ini_file(".env.testing"); $username = $config['DB_USERNAME']; $password = $config['DB_PASSWORD']; $database = $config['DB_DATABASE']; $host = $config['DB_HOST']; // Create test database $connection = new PDO("mysql:host={$host}", $username, $password); $connection->query("DROP DATABASE IF EXISTS " . $database); $connection->query("CREATE DATABASE " . $database); } public function testHomePage() { Artisan::call('migrate'); Artisan::call('db:seed'); $this->visit('/') ->see('Home') ->see('Please sign in') ->dontSee('Logout'); }

然后在单个测试中按要求进行调用迁移()和种子,例如:

/** * Runs migrations for individual tests * * @param array $migrations * @return void */ public function migrate(array $migrations = []) { $path = database_path('migrations'); $migrator = app()->make('migrator'); $migrator->getRepository()->createRepository(); $files = $migrator->getMigrationFiles($path); if (!empty($migrations)) { $files = collect($files)->filter( function ($value, $key) use ($migrations) { if (in_array($key, $migrations)) { return [$key => $value]; } } )->all(); } $migrator->requireFiles($files); $migrator->runPending($files); } /** * Runs some or all seeds * * @param string $seed * @return void */ public function seed(string $seed = '') { $command = "db:seed"; if (empty($seed)) { Artisan::call($command); } else { Artisan::call($command, ['--class' => $seed]); } }
    

在我的情况下,我创建了从 $this->migrate( [ '2013_10_11_081829_create_users_table', ] ); $this->seed(UserTableSeeder::class);

文件复制的文件。然后,我将数据库信息添加到此文件中。

.env.testing

在终端,您可以使用选项

.env.example
这样运行迁移工匠命令。
APP_ENV=testing APP_KEY=<generate your app key> ... DB_CONNECTION=sqlite DB_DATABASE=:memory:

1
投票

我认为

https://stackoverflow.com/a/38591471/3872647

的概念是正确的,但是这种方式覆盖代码可能会导致将来会导致新开发人员的不相容性。 this Post通过设置

--env

来描述一种更好的方法,其中每次测试只执行一次
Https://masteringlaravel.io/daily/2023-12-04-04-you-dont-need-need - 在您的测试中进行生产
    

最新问题
© www.soinside.com 2019 - 2024. All rights reserved.