Factory Bot offers a number of features to make test setup more convenient and less repetitive. Among these features is transient attributes.
Transient attributes are values that are passed into the factory but not directly set on the object’s attributes.
In order to illustrate how transient attributes can be useful, let’s look at an example where it’s painful not to use transient attributes.
PDF file attachment example
Let’s say we have an InsuranceDeposit
class that has PDF file attachments.
Perhaps we want to write some tests that depend on the content of an insurance deposit’s attached PDF files.
An example without using transient attributes
It would be tedious and repetitive to manually generate a PDF file on the spot every time we had a test case that needed a PDF file. Here’s what such code might look like:
This way is non-ideal because a) the code is hard to understand and b) if we use these steps end more than one place, we’ll have duplication.
We could of course conceivably extract that code into some sort of helper method. This would be an improvement over putting the code directly in our tests repetitively, but the remaining drawback is that then we’d have our test infrastructure code a little bit fragmented and scattered.
It would be nice if we could keep this code in the same place as all our other InsuranceDeposit
factory code.
An example with transient attributes
If we take advantage of transient attributes, we can gain both understandability and DRYness. Here’s what that might look like.
Now, in our test code, all we have to do is this:
This is much tidier than the original. If we want to see how pdf_content
works, we can open up the insurance_deposit
factory and have a look, but we aren’t burdened by these details when we just want to understand the high-level steps of the test.
Related articles
How I set up Factory Bot on a fresh Rails project
Nested factories in Factory Bot: what they are and how to use them
When to use Factory Bot’s traits versus nested factories
Great simple and to the point explanation! Thank you!