Django Error when using multiple fixtures and factory.Iterator
See original GitHub issueWe have several models with ForeignKey
.
These models have factories using factory.Iterator
on the same tables (Ex: Countries.objects.all()
, Currencies.objects.all()
, etc.)
Ex:
CountryID = factory.Iterator(models.Countries.objects.all())
CurrencyID = factory.Iterator(models.Currencies.objects.all())
We have multiple django test cases using different fixtures with different data for these tables (Ex: A fixture with the country “Afghanistan”, another fixture with “Canada” and “USA”).
With SQLite it gives this kind of error:
<AppName>.models.DoesNotExist: Countries matching query does not exist.
With MySQL it gives this kind of error:
django.db.utils.IntegrityError: (1452, 'Cannot add or update a child row: a foreign key constraint fails (`test_<AppName>`.`SomeModel`, CONSTRAINT `SomeModel_CurrencyID_2734797b_fk_Currencies_id` FOREIGN KEY (`CurrencyID`) REFERENCES `Currencies` (`id`))')
Tested with factory-boy
2.7.0 and 2.8.1 with django
1.9.
When many tests are ran the bug can occur. When running the tests individually they succeed.
I assume there is a problem with the iterator when unloading and loading fixtures on these table. The iterator may not be reinitialized between tests cases.
Workarounds:
- Use the same data for these tables (either same fixture or same data in different fixtures)
- Replace the iterator with a lamda that will randomly select a row in the table
- Replace the iterator with a subfactory (but does not work well with some models)
Issue Analytics
- State:
- Created 7 years ago
- Reactions:6
- Comments:5 (3 by maintainers)
Top GitHub Comments
Thanks for the bug report. Afraid I’m not very familiar with how the Django ORM resolves foreign keys, so I’ll let @rbarrois handle this one.
We had a similar issue. After debugging we see that the error is caused by
QuerySet
’s stale cache when it is used with eitherfactory.Iterator
orfactory.fuzzy.FuzzyChoice
.QuerySet
s will cache data once they are evaluatedfactory.Iterator
won’t evaluate theQuerySet
until it is used for the first time (which is useful to prevent other bugs)setUp
method, some test data is created that will be removed once the suite is runQuerySet
will be cached with the data that is created for that test caseQuerySet
is possible butfactory.Iterator
wraps it with another layer which makes it impossibleMinimal Example
Running each test case separately (or in parallel) doesn’t trigger an error but running them sequentially does.
Our Workaround
We created a new one that checks if the model instance is stale and resets the Queryset if so.
I’d like to create a PR if the solution makes sense.