【问题标题】:Migrate only once with Laravel dusk使用 Laravel 黄昏只迁移一次
【发布时间】:2017-06-18 05:43:31
【问题描述】:

根据to the "Database Testing" documentation,我可以在每次测试后重置数据库(第一个选项)。第二种选择是使用事务运行测试。这对我来说似乎是一种更好的方法,但如果我想使用事务运行,迁移不会运行。

有什么方法可以为所有测试过程运行一次迁移

换句话说,我想运行迁移,使用事务运行每个测试,然后回滚。我尝试了文档所说的内容,但我认为缺少某些内容。

【问题讨论】:

  • 如果您有多个 Dusk 类并且只想在所有 Dusk 类运行之前运行一次数据库播种,我认为这种方法将导致您正在寻找的实际答案:@987654322 @

标签: php laravel unit-testing laravel-5.4 laravel-dusk


【解决方案1】:

今天为此争论了一段时间,与迁移一起运行迁移似乎可以解决问题。我的测试截图如下:

<?php

namespace Tests\Browser;

use App\User;
use Tests\DuskTestCase;

use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;

class DefaultTest extends DuskTestCase
{
    use DatabaseMigrations, DatabaseTransactions;

    /**
     * A Dusk test example.
     *
     * @return void
     */
    public function test_something()
    {
        //Add test stuff here
    }
}

在我的实际测试中,我有几个工厂,它们似乎在进行迁移,并且在测试后按预期销毁了数据。

【讨论】:

  • 这只是运行数据库迁移。黄昏不支持事务,因为它是在浏览器中运行的。
【解决方案2】:

目前无法结合黄昏运行 DatabaseTransactions。

https://github.com/laravel/dusk/issues/110

用户记录的创建和在浏览器中的使用是 在两个不同的过程中完成。这意味着创建的用户是一部分 未提交的数据库事务,因此不 可由浏览器进程访问。

数据库迁移工作。所以你应该使用那些。还要确保你运行一个单独的测试数据库,这样你就不会弄乱你的生产/开发数据库。

https://laravel.com/docs/5.4/dusk#environment-handling

强制 Dusk 在运行测试时使用自己的环境文件, 在项目的根目录中创建一个 .env.dusk.{environment} 文件。 例如,如果您要从您的 本地环境,你应该创建一个 .env.dusk.local 文件。

运行测试时,Dusk 会备份你的 .env 文件并重命名你的 .env 的黄昏环境。测试完成后,您的 .env 文件将被恢复。

提供的答案有效,因为 DatabaseMigrations 有效。 use DatabaseTransactions 不相关。

【讨论】:

    【解决方案3】:

    据我了解,我认为使用黄昏时事务永远无法工作,因为黄昏时的每个浏览器请求都会创建一个单独的 laravel 应用实例。

    以前,phpunit 会在内存中创建一个新应用程序作为进程的一部分(在setUp / createApplication 方法中),然后针对该测试应用程序进行测试,然后销毁它并设置下一个应用程序。因此,在为下一次测试启动新的数据库连接之前,可以在该应用程序的创建和销毁部分周围(或仅在其内部)包装事务。

    使用黄昏,它是真正的端到端测试(包括浏览器、伪造的用户交互、本地机器上的路由等),这意味着它并不全部包含在运行测试的环境中,就像它们通常在 phpunit 中一样。

    Dusk 执行以下操作:

    • 复制您的 .env.dusk.* 并启动 chromedriver(或您使用的任何类似硒的东西)
    • 触发 phpunit shell 命令(即新命令、新进程)
    • phpunit 命令运行您的黄昏测试,每个测试都会打开一个浏览器窗口并发出请求(每个请求都会启动一个新的 php-fpm 和 php 进程(对于 nginx))——就像您自己发出这些请求一样。他们每个人都与数据库有单独的连接,因此无法与彼此的事务进行交互。

    还值得注意的是,DatabaseTransactions trait 位于 Foundation 包中,而不是 Dusk 包中,因此它在构建/打包时并未考虑到 Dusk。

    这也解释了为什么内存中的 sqlite 不适用于黄昏,因为一个进程无法访问另一个进程的内存。

    【讨论】:

      【解决方案4】:

      这是一种非常便携且可重复使用的方式:

      abstract class DuskTestCase extends BaseTestCase {
      
         ...
      
          /**
           * @param int $batchCounter
           * @param string $className
           * @param int $threshold
           */
          public function refreshDb(&$batchCounter, $className = '', $threshold = 0) {
              if ($batchCounter <= $threshold) {
                  //TODO: Here is where you'll want to run migrations and seeds and whatnot.
                  $batchCounter++;
                  $this->consoleOutput(trim($className . ' called refreshAndSeedTestingDb and $batchCounter++. $batchCounter=' . $batchCounter));
              }
          }
      
         /**
          * @param string $msg
          */
         public function consoleOutput($msg) {
             Log::debug($msg);
             $output = new \Symfony\Component\Console\Output\ConsoleOutput();
             $output->writeln($msg);
         }
      

      然后在每个测试文件中:

      class ExampleBrowserTest extends DuskTestCase {
      
          protected static $countDbRefreshed = 0;
      
          public function setUp() {//runs before every test function in this class
              parent::setUp();
              $this->refreshDb(self::$countDbRefreshed, __CLASS__); //inside uses a property to run only once per class
          }
      ...
      

      【讨论】:

        猜你喜欢
        • 2018-02-23
        • 2023-04-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-09-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多