Всем добрый день,
За последние несколько дней я много изучал Test Driven Development и решил, что мне тоже нужно это изучить. Хотя я не могу понять, как это сделать.
Мой проект зависит от структуры Symfony2.1.6 и Doctrine, поэтому у меня есть несколько таблиц базы данных, которые необходимо заполнить.
Книга (1, n) – (0, n) Жанр
Теперь, если я хочу вставить запись в жанре, мне сначала нужно написать тест, чтобы все было вставлено так, как должно (или я ошибаюсь?)
Проблема в том, что я не знаю, как получить доступ к моей базе данных, поскольку она управляется инфраструктурой.
Единственное, что я мог найти, было с LiipFunctionalTestBundle https://github.com/liip/LiipFunctionalTestBundle, который создает и восстанавливает временную базу данных каждый раз, когда я запускаю тест. Я настроил все в соответствии с инструкциями.
Изменить: Мое приложение / config / config_test.yml выглядит следующим образом:
imports: - { resource: config_dev.yml } framework: test: ~ session: storage_id: session.storage.filesystem liip_functional_test: ~ web_profiler: toolbar: false intercept_redirects: false swiftmailer: disable_delivery: true liip_functional_test: cache_sqlite_db: true doctrine: dbal: default_connection: default connections: default: driver: pdo_sqlite path: %kernel.cache_dir%/test.db
Итак, теперь у меня есть класс GenreTest:
У Лиипа нет документации, поэтому я просто попробовал такой подход.
use Liip\FunctionalTestBundle\Test\WebTestCase; class GenreTest extends WebTestCase { public function testInsert() { $container = $this->getContainer(); $registry = $container->get('doctrine'); $em = $registry->getEntityManager(null); $genre = new Genre(); $genre->setName("testGenre"); $em->persist($genre); $em->flush(); $result = $em->createQuery("SELECT g FROM QkprodMangressBundle:Genre g ". "WHERE g.name = :name") ->setParameter("name", $genre->getName()) ->getResult(); $this->assertEqual($result[0]->getName(), $genre->getName()); } }
phpunit -c web /
PDOException: не удалось найти драйвер /…/Mangress/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOConnection.php:36 /…/Mangress/vendor/doctrine/dbal/lib/Doctrine/DBAL /Driver/PDOSqlite/Driver.php: 60 /…/Mangress/vendor/doctrine/dbal/lib/Doctrine/DBAL/Connection.php:350 /…/Mangress/vendor/doctrine/dbal/lib/Doctrine /DBAL/Connection.php:949 /…/Mangress/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php:306 /…/Mangress/vendor/doctrine/orm/lib/Doctrine/ORM /EntityManager.php:355 /…/Mangress/app/cache/test/jms_diextra/doctrine/EntityManager_510128d0a5878.ph p: 362 /…/Mangress/src/Qkprod/MangressBundle/Tests/Entity/GenreTest.php: 27 НЕИСПРАВНОСТИ! Тесты: 3, Утверждения: 1, Ошибки: 1.
Большой вопрос, который у меня возникает, – это … как я могу проверить что-то подобное? Или я даже тестирую связь с базой данных? Подделка связи с базой данных через пользовательскую реализацию не кажется мне хорошей идеей, потому что она будет использовать ORM и Doctrine в производственной среде.
Извините, здесь оказался маленький роман.
Я почти полностью решил свою проблему:
Установите драйверы, необходимые для db-связи;)
PDO_SQLITE driver нет .. что делать?
sudo apt-get install php5-sqlite
Восстановить схему на каждом тестовом прогоне
https://stackoverflow.com/a/10463614/1177024
Это мое тестирование класса против базы данных
namespace Qkprod\MangressBundle\Entity; use Qkprod\MangressBundle\Entity\Genre; use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; private $em; /** * Sets up environment for testing * Regenerates Database schema before every test-run */ public function setUp() { static::$kernel = static::createKernel(); static::$kernel -> boot(); $this -> em = static::$kernel->getContainer() ->get('doctrine') ->getEntityManager(); $this->regenerateSchema(); } protected function tearDown() { parent::tearDown(); $this -> em -> close(); } /** * Drops current schema and creates a brand new one */ protected function regenerateSchema() { $metadatas = $this->em->getMetadataFactory()->getAllMetadata(); if (!empty($metadatas)) { $tool = new \Doctrine\ORM\Tools\SchemaTool($this->em); $tool -> dropSchema($metadatas); $tool -> createSchema($metadatas); } } public function testInsert() { $genre = new Genre(); $genre -> setName("testGenre"); $this -> em -> persist($genre); $this -> em -> flush(); $result = $this -> em -> createQuery("SELECT g " . " FROM QkprodMangressBundle:Genre g " . " WHERE g.name = :name") -> setParameter("name", $genre -> getName()) -> getResult(); $this -> assertEquals($result[0] -> getName(), $genre -> getName()); } }
Не удалось заставить LiipBundle работать, но вы можете увеличить скорость невероятно, установив symfony, чтобы сохранить SQL-файл sqlite в памяти вместо файловой системы. https://stackoverflow.com/a/10460139/1177024
# app/config/config_test doctrine: dbal: driver: pdo_sqlite path: :memory: memory: true
Или, возможно, только один раз создайте схему и вместо ее воссоздания просто переопределите базу данных новой резервной копией.
Надеюсь, это сократит поиск некоторых людей, имеющих ту же проблему! Спасибо всем, кто помогает мне в пути 🙂 Вы здорово!
Попробуйте еще раз с документами symfony.
http://symfony.com/doc/2.0/cookbook/testing/doctrine.html
Или вы можете изменить конструктор TestCase с помощью:
public function __construct() { $kernelNameClass = $this->getKernelClass(); $kernel = new $kernelNameClass('test', true); $kernel->boot(); $this->em = $kernel->getContainer()->get('doctrine.orm.entity_manager'); }
Тогда вы будете использовать
$this->em->createQuery($dql);
и т.п.
Вы можете подключиться внутри метода setUp()
:
/** * @var \Doctrine\ORM\EntityManager */ private $em; /** * {@inheritDoc} */ public function setUp() { static::$kernel = static::createKernel(); static::$kernel->boot(); $this->em = static::$kernel->getContainer() ->get('doctrine') ->getManager() ; }
Вот пример из книги Symfony 2.1