Skip to content

Latest commit

 

History

History
147 lines (92 loc) · 6.72 KB

File metadata and controls

147 lines (92 loc) · 6.72 KB
layout doc
title Working with Data - Codeception - Documentation

Working with Data

Tests should not affect each other. That's a rule of thumb. When tests interact with database, they may change 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 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 cleaning 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 database!

Automatic Cleanup

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.

The Db module is a rough tool. It works for any type of database supported by PDO. It could be used for all of the tests if it wasn't so slow. Loading a dump can take a lot of time that can be saved by using other techniques. When your test and application share the same database connection, as may be the case in functional and unit tests, the best way to speed up everything is to put all of the code in transaction, rolled back when test ends. In acceptance tests, different database connections are used, you can speed up tests by using SQLite file database. Alternatively, you can avoid recreating database on every test, but cleaning up all updates after the test.

Separate connections

In acceptance tests, your test is interacting with the application through a web server. There is no way to receive a database connection from the web server. This means that the test and the application will work with the same database but on different connections. Provide in the Db module the same credentials that your application uses, and then you can access the database for assertions (seeInDatabase actions) and perform automatic cleanups.

Shared connections

When an application or its parts are run within the Codeception process, you can use your application connection in your tests. If you can access the connection, all database operations can be put into one global transaction and rolled back at the end. That will dramatically improve performance. Nothing will be written to the database at the end, thus no database repopulation is actually needed.

ORM modules

If your application is using an ORM like Doctrine or Doctrine2, connect the respective modules to the suite. By default they will cover everything in a transaction. If you use several database connections, or there are transactions not tracked by the ORM, that module will be useless for you.

An ORM module can be connected with a Db module, but by default both will perform cleanup. Thus you should explicitly set which module is used:

In tests/functional.suite.yml:

{% highlight yaml %}

modules: enabled: - Db: cleanup: false
- Doctrine2: depends: Symfony2 - \Helper\Functional

{% endhighlight %}

Still, the Db module will perform database population from a dump before each test. Use populate: false to disable it.

Dbh module

If you use PostgreSQL, or any other database which supports nested transactions, you can use the Dbh module. It takes a PDO instance from your application, starts a transaction at the beginning of the tests, and rolls it back at the end. A PDO connection can be set in the bootstrap file. This module also overrides the seeInDatabase and dontSeeInDatabase actions of the Db module.

To use the Db module for population and Dbh for cleanups, use this config:

{% highlight yaml %}

modules: enabled: - Db: cleanup: false - Dbh - \Helper\Functional

{% endhighlight %}

Please, note that Dbh module should go after the Db. That allows the Dbh module to override actions.

Fixtures

Fixtures are sample data that we can use in tests. This data can be either generated, or taken from a sample database. Fixtures can be defined in separate PHP file and loaded in tests.

Fixtures for Acceptance and Functional Tests

Let's create fixtures.php file in tests/functional and load data from database to be used in tests.

{% highlight php %}

{% endhighlight %}

Fixture usage in a sample acceptance or functional test:

{% highlight php %}

amLoggedAs($john); $I->see('Welcome, John'); ?>

{% endhighlight %}

Also you can use the Faker library to create test data within a bootstrap file.

Per Test Fixtures

If you want to create 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 provided values into database. All added records will be deleted in the end of a test. In MongoDB module we have similar haveInCollection method.

Conclusion

Codeception is not abandoning the developer when dealing with data. Tools for database population and cleanups are bundled within the Db module. To manipulate sample data in a test, use fixtures that can be defined within the bootstrap file.