【问题标题】:Running setup code before every test in a suite在套件中的每个测试之前运行设置代码
【发布时间】:2017-05-02 16:00:54
【问题描述】:

我有一个正在开发的 Laravel 5 应用程序,它有两个测试套件:UnitFunctional。我在phpunit.xml中定义了这些:

<testsuite name="Unit">
    <directory>./tests/unit</directory>
</testsuite>
<testsuite name="Functional">
    <directory>./tests/functional</directory>
</testsuite>

为了使功能测试正确运行,它们需要有一个有效的数据库来处理。这意味着在运行功能测试之前执行一些设置以迁移数据库。

通常我会在我的测试中使用DatabaseMigrations 特征来确保在每次测试之前迁移数据库。不幸的是,这大大减慢了我们的测试速度(我们有数百个)。我将测试切换为使用 DatabaseTransactions 特征,这使它们运行得更快,但现在在运行测试之前不会迁移数据库。如果我在项目的新克隆上运行测试套件,它会失败,因为我在运行功能测试套件之前没有迁移数据库。

对此的明显解决方案是将$this-&gt;artisan('migrate'); 添加到tests/TestCase.phpsetUp 方法中。但这有两个问题:

  1. 这会导致在每次测试之前迁移数据库,这是我一开始就试图避免的。

  2. 这也尝试在运行单元测试套件时迁移数据库,这显然不理想。

对我来说,确保在运行任何测试之前迁移功能测试数据库的最佳方法是什么,但仅限于功能测试?

【问题讨论】:

    标签: php laravel unit-testing testing laravel-5


    【解决方案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 应用程序工作。

    【讨论】:

    • 好主意。我最终创建了一个仅扩展我的功能测试的 FunctionalTestCase,它负责任何数据库设置工作。谢谢!
    猜你喜欢
    • 2014-11-24
    • 1970-01-01
    • 2014-05-02
    • 2018-07-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多