One of the greatest things of testing Ruby on Rails applications was usage of Factories, managed by FactoryGirl. It changed the way the test data was managed in test. Instead of defining fixtures one by one, in a single .yml
configuration, it allowed to generate required models per test. This concept is very convenient, however it is not widespread in PHP world. Probably, this was because, there is no single ORM in PHP, like ActiveRecord is for Ruby. We have Doctrine, Eloquent, and each major framework has its own ORM layer, so that we it is pretty hard to deal with models of those frameworks in one manner.
But it looks like factories finally came to PHP! The League of Extraordinary Packages produced a great package, self-claimed as factory_girl for PHP. Meet Factory Muffin. It allows simple generation of database records for integration and functional testing. Let’s see how it can be used with Codeception.
Setup in Codeception
At first lets add league/factory-muffin": "~2.0
to composer.json
:
Then we execute composer install
.
As you may noticed, FactoryMuffin uses awesome Faker library for generating random data for models.
For using factories inside tests we will create FactoryHelper
:
We will define factories in the _initialize
method of FactoryHelper
.
Let’s say we have two models, Post
and User
in application. This is how we specify rules for generating new objects of these models.
This is how generation of Post and User is defined. From the box, Muffin is designed to work with ActiveRecord models, and with Eloquent in particular. So you can use it in Yii, Phalcon, yet we will demonstrate its usage in Laravel application. FactoryMuffin can also be customized to work with Doctrine as well.
Using Factories in Laravel
To use FactoryMuffin in Laravel functional tests we need to create additional methods in FactoryHelper
for generating and saving records: havePosts
and haveUsers
methods. They will populate database with number of records specified. We will need to clean up those records at the end of a test.
By including FactoryHelper to the functional suite config, we can use it inside the actor ($I
) object.
This allows us to test features like pagination. For instance, we can check that only 20 posts are listed on a page:
Source code of this example is on GitHub.
Factories in Unit Tests
Factories can also be used in unit testing. Let’s say user can create posts, and in order to optimize queries we are saving number of user posts in num_posts
column of users
table. We are going to test that this column is updated each time a new post by user is created.
We will need one more method added into FactoryHelper
class:
After we include FactoryHelper
into unit suite we can use its methods in tests:
Conclusion
As you see, factories make your tests clean and expressive. Forget about managing test data manually, forget about fixtures. Use FactoryMuffin.