【发布时间】:2017-01-25 21:14:44
【问题描述】:
我正在尝试编写一个简单的单元测试来测试我的fake_user's(通过FactoryBoy 创建)username 是否已经存在。 (即有人已经创建了一个具有相同用户名的用户)。
一个简单的测试版本如下:
# factories.py
import factory
class BaseUserFactory(factory.DjangoModelFactory):
"""A factory for creating User objects."""
username = factory.Faker('word')
email = factory.lazy_attribute(lambda x: '%s@email.com' % (x.username))
class Meta:
"""User factory Meta attributes."""
model = models.User
django_get_or_create = ('username', 'email')
一个简单的测试:
#test_user.py
from django.test import TestCase
from django.apps import apps
from . import factories
class TestAccountModels(TestCase):
"""Testing the User models."""
users = [user.username for user in models.User.objects.all()]
fake_user = factories.BaseUserFactory.create()
def test_username_available(self):
self.assertIn(self.fake_user.username, self.users)
现在就上下文而言,假设我的(已经存在的)username(s) 是“Brody”和“Sam”。当test_username_available 运行时,我会回来:
self.assertIn(self.fake_user.username, self.users)
AssertionError: 'suscipit' not found in ['Sam', 'Brody']
我的问题是这样的:
我想写一个测试来测试这个特定的错误。我尝试过这样的事情:
def test_clean_username(self):
self.assertRaises(
AssertionError, '"{0}" unexpectedly found in "{1}"'.format(
self.proposed_username,
self.taken_usernames,
)
)
但不断收到str object is not callable(在taken_usernames);我明白了,但似乎找不到解决方法
地点:
proposed_username = self.fake_user.username
self.taken_usernames = [self.user.username for self.user in self.user]
我尝试过以不同的方式重新工作,但似乎问题与此有关(从另一个答案,我在某个地方记下了这个,所以很遗憾没有链接):
You are using self.assertRaises() incorrectly.
It has to call the test function for you, in order to catch the exception
self.assertRaises(mouse16.BadInternalCallException,
stack.insertn, [8, 4, 12], 16)
You were passing in the result of the stack.insertn() call (which didn't raise an exception, but returned either None or an integer instead), and that return value is not callable.
An older version of the method accepted None for that argument as well, which is no longer supported, hence the deprecation warning when None is passed in versus an integer.
The better way is to use self.assertRaises() as a context manager:
with self.assertRaises(mouse16.BadInternalCallException):
stack.insertn([8, 4, 12], 16
我需要使用上下文管理器吗?我觉得这应该更容易,我让它变得比它必须的更难。最初我试图从模型中提取属性。dict 但最终接受了别人的建议并使用了一些列表理解。
这在 TestCase 方法/类之外有效。我觉得应该有一个简单的解决方法,但我对 python/django 的了解还不够。
感谢您的帮助!
编辑:下面提供的答案似乎很有希望,但无论如何似乎都通过了。我希望测试失败,除非正则表达式(即错误消息)和错误类型(在本例中为 AssertionError)完全匹配
【问题讨论】:
-
但是您似乎没有将任何类型的函数传递给 assertRaises,只是两组用户名。你期望发生什么?
-
不管怎样,你为什么要测试另一个测试引发的错误?
-
好吧,我本身不想进行第二次测试。我在想测试这个特定的错误会比仅仅测试 abc 中是否存在 xyz 更好。只是认为这是一种更好的做法,可以说是测试错误..
-
基本上我想测试当一个人尝试添加一个存在或不存在于数据库中的用户名时会弹出的断言错误。我希望 .format 可以让我在 assertRaises 中插入“假”和“真实”名称,但显然没有正确使用它
标签: python django unit-testing django-models