我正在将一个大型Web应用程序从Python 2.7移植到Python 3.6。我已经管理了数据库迁移并使用2to3转换了代码,但是在运行测试套件时遇到了问题。对于大量测试,我会收到如下错误:
62 self = <django.db.backends.utils.CursorWrapper object at 0x7fc7d0abbeb8>
63 sql = 'SET CONSTRAINTS ALL IMMEDIATE', params = None
64
65 def execute(self, sql, params=None):
66 self.db.validate_no_broken_transaction()
67 with self.db.wrap_database_errors:
68 if params is None:
69 > return self.cursor.execute(sql)
70 E psycopg2.IntegrityError: insert or update on table "probex_historicalproject" violates forei
gn key constraint "probex_historicalpro_history_user_id_88371c5c_fk_auth_user"
71 E DETAIL: Key (history_user_id)=(303) is not present in table "auth_user".
72
73 ../../venv3/lib/python3.6/site-packages/django/db/backends/utils.py:62: IntegrityError
74
75 The above exception was the direct cause of the following exception:
76
77 self = <django.test.testcases.TestCase testMethod=__init__>
78
79 def _post_teardown(self):
80 """Performs any post-test things. This includes:
81
82 * Flushing the contents of the database, to leave a clean slate. If
83 the class has an 'available_apps' attribute, post_migrate isn't fired.
84 * Force-closing the connection, so the next test gets a clean cursor.
85 """
86 try:
87 > self._fixture_teardown()
88
89 ../../venv3/lib/python3.6/site-packages/django/test/testcases.py:925:
90 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
91 ../../venv3/lib/python3.6/site-packages/django/test/testcases.py:1081: in _fixture_teardown
92 connections[db_name].check_constraints()
93 ../../venv3/lib/python3.6/site-packages/django/db/backends/postgresql/base.py:243: in check_constraints
94 self.cursor().execute('SET CONSTRAINTS ALL IMMEDIATE')
95 ../../venv3/lib/python3.6/site-packages/raven/contrib/django/client.py:127: in execute
96 return real_execute(self, sql, params)
97 ../../venv3/lib/python3.6/site-packages/django/db/backends/utils.py:64: in execute
98 return self.cursor.execute(sql, params)
99 ../../venv3/lib/python3.6/site-packages/django/db/utils.py:94: in __exit__
100 six.reraise(dj_exc_type, dj_exc_value, traceback)
101 ../../venv3/lib/python3.6/site-packages/django/utils/six.py:685: in reraise
102 raise value.with_traceback(tb)
103 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
我尝试在同事的某些机器上运行测试,有些人在运行测试时没有问题,但是有些人和我自己有相同的问题。
也值得注意:如果我自己运行单个测试文件(即py.test /path/to/file
),则不会发生此错误。我认为它必须与测试之间处理数据库数据的方式有关。
这是一个失败的示例测试:
1
2 from django.utils import timezone
3 from tests.tests_probex.tests_python.testing_utilities import LoggedInTestCase
4 from tests.tests_probex.tests_python.factories import JobFactory
5 from probex.models import Profile, Tenant, Job
6 from probex.views.reports import build_tenant_report
7 from django.contrib.auth.models import User
8 import pytest
9
10 pytestmark = pytest.mark.xfail(reason="Not working in Python 3.6")
11
12
13 class TestTenantReport(LoggedInTestCase):
14 def setUp(self):
15 super(TestTenantReport, self).setUp()
16 self.end_date = timezone.now()
17 self.delta = timezone.timedelta(days=7)
18 self.start_date = self.end_date - self.delta
19
20 self.date = timezone.now() - timezone.timedelta(days=3)
21 self.job = JobFactory(absolute_num=1600, relative_num=1600, protocol=self.protocol, project=self.project, status='Co
mplete', created=self.date, submitter_id=self.user.id)
22
23 def test_returns_new_users(self):
24 users = User.objects.all()
25 for user in users:
26 user.date_joined = self.date
27 p = Profile.objects.get(user_id=user.id)
28 tenant = Tenant.objects.get(id=p.tenant_id)
29 tenant.app_scientist = self.user
30 user.save()
31 tenant.save()
32
33 report = build_tenant_report(self.user)
34 self.assertGreaterEqual(report['new_users'].count(), users.count())
LoggedInTestCase是Django TestCase的子类:
15 class LoggedInTestCase(TestCase):
16 def setUp(self):
17 self.user = User.objects.create_user(username='dummy@hotmail.com', email='dummy@hotmail.com', password="secret123")
18 self.user.user_permissions.add(Permission.objects.get(codename='add_job'))
19 self.user.user_permissions.add(Permission.objects.get(codename='change_job'))
20 self.user.user_permissions.add(Permission.objects.get(codename='add_project'))
21 self.user.user_permissions.add(Permission.objects.get(codename='add_user'))
22 self.user.user_permissions.add(Permission.objects.get(codename='change_user'))
23 self.tenant = Tenant.objects.create(name="testtenant")
24 self.user.profile.tenant = self.tenant
25 self.user.profile.save()
26 self.project = ProjectFactory(name="testproject", tenant=self.tenant, active=True, identifier='AAA')
27 self.protocol = ProtocolFactory()
28 self.root_term = TermFactory(is_root=True, acc='all')
29 self.login()
30
31 def login(self):
32 self.client.login(username='dummy@hotmail.com', password='secret123')
33
34 def logout(self):
35 self.client.logout()
36
37 def get_user(self):
38 return self.client
39
40 def permission_restricted(self, response, first_stop_url):
41 first_redirect, status_1 = response.redirect_chain[0]
42 second_redirect, status_2 = response.redirect_chain[1]
43 self.assertEqual(first_redirect, first_stop_url)
44 self.assertEqual(status_1, 302)
45 self.assertEqual(second_redirect, reverse('home'))
46 self.assertEqual(status_2, 302)
这些测试过去在Python 2.7下运行时可以通过,除了更新到3.6以外,我没有做太多改变。我仍然希望他们现在通过。如果有人有任何指点,我将不胜感激。这里是第一次海报。
答案 0 :(得分:0)
对于任何偶然发现此问题的人:提示是在违反的键中。 historicalproject
和history_user
与django-simple-history
包相关。我们最终将工厂男孩生成器更新为还包括历史工厂。这样就解决了问题。
答案 1 :(得分:0)
我在使用 django-simple-history
库时也遇到了这个问题。事实证明,我们的问题是由于多个模型在不同的数据库中相互依赖造成的。为了测试,我们更改了数据库路由器以将所有模型设置为在同一数据库中创建,这为我们解决了 IntegrityError
。我认为在不同的数据库中拥有历史和模型也可能是一个问题。