장고 메시지 단위 테스트는 어떻게하나요?


78

내 django 애플리케이션에서 작업을 수행 한 다음 응답에서 메시지를 확인하는 단위 테스트를 작성하려고합니다.

내가 말할 수있는 한, 이것을하는 좋은 방법은 없습니다.

CookieStorage 저장 방법을 사용하고 있으며 다음과 유사한 작업을 수행하고 싶습니다.

    response = self.client.post('/do-something/', follow=True)
    self.assertEquals(response.context['messages'][0], "fail.")

문제는 내가 돌려받는 건

print response.context['messages']
<django.contrib.messages.storage.cookie.CookieStorage object at 0x3c55250>

이것을 유용한 것으로 바꾸려면 어떻게해야합니까, 아니면 모두 잘못하고 있습니까?

고마워, 다니엘


작동하지만 ... 진지하게? response.context [ 'messages'] ._ get () [0] [0] .__ dict __ [ 'message']
dvydra

5
이 아름다운 코드를 아름다운 함수로 캡슐화 assert_has_message(response, msg_text)하고 그 후에 원하는 모든 곳에서 사용할 수 있습니다. 메시지에 액세스하는 더 좋은 방법을 찾으면 한 곳에서 기능을 수정하기 만하면됩니다.
nkrkv

@nailxx, 그래, 기본적으로 내가 한 일이지만 기분이 나쁘다 :)
dvydra

3
이것은 또한 작동합니다. messages_list = CookieStorage(response)._decode(response.cookies['messages'].value) 이것은 django.contrib.messages.storage.base.Message 객체 목록을 제공합니다.
dvydra

@dvydra 만약 당신이 아직 주위에 있다면, 당신은 받아 들여진 대답을 바꾸고 싶을지도 모릅니다
OrangeDog

답변:


90

정말 쉬운 접근 방식을 찾았습니다.

response = self.client.post('/foo/')
messages = list(response.context['messages'])
self.assertEqual(len(messages), 1)
self.assertEqual(str(messages[0]), 'my message')

컨텍스트가없는 응답에서 메시지를 확인해야하는 경우 다음을 사용할 수 있습니다.

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')

대체 저장소는 인덱싱을 지원하지 않지만 반복 가능합니다.


2
나는 또한 그 self.assertEqual(m[0].message, 'my message')작동 을 발견했다
Aaron Lelevier

6
컨텍스트가없는 응답 (예 : 리디렉션)에서 메시지를 확인해야하는 경우 다음을 사용할 수 있습니다.list(r.wsgi_request._messages)
BenjaminGolder

6
새 버전에서는 [0]이 작동하지 않는 것 같습니다 : *** TypeError: 'FallbackStorage' object does not support indexing. 그러나 Iterable이며 모든 for m in messages구성을 사용할 수 있습니다 .
Dunatotatos

2
@Jonathan 은 테스트 케이스 dir()내부의 대화 형 디버거 ( import ipdb; ipdb.set_trace()) 내부에서 사용합니다.
BenjaminGolder


19

에서 장고 문서 :

템플릿 외부에서 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)


17

이것은 나를 위해 작동합니다 (모든 메시지 표시).

print [m.message for m in list(response.context['messages'])]

또한 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)))

2
명시 적 ResponseContext 또는 TemplateResponse (ResponseContext 생성을 시도 함)에서만 작동합니다.
pkoch

3

최신 정보

내 원래 대답은 django가 여전히 1.1 정도일 때 작성되었습니다. 이 답변은 더 이상 관련이 없습니다. 더 나은 솔루션은 @daveoncode의 답변 을 참조하십시오 .

원래 답변

나는 이것을 테스트하기 위해 실험을했다. MESSAGE_STORAGE내 프로젝트 중 하나의 설정을로 변경하고 '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])

의 가치가 시도합니다.


27
user.get_and_delete_messages ()는 Django 1.2에서 더 이상 사용되지 않습니다
Dave

0

교착 상태의 간단한 버전 :

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)
                )

지정된 텍스트가되어 내 버전 검사로이 정확히 동일하지 않습니다 포함 에이 (하지 동일하지 메시지의 / 아무것도에). 나는 그것을 선호한다. 그래서 나는 메시지의 핵심 부분을 테스트 케이스에 입력하고 메시지 텍스트가 테스트를 중단하지 않고 업데이트되도록 허용하기 만하면된다.
anttikoo

0

응답 메시지 수 및 내용의 유효성 검사를위한 테스트 도우미

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)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.