CakePHP Fixture Factories video tutorial

Hi community,

I would like to share here my series of videos on how to use the CakePHP Fixture Factories. This could seriously help you writting tests.

Here is the link to the package:

All the best!

1 Like

Hi @pabloelcolombiano,

I like the idea of this. My applications always have a lot of table cross-references, which means that when I’m unit testing controller actions, I often need to import a LOT of fixtures, so tests run pretty slowly.

My understanding is that this loads the fixtures then runs the test in a transaction. But a lot of my code already depends on transactions that wrap up multiple updates, and there are tests that re-read the original record to make sure it wasn’t changed in such a scenario. Is this sort of thing feasible in conjunction with this? It seems like maybe not, from what I know of transactions.

Thanks for the new videos.

Hi @Zuluru ,

thank you for your interest.

My understanding is that this loads the fixtures then runs the test in a transaction.

The package does change the way CakePHP manages its fixtures at all.

The package proposes you simply to persist data in your DB on the fly and in an intuitive way, so you can get rid of the CakePHP fixtures. There are no transactions involved.

For example, calling

$article = ArticleFactory::make(['title' => 'Foo'])->persist();

is equivalent to:

$ArticlesTable = TableRegistry::getTableLocator()->get('Articles');
$article = $ArticlesTable->newEntity(['title' => 'Foo']);

If your code supports the three lines above, it should get along with the Fixture Factories well.

The Fixture Factories offers additional helpers, such as saving associated data on the fly, or assigning default values to your fields with faker. This is particularly interesting for required fields.

The package also proposes to maintain the schema of your test DB the same way as you do for your regular DB, with migrations. See here the doc:

So in the end, you do not have to get rid of the fixtures, but you can. Tests using Fixture Factories are faster, because DB is persisted at the test’s need, and not at the need of all the other tests. If your test requries only one article in the DB, you create that article on the fly with the help of your ArticleFactory and all it’s helping methods that you created at your model’s need, and there will be only one article persisted for that test.

This also helps documenting your test: the reviewer sees what the developer inserted in the DB for that test, and does not have to struggle understanding what is stored the CakePHP fixtures, in particular for applications with a lot of table cross-references. The video on associations illustrates that:

I hope this answers your concern!

I wonder if I’m thinking of something else re the transactions.

Anyway, this sounds very useful. I definitely have some tests where I need to create records on the fly. But many others where the multiple levels of associations are very much required, and the same data runs a large number of tests, so it might be easier to leave those ones as fixtures. (It’s a very permission-driven system, where what information is on a given page depends on both roles and specific records, so many of the tests execute controller actions as different users to make sure only the right sections are shown, and that can easily involve 10 tables.) All the tables certainly need to be created in order to prevent JOIN errors, even if they’re empty. I guess I could add new test functions that populate all the tables as required for a particular set of tests, but then I’m not sure what I’m really gaining (given what I know about my test data set) over just using fixtures.

I’ll read up and check the video and see how this fits into my system.

I’m also facing a deep-structure situation and a need for a variety of roles to interact with the structures in nuanced ways. These are precisely the factors that make Fixture Factories so attractive to me.

With a little prep to make sure the factories will provide data to my required fields I can set up complex test data like this:

Now I can insure the Tenant Administrator can view and interact with their world of data but not parallel but un-affiliated worlds.

The tenant admin in this case is even backed up by a suite of records because of details I added to the setDefaultTemplate() method.

This feels very tight and focused to me. I’m excited!

The package has the advantage, that it never drops tables. So all your tables will be present, always. Dropping tables is to me a major disadvantage of the CakePHP fixtures, because it is useless, costly and as you wrote forces you to load fixtures just for the sake of having JOINs working.

This is why the package proposes in addition, to maintain the test DB with the same migrations the regular DB is maintained with. See the Migrator.

Conserning the user rights restriction: as @dreamingmind mentioned and shows in his exmple, the fixture factories are exactly made for such cases.

You can write in your UserFactory (or PersonFactory) class:

  • a method ->withRole(string $role),
  • or if a role, say the admin role, is particularly often used, a method ->asAdmin()
  • or whatever fits your business logic

and shape that user/person on the fly. As long as your self-made methods return $this, you can chain them.

Thanks. I hadn’t quite gotten that far in my thinking. This will make things very simple.