如何正确使用str类型对象的assertRaises()

时间:2017-01-25 21:14:44

标签: python django unit-testing django-models

我正在尝试编写一个简单的unittest来测试我的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 callabletaken_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)完全匹配,否则我希望测试失败

1 个答案:

答案 0 :(得分:0)

assertRaises用法如下:

self.assertRaises(InvalidOperation, Decimal, '25,34')
  除非callableObj引发类excClass的异常,否则

失败   当使用参数args和关键字参数kwargs调用时。

十进制是示例中的可调用,'25,34'是arg。

在您的情况下使用assertRaisesMessage:

def test_clean_username(self):
  self.assertRaisesMessage(
      AssertionError, '"{0}" unexpectedly found in "{1}"'.format(
          self.proposed_username,
          self.taken_usernames,
          )
      )
  

断言expect_message可以在凸起的消息中找到   异常。