Django 升级后单元测试失败
Unit tests fail after a Django upgrade
我正在尝试将 Django 项目从 1.8 版升级到 1.11 版。除了单元测试,几乎所有东西似乎都运行良好。我们有一个基础测试 class 继承自 Django TestCase 和 Tastypie mixin。基础 class 在 setUp() 中有一些这样的代码
class BaseApiTest(ResourceTestCaseMixin, django.test.TestCase):
def setUp(self):
super().setUp()
self.username = "secret_user"
self.password = "sekret"
self.email = "secret@mail.com"
self.first_name = "FirstName"
self.last_name = "LastName"
self.user = User.objects.create_superuser(
self.username,
self.username,
self.password
)
并且应用特定测试将继承基础测试并执行类似
的操作
class TheAPITest(BaseApiTest):
def setUp(self):
super().setUp()
# more setup goes here
所以,在 Django 1.8.x 下这工作正常。但是在 1.11.x 下所有这些都给我一个关于 User.objects.create_superuser() line
.
的错误
django.db.utils.InterfaceError: connection already closed
我一直在浏览发行说明,但 1.8 和 1.11 之间发生的事情太多了。有什么简单的东西是我遗漏的吗?
错误跟踪可能会有用。
但是目前在代码中我看到了这个错误:
self.user = User.objects.create_superuser(
self.username,
self.username, **this should be self.email**
self.password
)
我发现我的单元测试覆盖率存在多个问题,但为了回答我发布的问题,有两个不同的问题导致了我描述的错误。
Django 1.11 对其模型实例创建更加严格,我们有一些未更新到新模型结构的遗留测试代码。例如,如果你采用默认的 User 模型,在 Django 1.8 中你可以做
from django.contrib.auth.models import User
User.objects.create(username="something", password="something", something="something")
但在 Django 1.11 中它会引发异常 "TypeError: 'something' is an invalid keyword argument for this function"
。
第二个问题是 Django TestCase 将测试用例包装在两个单独的原子块中。这有助于将 class 级别设置与实例级别设置分开,但它也引入了一个微妙的问题。如果测试因数据库错误而崩溃,您将永远看不到该错误,因为它发生在原子测试级别而不是 class 原子级别。测试级别原子失败并且数据库连接被丢弃。在那之后,每个测试都会失败,并出现我看到的 django.db.utils.InterfaceError: connection already closed
错误。从 TestCase 切换到 TransactionTestCase 导致很多这些问题直接暴露在测试输出中。
我正在尝试将 Django 项目从 1.8 版升级到 1.11 版。除了单元测试,几乎所有东西似乎都运行良好。我们有一个基础测试 class 继承自 Django TestCase 和 Tastypie mixin。基础 class 在 setUp() 中有一些这样的代码
class BaseApiTest(ResourceTestCaseMixin, django.test.TestCase):
def setUp(self):
super().setUp()
self.username = "secret_user"
self.password = "sekret"
self.email = "secret@mail.com"
self.first_name = "FirstName"
self.last_name = "LastName"
self.user = User.objects.create_superuser(
self.username,
self.username,
self.password
)
并且应用特定测试将继承基础测试并执行类似
的操作class TheAPITest(BaseApiTest):
def setUp(self):
super().setUp()
# more setup goes here
所以,在 Django 1.8.x 下这工作正常。但是在 1.11.x 下所有这些都给我一个关于 User.objects.create_superuser() line
.
django.db.utils.InterfaceError: connection already closed
我一直在浏览发行说明,但 1.8 和 1.11 之间发生的事情太多了。有什么简单的东西是我遗漏的吗?
错误跟踪可能会有用。 但是目前在代码中我看到了这个错误:
self.user = User.objects.create_superuser(
self.username,
self.username, **this should be self.email**
self.password
)
我发现我的单元测试覆盖率存在多个问题,但为了回答我发布的问题,有两个不同的问题导致了我描述的错误。
Django 1.11 对其模型实例创建更加严格,我们有一些未更新到新模型结构的遗留测试代码。例如,如果你采用默认的 User 模型,在 Django 1.8 中你可以做
from django.contrib.auth.models import User
User.objects.create(username="something", password="something", something="something")
但在 Django 1.11 中它会引发异常 "TypeError: 'something' is an invalid keyword argument for this function"
。
第二个问题是 Django TestCase 将测试用例包装在两个单独的原子块中。这有助于将 class 级别设置与实例级别设置分开,但它也引入了一个微妙的问题。如果测试因数据库错误而崩溃,您将永远看不到该错误,因为它发生在原子测试级别而不是 class 原子级别。测试级别原子失败并且数据库连接被丢弃。在那之后,每个测试都会失败,并出现我看到的 django.db.utils.InterfaceError: connection already closed
错误。从 TestCase 切换到 TransactionTestCase 导致很多这些问题直接暴露在测试输出中。