I started using the factory_boy
package so I've set up some factories and wanted to test that the objects created don't raise any validation errors.
Here's the mixin I'm using that basically takes every factory from a module, creates an instance, then tests that there are no errors from .full_clean()
. The user fixtures that are loaded are 10 instances with IDs 1 to 10.
class FactoriesTestCaseMixin:
fixtures = [
'user/tests/fixtures/user.json',
]
module = None
def test_factories(self):
err_msg = '{name} caused errors:\n{errors}'
factories = [
(name, obj) for name, obj in inspect.getmembers(self.module, inspect.isclass)
if obj.__module__ == self.module.__name__
and not obj._meta.abstract
]
for factory in factories:
name = factory[0]
instance = factory[1]()
errors = None
try:
instance.full_clean()
except ValidationError as e:
errors = e
self.assertTrue(errors is None, err_msg.format(name=name, errors=errors))
The mixin would be used like this
from django.test import TestCase
from order import factories
class OrderFactoriesTestCase(FactoriesTestCaseMixin, TestCase):
module = factories
But I keep getting an IntegrityError
(traceback below) after the test successfully passes in regards to fixture teardown and I can't figure out how to get around it so my tests pass with no errors.
If I run the tests for each individual app there are no errors. I never get problems in any of my other model's fixtures that also have a created_by
field.
django.db.utils.IntegrityError: insert or update on table "product_product" violates foreign key constraint "product_product_created_by_id_96713f93_fk_user_user_id"
DETAIL: Key (created_by_id)=(13) is not present in table "user_user".
What I think is happening is that a previous test is creating a new user and the factory boy Iterator
is picking one of the new user IDs.. still not sure why this would cause an error after successfully passing the test.
created_by = factory.Iterator(User.objects.all())
The modules that cause this problem always have a SubFactory
to the ProductFactory
product = factory.SubFactory(ProductFactory)
Any suggestions on how to solve this?
Traceback (most recent call last):
File "/home/Development/project/venv/lib/python3.7/site-packages/django/test/testcases.py", line 274, in __call__
self._post_teardown()
File "/home/Development/project/venv/lib/python3.7/site-packages/django/test/testcases.py", line 1009, in _post_teardown
self._fixture_teardown()
File "/home/Development/project/venv/lib/python3.7/site-packages/django/test/testcases.py", line 1177, in _fixture_teardown
connections[db_name].check_constraints()
File "/home/Development/project/venv/lib/python3.7/site-packages/django/db/backends/postgresql/base.py", line 246, in check_constraints
self.cursor().execute('SET CONSTRAINTS ALL IMMEDIATE')
File "/home/Development/project/venv/lib/python3.7/site-packages/django/db/backends/utils.py", line 67, in execute
return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
File "/home/Development/project/venv/lib/python3.7/site-packages/django/db/backends/utils.py", line 76, in _execute_with_wrappers
return executor(sql, params, many, context)
File "/home/Development/project/venv/lib/python3.7/site-packages/django/db/backends/utils.py", line 84, in _execute
return self.cursor.execute(sql, params)
File "/home/Development/project/venv/lib/python3.7/site-packages/django/db/utils.py", line 89, in __exit__
raise dj_exc_value.with_traceback(traceback) from exc_value
File "/home/Development/project/venv/lib/python3.7/site-packages/django/db/backends/utils.py", line 82, in _execute
return self.cursor.execute(sql)
django.db.utils.IntegrityError: insert or update on table "product_product" violates foreign key constraint "product_product_created_by_id_96713f93_fk_user_user_id"
DETAIL: Key (created_by_id)=(12) is not present in table "user_user".
pytest-django Documentation. pytest-django is a plugin for pytest that provides a set of useful tools for testing Django applications and projects.
Django's unit tests use a Python standard library module: unittest . This module defines tests using a class-based approach.
I have a related problem which I've fixed by specializing _fixture_teardown
in my test case class.
_fixture_teardown
is implemented in django.test.testcases
to call the django command 'flush' which attempts to remove all data from the database. I don't know if this is useful for you or not. In my scenario where I persist the test database and use --keepdb
, it was causing problems.
As I don't need (or want) to flush the test database, I've simply specialized the method to do nothing. This solves my problem and might help solve yours.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With