Вопрос по php, symfony, unit-testing – Практики для тестирования базы данных в Symfony2? Как изолировать?

12

Каковы современные рекомендации по тестированию взаимодействия баз данных с Symfony2? У меня есть простая настройка CRUD, и я хочу убедиться, что мое тестирование в порядке. Прямо сейчас у меня есть 4 теста, каждый из которых проверяет, что действия по созданию, обновлению, удалению и списку выполняются нормально.

У меня есть два магических метода, __construct и __destruct, в моем тестовом случае. Внутри них я вызываю exec () с помощью «php app / console ...» чтобы создать базу данных, создайте схему, а затем удалите базу данных. Тем не менее, это МЕДЛЕННО, черт возьми, и это происходит все время, когда у меня более одного тестового случая.

Как мне действовать, когда дело доходит до тестирования базы данных и изоляции таких тестов?

Видел хорошую статью на эту тему раньше.blog.sznapka.pl/fully-isolated-tests-in-symfony2 Adam

Ваш Ответ

4   ответа
8

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

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

У меня есть базовый класс тестового случая с именем KernelAwareTest, который помогает мне в построении схемы. Вы можете найти это в сущности:https://gist.github.com/1319290

setUp() загружает ядро Symfony и сохраняет ссылку на него в свойстве класса (вместе со ссылками на DIC и диспетчер сущностей). Также призыв кgenerateSchema() сделан для генерации схемы базы данных (использует Schema Tool из Doctrine).

По умолчанию он генерирует структуру базы данных для всех сущностей, известных менеджеру сущностей. Вы можете изменить это поведение в своем тестовом классе, переопределивgetMetadatas() метод.

П.С .: Я пытался использовать в базе данных памяти (sqlite), но она не была идеальной. В любом случае, вероятно, лучше запускать тесты для базы данных, которую вы используете в производственной среде.

0

тестирование на локальной машине - это боль в ..., поэтому я начал использовать ci system buddy.works (есть бесплатная автономная версия), и для этого мне нужно было решить эту проблему самостоятельно.

результат:

  • all tests works
  • tests are runing on production sql data
  • tests are running in separation (not in dev or production) - so i can do anything that i want with database
  • all pushes to git are tested and i have notification if something is broken
  • all pushes/pull request to deploy branch are automatic uploaded to production

Это мое решение:

  1. second parameters.yml in config with configuration for test
  2. on production i'm making daily sqldump
  3. on starting test on ci this sql backup is copied via scp to test machine
  4. to prepare all this i'm using robo.li ( my config is below)

/**
* This is project's console commands configuration for Robo task runner.
*
* @see http://robo.li/
*/
class RoboFile extends \Robo\Tasks
{

function  loadDb(){
    $this->taskExecStack()
        ->stopOnFail()
        ->exec(" mysql -h mariadb -u root -pqwerty -e 'create database test' ")
        ->exec(" mysql -h mariadb -u root -pqwerty test < test.sql ")
        ->run();
}


function prepareDb(){
    $this->taskExecStack()
        ->stopOnFail()
        ->exec("cp  app/config/parameters-test.yml app/config/parameters.yml")
        ->run();

    $this->taskReplaceInFile('app/config/parameters.yml')
        ->from('database_host:     127.0.0.1')
        ->to("database_host:     'mariadb'")
        ->run();

    $this->taskReplaceInFile('app/config/parameters.yml')
        ->from('database_user:     dbuser')
        ->to("database_user:     'root'")
        ->run();

    $this->taskReplaceInFile('app/config/parameters.yml')
        ->from('database_password: 123')
        ->to("database_password: 'qwerty'")
        ->run();


}

}

Я надеюсь, что это поможет вам создать идею, как все это организовать. Использование автономного ci сложно в настройке, но это действительно хорошая идея

7

Тестирование базы данных всегда медленное, так как вам нужно создавать / удалять схему до / после каждого теста. Чтобы избежать ненужных операций, вы можете:

  • create schema in the 'setUpBeforeClass' method;
  • ensure your 4 tests are launched in one thread with the '@depend' annotation;
  • drop schema in the 'tearDownAfterClass' method.

Схема будет создана / удалена только один раз для вашего теста.

Вы также можете настроить доктрину для использования базы данных sqlite (это очень быстро):

doctrine:
    dbal:
        driver: pdo_sqlite
        path: :memory:
        memory: true

В любом случае, _construct' and '_destruct & APOS; никогда не должен использоваться в тестовых случаях phpunit, вместо этого вы должны использовать «setUp»; и «tearDown».

Есть ли хороший способ избавиться от моего exec ()? Я чувствую себя грязно, запустив exec («php app / console doctrine: schema: create») на моих тестах. vinnylinux
1

Вопрос довольно старый, но все еще актуален сегодня, так что вот мой опыт и то, как я справляюсь сегодня с моими проектами Symfony.

Я начал использовать базу данных SQLite в памяти для своих тестов и перестраивал схему db + вставленные осветители перед каждым отдельным тестом. Это имело два основных недостатка:

  • It was still way too slow :(
  • On dev & prod I used Mysql which soon became a problem because SQLite simply does not have all the features needed and sometimes behaves differently

Использование MSQL для тестов и перестройка схемы + вставка осветителей перед каждым тестом просто была слишком медленной. Поэтому я искал альтернативы ...

Я наткнулся на это сообщение в блоге:http://alexandre-salome.fr/blog/Symfony2-Isolation-Of-Tests

Парень здесь предлагает запускать тесты внутри активных транзакций базы данных и просто откатывать любые изменения после каждого отдельного теста.

Я взял эту идею и создал пакет для нее:https://github.com/dmaicher/doctrine-test-bundle

Настройка пакета очень проста и не требует изменения каких-либо существующих классов тестирования php. Внутренне это изменяет конфигурацию доктрины, чтобы использовать пользовательские соединения с базой данных + драйвер.

С помощью этого комплекта вы можете просто создать свою схему базы данных + вставить приспособления ОДИН РАЗ перед выполнением всего набора тестов (я предпочитаю делать это в пользовательском файле начальной загрузки phpunit). При использовании прослушивателя phpunit все тесты будут выполняться внутри транзакций базы данных.

Я уже давно пользуюсь этим комплектом, и для меня он прекрасно работает с использованием SQLite, MySQL или PostgreSQL.

С тех пор его также использовали в проекте symfony-demo.

Похожие вопросы