Yesterday, I talked about keeping the default factory state simple.
Today, I want to build on that discussion and talk specifically about relationships in factories.
When you're setting up a factory, it might be tempting to create a bunch of related records.
For example, if you're creating a User
record, and users can make payments, you might also want to generate several Payment
records for that user as well.
One reason this can be tempting is to make your tests less verbose.
You might reason that dozens of tests need a user with payments, so it's easier to just build a factory state like withPayments
to give me that by default.
This mindset starts out innocently enough, but over the life of a project, it can make your test suite slow and flaky.
Instead, my preference is to have each test set up the data it needs.
Maybe this test needs a user with only 1 payment, but the other test needs a user with 15 payments, to test some pagination logic.
Or payments might need specific dates, statuses, amounts, recipients, and so on. It's really hard to capture a useful set of defaults in a state that will apply to all your tests. So you end up overriding and customizing in the test anyway.
As I've stated before, it's okay for tests to be verbose and repetitive. I actually consider that a benefit not a drawback.
And Laravel makes it very easy to created related records in your tests, so maybe that factory state isn't really helping much anyways.
Here to help,
Joel
P.S. Here I am talking about tests again. If you have not yet written a test for you Laravel app, I'd love to pair with you and help you get started.