Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django test IntegrityError in fixture teardown

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".
like image 979
bdoubleu Avatar asked Sep 13 '19 12:09

bdoubleu


People also ask

Does Django test use Pytest?

pytest-django Documentation. pytest-django is a plugin for pytest that provides a set of useful tools for testing Django applications and projects.

Does Django use Pytest or Unittest?

Django's unit tests use a Python standard library module: unittest . This module defines tests using a class-based approach.


1 Answers

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.

like image 121
Paul Whipp Avatar answered Sep 25 '22 05:09

Paul Whipp