Search code examples
pythondjangodatetimefactory-boy

Factory-boy fuzzy DateTimeField always the same date when using create_batch


I am using factory-boy for creating instances of a Django model, and I am always getting the same value returned when using factory.fuzzy.FuzzyDateTime.

Minimal example:

# factory class
class FooFactory(DjangoModelFactory):

    class Meta:
        # models.Foo has a dt_field that is a DateTimeField
        model = models.Foo

# creation of object, in unit tests
# I can't move the dt_field declaration
# into the factory definition since different
# unit tests use different start / end points
# for the datetime fuzzer
now = datetime.datetime.now(tz=pytz.timezone("America/New_York"))
one_week_ago = now - datetime.timedelta(days=7)
FooFactory.create_batch(
    10,
    dt_field=factory.fuzzy.FuzzyDateTime(
        start_dt=one_week_ago, end_dt=now
    )
)

When inspecting the Foo models after factory creation, the dt_field has the same date:

>>> [r.dt_field for r in Foo.objects.all()]
>>> [datetime.datetime(2022, 12, 10, 20, 15, 31, 954301, tzinfo=<UTC>), datetime.datetime(2022, 12, 10, 20, 15, 31, 961147, tzinfo=<UTC>),  
datetime.datetime(2022, 12, 10, 20, 15, 31, 967383, tzinfo=<UTC>), ...]

Solution

  • The core issue was that the model in my code had auto_now_add=True in the model definition. This is a Django internal that always overrides the provided value and therefore can't be used with factory-boy.

    Instead, the auto_now_add field is removed in favor of default=timezone.now, and the field can be fuzzed with factory-boy correctly.