| layout | doc |
|---|---|
| title | 09-Data - Codeception - Documentation |
Tests should not affect each other. That's a rule of thumb. When tests interact with a database, they may change the data inside it, which would eventually lead to data inconsistency. A test may try to insert a record that has already been inserted, or retrieve a deleted record. To avoid test failures, the database should be brought back to its initial state before each test. Codeception has different methods and approaches to get your data cleaned.
This chapter summarizes all of the notices on clean-ups from the previous chapters and suggests the best strategies of how to choose data storage backends.
When we decide to clean up a database, we should make this cleaning as fast as possible. Tests should always run fast. Rebuilding the database from scratch is not the best way, but might be the only one. In any case, you should use a special test database for testing. Do not ever run tests on development or production databases!
Codeception has a Db module, which takes on most of the tasks of database interaction.
By default it will try to repopulate the database from a dump and clean it up after each test.
This module expects a database dump in SQL format. It's already prepared for configuration in codeception.yml:
{% highlight yaml %}
modules: config: Db: dsn: 'PDO DSN HERE' user: 'root' password: dump: tests/_data/your-dump-name.sql
{% endhighlight %}
After you enable this module in your test suite, it will automatically populate the database from a dump
and repopulate it on each test run. These settings can be changed through the populate and cleanup options,
which may be set to false.
In acceptance tests, your tests are interacting with the application through a web server. This means that the test
and the application work with the same database. You should provide the same credentials in the Db module
that your application uses, then you can access the database for assertions (seeInDatabase actions)
and to perform automatic clean-ups.
The Db module provides actions to create and verify data inside a database.
If you want to create a special database record for one test,
you can use haveInDatabase method of Db module:
{% highlight php %}
haveInDatabase('posts', [ 'title' => 'Top 10 Testing Frameworks', 'body' => '1. Codeception' ]); $I->amOnPage('/posts'); $I->see('Top 10 Testing Frameworks'); {% endhighlight %} `haveInDatabase` inserts a row with the provided values into the database. All added records will be deleted at the end of the test. If you want to check that a table record was created use [`seeInDatabase`](http://codeception.com/docs/modules/Db#haveInDatabase) method: {% highlight php %} amOnPage('/posts/1'); $I->fillField('comment', 'This is nice!'); $I->click('Submit'); $I->seeInDatabase('comments', ['body' => 'This is nice!']); {% endhighlight %} See the module [reference](http://codeception.com/docs/modules/Db) for other methods you can use for database testing. There are also modules for [MongoDb](http://codeception.com/docs/modules/MongoDb), [Redis](http://codeception.com/docs/modules/Redis), and [Memcache](http://codeception.com/docs/modules/Memcache) which behave in a similar manner. ### Sequence If the database clean-up takes too long, you can follow a different strategy: create new data for each test. This way, the only problem you might face is duplication of data records. [Sequence](http://codeception.com/docs/modules/Sequence) was created to solve this. It provides the `sq()` function which generates unique suffixes for creating data in tests. ## ORM modules Your application is most likely using object-relational mapping (ORM) to work with the database. In this case, Codeception allows you to use the ORM methods to work with the database, instead of accessing the database directly. This way you can work with models and entities of a domain, and not on tables and rows. By using ORM in functional and integration tests, you can also improve performance of your tests. Instead of cleaning up the database after each test, the ORM module will wrap all the database actions into transactions and roll it back at the end. This way, no actual data will be written to the database. This clean-up strategy is enabled by default, you can disable it by setting `cleanup: false` in the configuration of any ORM module. ### ActiveRecord Popular frameworks like Laravel, Yii, and Phalcon include an ActiveRecord data layer by default. Because of this tight integration, you just need to enable the framework module, and use its configuration for database access. Corresponding framework modules provide similar methods for ORM access: * `haveRecord` * `seeRecord` * `dontSeeRecord` * `grabRecord` They allow you to create and check data by model name and field names in the model. Here is the example in Laravel: {% highlight php %} haveRecord('posts', ['body' => 'My first blogpost', 'user_id' => 1]); $I->amOnPage('/posts/'.$id); $I->see('My first blogpost', 'article'); // check record exists $I->seeRecord('posts', ['id' => $id]); $I->click('Delete'); // record was deleted $I->dontSeeRecord('posts', ['id' => $id]); {% endhighlight %}