Мигрируйте только один раз с закатом Laravel

Согласно документации "Тестирование базы данных" Я могу сбрасывать базу данных после каждого теста (первый вариант). Второй вариант — запустить тест с использованием транзакций. Мне кажется, это лучший подход, но если я хочу запустить транзакцию, миграция не запускается.

Есть ли способ запустить миграцию один раз для всего процесса тестирования?

Другими словами, я хочу запустить миграцию, запустить все тесты с транзакцией, а затем выполнить откат. Я пробовал с тем, что говорится в документации, но я думаю, что чего-то не хватает.


person rap-2-h    schedule 01.02.2017    source источник
comment
Если у вас есть несколько классов Dusk и вы хотите запустить заполнение базы данных только один раз, прежде чем будут запущены все классы Dusk, я думаю, что этот подход приведет к фактическому ответу, который вы ищете: stackoverflow.com/a/35457334/470749   -  person Ryan    schedule 28.02.2019


Ответы (4)


Сегодня некоторое время спорили с этим, и запуск миграций в сочетании с миграциями, похоже, помогает. Снимок моего теста выглядит следующим образом:

<?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
    }
}

У меня есть пара фабрик в моем реальном тесте, и они, похоже, проходят миграцию с данными, уничтоженными после теста, как и ожидалось.

person simnom    schedule 06.02.2017
comment
Это просто запускает миграцию базы данных. Транзакции не поддерживаются в сумерках, поскольку они выполняются в браузере. - person Christophvh; 11.04.2017

На данный момент невозможно запустить 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 и переименует вашу среду Dusk в .env. После завершения тестов ваш файл .env будет восстановлен.

Предоставленный ответ работает, потому что работает DatabaseMigrations. use DatabaseTransactions не имеет значения.

person Christophvh    schedule 11.04.2017

Насколько я понимаю, я не думаю, что транзакции могут когда-либо работать в сумерках, поскольку каждый запрос браузера в сумерках создает отдельный экземпляр вашего приложения laravel.

Раньше phpunit создавал новое приложение в памяти как часть процесса (в методе setUp/createApplication), затем тестировал это тестовое приложение, затем уничтожал его и устанавливал следующее. Таким образом, транзакции могут быть обернуты вокруг (или только внутри) частей создания и уничтожения этого приложения, прежде чем оно запустит новое соединение с базой данных для следующего теста.

С наступлением сумерек это настоящее сквозное тестирование (включая браузер, фальшивое взаимодействие с пользователем, маршрутизацию на вашем локальном компьютере и т. д.), что означает, что не все содержится в среде, в которой выполняются ваши тесты, как они обычно находятся в phpunit.

Сумерки делают следующее:

  • Копирует ваш .env.dusk.* и запускает chromedriver (или любую другую селеноподобную вещь, которую вы используете)
  • Запускает команду оболочки phpunit (т.е. новая команда, новый процесс)
  • Команда phpunit запускает ваши тесты в сумерках, каждый из которых открывает окно браузера и отправляет запросы (каждый запрос запускает новый процесс php-fpm и php (для nginx)) — так же, как если бы вы сами делали эти запросы. Каждый из них имеет отдельные подключения к базе данных и поэтому не может взаимодействовать с транзакциями друг друга.

Также стоит отметить, что трейт DatabaseTransactions находится в пакете Foundation, а не в пакете Dusk, поэтому он не собирается/упаковывается с учетом Dusk.

Это также объясняет, почему sqlite в памяти не работает с сумерками, поскольку один процесс не имеет доступа к памяти другого процесса.

person Vinayak Kulkarni    schedule 23.06.2017

Вот очень портативный и многоразовый способ:

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
    }
...
person Ryan    schedule 28.02.2019