Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Practices for database testing in Symfony2? How to isolate?

What are the current best practices for testing database interaction with Symfony2? I have a simple CRUD setup and i want to make sure my testing is OK. Right now, i have 4 tests, each one making sure that create, update, delete and list actions are occurring ok.

I have two magic methods, __construct and __destruct, on my test case. Inside them, i call exec() with 'php app/console ...' in order to create the database, create the schema and later on drop the database. However, this is SLOW as hell and it happens all the time when i have more than one test case.

How should i proceed when it comes to database testing and isolating such tests?

like image 766
vinnylinux Avatar asked May 04 '12 23:05

vinnylinux


2 Answers

I think it's best to always start clean to be sure that tests are fully isolated. To do that I'm simply building the database structure before each test and than I'm filling it with fixtures needed for a given test.

Note that I'm only building needed database tables and I'm only inserting needed fixtures. It's a bit faster than loading a big database dump. It's also more clean as tests don't share fixtures (which makes them easier to maintain).

I have a base test case class called KernelAwareTest which helps me in building the schema. You can find it on gist: https://gist.github.com/1319290

setUp() boots the Symfony kernel and stores a reference to it in a class property (together with references to the DIC and the entity manager). Also a call to generateSchema() is made to generate the database schema (it uses Schema Tool from Doctrine).

By default it generates the database structure for all entities known to the entity manager. You can change this behaviour in your test class by overriding the getMetadatas() method.

P.S.: I tried using in memory database (sqlite) but it wasn't perfect. Anyway it's probably better to run tests against the database you use on production.

like image 55
Jakub Zalas Avatar answered Oct 17 '22 09:10

Jakub Zalas


Database testing is always slow as you need to create/drop your schema before/after each test. To avoid unnecessary operations, you could:

  • 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.

The schema will be created/droped only once for your tests case.

You can also setup doctrine to use an inmemory sqlite database (which is very fast):

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

Anyway, '_construct' and '_destruct' should never be used in phpunit test cases, instead you should use 'setUp' and 'tearDown'.

like image 27
JF Simon Avatar answered Oct 17 '22 10:10

JF Simon