Symfony 2 WebTestCase에서 테스트 데이터베이스를 만들고 픽스쳐를로드하는 가장 좋은 방법은 무엇입니까?
내 응용 프로그램에서 몇 가지 기본 경로를 실행하는 WebTestCase가 있습니다.
setUpPHPUnit 의 방법으로 메인 데이터베이스와 동일한 테스트 데이터베이스를 생성하고 픽스쳐를로드하고 싶습니다.
현재 몇 가지 해결 방법을 수행하고 다음과 같은 콘솔 명령을 실행하고 있습니다.
class FixturesWebTestCase extends WebTestCase
{
protected static $application;
protected function setUp()
{
self::runCommand('doctrine:database:create');
self::runCommand('doctrine:schema:update --force');
self::runCommand('doctrine:fixtures:load --purge-with-truncate');
}
protected static function runCommand($command)
{
$command = sprintf('%s --quiet', $command);
return self::getApplication()->run(new StringInput($command));
}
protected static function getApplication()
{
if (null === self::$application) {
$client = static::createClient();
self::$application = new Application($client->getKernel());
self::$application->setAutoExit(false);
}
return self::$application;
}
}
그러나 나는 확신이는 특히 때문에, 가장 좋은 방법이 아니에요 doctrine:fixtures:load사용자가 공격 할 것으로 예상 Y동작을 확인하기 위해 문자를.
어떻게 해결할 수 있습니까?
을 doctrine:fixtures:load사용하려면 --append옵션을 사용 하여 사용자 확인을 피할 수 있습니다 . 매번 데이터베이스를 다시 생성하므로 제거 할 필요가 없습니다. 나는 테스트를 위해 독트린 픽스쳐만을 사용했지만, DRY를 피하기 위해 픽스쳐와 LiipFunctionalTestBundle 을 사용하는 것으로 전환했습니다 . 이 번들은 조명기를 관리하기 쉽게 만듭니다.
편집 : David Jacquel의 대답은 Doctrine Fixtures를로드하는 데 올바른 것입니다.
doctrine:fixtures:load --no-interaction
or
doctrine:fixtures:load -n
사용자 확인을 우회하려면 다음을 사용할 수 있습니다.
doctrine:fixtures:load --no-interaction
or
doctrine:fixtures:load -n
업데이트 된 답변
Doctrine Data Fixtures 라이브러리 의 일부 클래스를 활용하여 픽스처로드를 쉽게 만드는 테스트 케이스에 대한 기본 클래스를 만들 수 있습니다 . 이 클래스는 다음과 유사합니다.
<?php
use Doctrine\Common\DataFixtures\Executor\ORMExecutor;
use Doctrine\Common\DataFixtures\FixtureInterface;
use Doctrine\Common\DataFixtures\Purger\ORMPurger;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bridge\Doctrine\DataFixtures\ContainerAwareLoader;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
abstract class FixtureAwareTestCase extends KernelTestCase
{
/**
* @var ORMExecutor
*/
private $fixtureExecutor;
/**
* @var ContainerAwareLoader
*/
private $fixtureLoader;
public function setUp()
{
self::bootKernel();
}
/**
* Adds a new fixture to be loaded.
*
* @param FixtureInterface $fixture
*/
protected function addFixture(FixtureInterface $fixture)
{
$this->getFixtureLoader()->addFixture($fixture);
}
/**
* Executes all the fixtures that have been loaded so far.
*/
protected function executeFixtures()
{
$this->getFixtureExecutor()->execute($this->getFixtureLoader()->getFixtures());
}
/**
* @return ORMExecutor
*/
private function getFixtureExecutor()
{
if (!$this->fixtureExecutor) {
/** @var \Doctrine\ORM\EntityManager $entityManager */
$entityManager = self::$kernel->getContainer()->get('doctrine')->getManager();
$this->fixtureExecutor = new ORMExecutor($entityManager, new ORMPurger($entityManager));
}
return $this->fixtureExecutor;
}
/**
* @return ContainerAwareLoader
*/
private function getFixtureLoader()
{
if (!$this->fixtureLoader) {
$this->fixtureLoader = new ContainerAwareLoader(self::$kernel->getContainer());
}
return $this->fixtureLoader;
}
}
그런 다음 테스트 케이스에서 위의 클래스를 확장하고 테스트 전에 필요한 모든 픽스처를 추가하고 실행하십시오. 이것은 조명기를로드하기 전에 데이터베이스를 자동으로 제거합니다. 예는 다음과 같습니다.
class MyTestCase extends FixtureAwareTestCase
{
public function setUp()
{
parent::setUp();
// Base fixture for all tests
$this->addFixture(new FirstFixture());
$this->addFixture(new SecondFixture());
$this->executeFixtures();
// Fixtures are now loaded in a clean DB. Yay!
}
}
오래된 답변
(나는이 답변을 "사용하지 않기"로 결정했는데, 픽스쳐를로드하는 방법을 말하지 않고 데이터베이스를 정리하는 방법 만 설명하기 때문입니다).
명령을 실행하지 않고도이를 수행 할 수있는 더 깔끔한 방법이 있습니다. 기본적으로 SchemaTool과 ORMPurger의 조합을 사용하여 구성됩니다. 이러한 종류의 작업을 수행하는 추상 기본 클래스를 만들어 각 특수 테스트 사례에 대해 반복하지 않도록 할 수 있습니다. 다음은 일반 테스트 케이스에 대한 데이터베이스를 설정하는 테스트 케이스 클래스의 코드 예제입니다.
use Doctrine\Common\DataFixtures\Purger\ORMPurger;
use Doctrine\ORM\Tools\SchemaTool;
abstract class DatabaseAwareWebTestCase extends WebTestCase {
public static function setUpBeforeClass() {
parent::setUpBeforeClass();
$kernel = static::createKernel();
$kernel->boot();
$em = $kernel->getContainer()->get('doctrine')->getManager();
$schemaTool = new SchemaTool($em);
$metadata = $em->getMetadataFactory()->getAllMetadata();
// Drop and recreate tables for all entities
$schemaTool->dropSchema($metadata);
$schemaTool->createSchema($metadata);
}
protected function tearDown() {
parent::tearDown();
$purger = new ORMPurger($this->getContainer()->get('doctrine')->getManager());
$purger->setPurgeMode(ORMPurger::PURGE_MODE_TRUNCATE);
$purger->purge();
}
}
This way, before running each test case which inherits from the above class, the database schema will be rebuilt from scratch, then cleaned up after every test run.
Hope this helps.
I've stumbled upon a really neat bundle named Doctrine-Test-Bundle Instead of creating and dropping schema on every test it simply rollback. My Tests went from 1m40s to.. 2s. And it's isolated. All you need is a clear test database and it'll do the trick.
I used this command:
yes | php app/console doctrine:fixtures:load --purge-with-truncate
But of course LiipFunctionalTestBundle looks promising.
I wanted to load all your fixtures like the doctrine:fixtures:load command does. I didn't want to run exec from inside the test case because it seemed like a messy way to do things. I looked at how the doctrine command does this itself and just copied over the relevant lines.
I extended from the Symfony WebTestCase and after the Kernel was created I just called my method which works exactly like the Doctrine load-fixtures command.
/**
* Load fixtures for all bundles
*
* @param Kernel $kernel
*/
private static function loadFixtures(Kernel $kernel)
{
$loader = new DataFixturesLoader($kernel->getContainer());
$em = $kernel->getContainer()->get('doctrine')->getManager();
foreach ($kernel->getBundles() as $bundle) {
$path = $bundle->getPath().'/DataFixtures/ORM';
if (is_dir($path)) {
$loader->loadFromDirectory($path);
}
}
$fixtures = $loader->getFixtures();
if (!$fixtures) {
throw new InvalidArgumentException('Could not find any fixtures to load in');
}
$purger = new ORMPurger($em);
$executor = new ORMExecutor($em, $purger);
$executor->execute($fixtures, true);
}
Just recently the bundle hautelook/AliceBundle expose two traits to help you solve the use case of loading fixtures in functional tests: RefreshDatabaseTrait and ReloadDatabaseTrait.
From the doc:
namespace App\Tests;
use Hautelook\AliceBundle\PhpUnit\RefreshDatabaseTrait;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
class NewsTest extends WebTestCase
{
use RefreshDatabaseTrait;
public function postCommentTest()
{
$client = static::createClient(); // The transaction starts just after the boot of the Symfony kernel
$crawler = $client->request('GET', '/my-news');
$form = $crawler->filter('#post-comment')->form(['new-comment' => 'Symfony is so cool!']);
$client->submit($form);
// At the end of this test, the transaction will be rolled back (even if the test fails)
}
}
And you are good !
'Nice programing' 카테고리의 다른 글
| WebKit / Safari 용 콘솔 API는 어디에 있습니까? (0) | 2020.11.24 |
|---|---|
| IDE를 사용할 때 Powershell에서 타사 실행 파일을 호출 할 때 오류 발생 (0) | 2020.11.24 |
| ExpressJS의 req.query 및 req.param (0) | 2020.11.24 |
| Amazon Lambda에서 moviepy, scipy 및 numpy 사용 (0) | 2020.11.24 |
| jQuery없이 'data-'속성에 액세스 (0) | 2020.11.23 |