Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/360.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何对django消息进行单元测试?_Python_Django_Unit Testing_Django Testing - Fatal编程技术网

Python 如何对django消息进行单元测试?

Python 如何对django消息进行单元测试?,python,django,unit-testing,django-testing,Python,Django,Unit Testing,Django Testing,在我的django应用程序中,我试图编写一个单元测试来执行一个操作,然后检查响应中的消息 就我所知,没有什么好办法 我正在使用CookieStorage存储方法,我想做一些类似于以下的事情: response = self.client.post('/do-something/', follow=True) self.assertEquals(response.context['messages'][0], "fail.") from django.contrib.messag

在我的django应用程序中,我试图编写一个单元测试来执行一个操作,然后检查响应中的消息

就我所知,没有什么好办法

我正在使用CookieStorage存储方法,我想做一些类似于以下的事情:

    response = self.client.post('/do-something/', follow=True)
    self.assertEquals(response.context['messages'][0], "fail.")
from django.contrib.messages import get_messages
messages = list(get_messages(response.wsgi_request))
self.assertEqual(len(messages), 1)
self.assertEqual(str(messages[0]), 'my message')
问题是,我得到的只是一个

print response.context['messages']
<django.contrib.messages.storage.cookie.CookieStorage object at 0x3c55250>
print response.context['messages']
我怎样才能把它变成有用的东西,还是我做错了

谢谢, 丹尼尔

更新 我最初的答案是在django还是1.1左右的时候写的。这一答案不再相关。有关更好的解决方案,请参阅@daveoncode

原始答案 我做了一个实验来测试这个。我将我的一个项目中的
MESSAGE\u存储设置更改为
'django.contrib.messages.STORAGE.cookie.CookieStorage'
,并执行了我编写的检查消息的测试。成功了

与您所做的主要区别在于我检索消息的方式。见下文:

def test_message_sending(self):
    data = dict(...)
    response = self.client.post(reverse('my_view'), data)
    messages = self.user.get_and_delete_messages()

    self.assertTrue(messages)
    self.assertEqual('Hey there!', messages[0])
这可能值得一试。

这对我有用(显示所有消息):

这里还有我在从Django的TestCase继承的测试类中拥有的几个实用方法。如果希望将它们作为函数,请删除
self
参数,并将
self.fail()
替换为
raise

def assert_message_count(self, response, expect_num):
    """
    Asserts that exactly the given number of messages have been sent.
    """

    actual_num = len(response.context['messages'])
    if actual_num != expect_num:
        self.fail('Message count was %d, expected %d' %
            (actual_num, expect_num))

def assert_message_contains(self, response, text, level=None):
    """
    Asserts that there is exactly one message containing the given text.
    """

    messages = response.context['messages']

    matches = [m for m in messages if text in m.message]

    if len(matches) == 1:
        msg = matches[0]
        if level is not None and msg.level != level:
            self.fail('There was one matching message but with different'
                'level: %s != %s' % (msg.level, level))

        return

    elif len(matches) == 0:
        messages_str = ", ".join('"%s"' % m for m in messages)
        self.fail('No message contained text "%s", messages were: %s' %
            (text, messages_str))
    else:
        self.fail('Multiple messages contained text "%s": %s' %
            (text, ", ".join(('"%s"' % m) for m in matches)))

def assert_message_not_contains(self, response, text):
    """ Assert that no message contains the given text. """

    messages = response.context['messages']

    matches = [m for m in messages if text in m.message]

    if len(matches) > 0:
        self.fail('Message(s) contained text "%s": %s' %
            (text, ", ".join(('"%s"' % m) for m in matches)))

僵局的简单版本:

class TestCaseMessagesMixture(object):
    def assertMessageCount(self, response, expect_num):
        """
        Asserts that exactly the given number of messages have been sent.
        """

        actual_num = len(response.context['messages'])
        if actual_num != expect_num:
            self.fail('Message count was %d, expected %d' %
                    (actual_num, expect_num)
                )

    def assertMessageEqual(self, response, text):
        """
        Asserts that the response includes the message text.
        """

        messages = [m.message for m in response.context['messages']]

        if text not in messages:
            self.fail(
                'No message with text "%s", messages were: %s' % 
                    (text, messages)
                )

    def assertMessageNotEqual(self, response, text):
        """
        Asserts that the response does not include the message text.
        """

        messages = [m.message for m in response.context['messages']]

        if text in messages:
            self.fail(
                'Message with text "%s" found, messages were: %s' % 
                    (text, messages)
                )

我发现了一个非常简单的方法:

response = self.client.post('/foo/')
messages = list(response.context['messages'])
self.assertEqual(len(messages), 1)
self.assertEqual(str(messages[0]), 'my message')
如果需要检查没有上下文的响应上的消息,可以使用以下选项:

    response = self.client.post('/do-something/', follow=True)
    self.assertEquals(response.context['messages'][0], "fail.")
from django.contrib.messages import get_messages
messages = list(get_messages(response.wsgi_request))
self.assertEqual(len(messages), 1)
self.assertEqual(str(messages[0]), 'my message')
回退存储不支持索引,但它是一个可索引的存储

来自:

在模板之外,您可以使用get_messages()

所以,你可以这样写:

from django.contrib.messages import get_messages

[...]

messages = [m.message for m in get_messages(response.wsgi_request)]
self.assertIn('My message', messages)


测试助手用于验证响应消息计数和内容

def get_response_messages(self, response):
    from django.contrib.messages import get_messages
    return list(get_messages(response.wsgi_request))


def check_response_messages(self, response, message_index=None, message_value=None, exp_count=None):
    messages = self.get_response_messages(response)
    if exp_count is not None:
        self.assertEqual(len(messages), exp_count)

    if message_index is not None:
        message = messages[message_index]
        self.assertIn(message_value, str(message))
可以这样使用吗

message_value = "You can not switch to another type of account"
self.check_response_messages(response, exp_count=1, message_index=0, message_value=message_value)

这是可行的,但是。。。认真地response.context['messages'].\u get()[0][0]。\u dict\u['message']您可以尝试将这段不太漂亮的代码封装在漂亮的函数
assert\u has\u message(response,msg\u text)
中,并在此后的任何地方使用它。如果你能找到更好的方式来访问消息,你只需在一个地方修改函数。@nalxx,是的,这基本上就是我所做的,但它让我感到不舒服:)这同样有效:
messages\u list=CookieStorage(response)。\u decode(response.cookies['messages'].value)
这将为您提供django.contrib.messages.storage.base.Message对象的列表。@dvydra如果您还在,您可能希望更改接受的应答器仅适用于显式ResponseText或TemplateResponse(尝试构造ResponseText)。user.get_和_delete_messages()在Django 1.2中被弃用这与我的版本不完全相同,因为我的版本检查给定文本是否包含在(不等于)任何消息中。我更喜欢这种方式,这样我只需要在测试用例中输入消息的关键部分,并允许在不破坏测试的情况下更新消息文本。我还发现,
self.assertEqual(m[0]。message,'my message')
在需要检查无上下文(如重定向)响应上的消息时起作用,您可以使用
list(r.wsgi\u request.\u messages)
看起来[0]在新版本上不起作用:
***TypeError:'FallbackStorage'对象不支持索引
。但是,它是一个Iterable,您可以对消息中的m使用任何
构造。@Jonathan在测试用例中的交互式调试器(
import ipdb;ipdb.set_trace()
)中使用
dir()
。@Jonathan