Как откат совершает в Behat 3 функциональных теста с Symfony2 и Doctrine?
Как название, моя цель - откат любого фиксации, сделанного во время функциональных тестов Behat.
Я проверил этот ответ очень похожим, но это происходит два года назад, и это кажется невозможным.
Возможно, теперь с Behat 3 это возможно.
Я знаю, что с PHPUnit я могу достичь чего-то подобного, используя методы startUp и tearDown.
Я попытался запустить и отменить транзакцию, связанную с аннотациями @BeforeScenario и @AfterScenario, но, похоже, что это так, и приложение не использует один и тот же экземпляр диспетчера сущностей.
Некоторые советы по этому поводу?
Спасибо.
UPDATE
Спасибо всем за ваши советы. Вот некоторые новые соображения:
-
ЗАГРУЗКИ FIXTURES: Да, это работает. Я могу запускать приборы до начала тестов, но проблема (моя ошибка, чтобы не упоминать об этом) заключается в том, что для монтажа иногда требуется несколько минут, и до начала тестов ждать 10 или более минут. >
-
BEGIN/ROLLBACK TRANSACTION: он работает тоже или кажется. Я не получаю ошибок, но данные, записанные во время тестов, все еще находятся в моей базе данных, когда они закончились. Я добавил первый в методе tagged @BeforeScenario e последний в методе, отмеченном @AfterScenario
$this->kernel->getContainer()
->get('doctrine.orm.entity_manager')
->getConnection()
->beginTransaction();
$this->kernel->getContainer()
->get('doctrine.orm.entity_manager')
->getConnection()
->rollBack();
- SAVEPOINT. Я думаю, что именно то, что мне нужно, но мои данные все еще существуют. Я попытался добавить создание точки сохранения в свой метод @BeforeScenario и откат метода @AfterScenario
public function gatherContexts(BeforeScenarioScope $scope) {
$environment = $scope->getEnvironment();
$connection = $this->kernel->getContainer()->get('doctrine.orm.entity_manager')->getConnection();
$connection->beginTransaction();
$connection->createSavepoint('tests');
}
public function rollback(AfterScenarioScope $scope) {
$connection = $this->kernel->getContainer()->get('doctrine.orm.entity_manager')->getConnection();
$connection->rollbackSavepoint('tests');
}
Все эти тесты используются для тестирования моего проекта REST API. После этих соображений я думаю, что Behat и мое приложение не используют один и тот же экземпляр менеджера сущности. Можете ли вы поделиться одним и тем же экземпляром между вашими тестами и вашими проектами во время тестов?
Ответы
Ответ 1
Если ваш контекст реализует KernelAwareContext
, то в аннотированных методах @BeforeScenario и @AfterScenario вы можете сделать
$this->kernel->getContainer()->getDoctrine()->getConnection()->beginTransaction();
$this->kernel->getContainer()->getDoctrine()->getConnection()->rollBack();
Это предполагает, что у вас есть только одно соединение, и оно используется em.
Вы также можете попробовать $connection->setRollbackOnly()
, но имейте в виду, что он будет дико зависеть от вашего базового db. Mysql может автокомментировать в нескольких случаях, если бы вы этого не ожидали.
И, наконец, есть и $connection->createSavepoint('savePointName')
для использования с $connection->rollbackSavepoint('savePointName')
Это из моей головы, поэтому может потребоваться некоторые корректировки.
Ответ 2
С помощью метода setUp
вы можете начать транзакцию. Вы можете откатить его в методе tearDown
, если между двумя вызовами метода нет фиксации.
Очень опасно запускать тесты в производственной базе данных, даже если вы откатываете запросы. Это лучший способ инициализировать тест базы данных с помощью прибора. Если вы не можете это сделать (я так думаю), вы хотите протестировать с данными о производстве. Используйте doctrine:migrations
(или doctrine:schema:create
), чтобы скопировать схему производственной базы данных в среду разработки и добавить script для копирования данных.
Ответ 3
Я думаю, что схема "dropping" и "create" - это решение, которое вы ищете.
Я использую Behat3
для моего функционального тестирования - я тестирую довольно сложное веб-приложение и API REST. Я использую подготовленные приборы, а также добавляю дополнительные данные во время сценария.
Вы можете настроить контекст Behat
для загрузки светильников для каждого (до) сценария - это работает очень хорошо:
class CustomContext implements Context, KernelAwareContext {
/**
* @param type ScenarioEvent
*
* @BeforeScenario
*/
public function reloadSchema($event)
{
// Note: EntityManager and ClassMetadata is required
// reload Schema
$schemaTool = new SchemaTool($entityManager);
$schemaTool->dropSchema($metadata);
$schemaTool->createSchema($metadata);
}
/**
* @param type ScenarioEvent
*
* @AfterScenario
*/
public function closeConnections($event)
{
// close connection(s)
}
// ...
}
Перед каждым сценарием Doctrine2
отбрасывается и создается схема. Далее, благодаря узлам ниже, вы можете загружать определенные/общие приспособления для своих сценариев.
Я использую следующую конфигурацию для Behat
светильников:
Благодаря этому вы можете загружать светильники в сценарии:
Given the fixtures file "dummy.yml" is loaded
Given the fixtures file "dummy.yml" is loaded with the persister "doctrine.orm.entity_manager"
Given the following fixtures files are loaded:
| fixtures1.yml |
| fixtures2.yml |
Позвольте мне теперь, если вам нужно больше деталей.