Подтвердить что ты не робот

Правильный способ тестирования сигналов Django

Я пытаюсь проверить переданный сигнал и его обеспечение_арги. Сигнал запускается внутри contact_question_create только после отправки формы.

My TestCase - это что-то вроде:

    def test_form_should_post_proper_data_via_signal(self):
        form_data = {'name': 'Jan Nowak'}
        signals.question_posted.send(sender='test', form_data=form_data)
        @receiver(signals.question_posted, sender='test')
        def question_posted_listener(sender, form_data):
            self.name = form_data['name']
        eq_(self.name, 'Jan Nowak')

Это правильный способ проверить этот сигнал? Любые лучшие идеи?

4b9b3361

Ответ 1

Я решил проблему самостоятельно. Я думаю, что лучшее решение следующее:

    def test_form_should_post_proper_data_via_signal(self):
        # define the local listener
        def question_posted_listener(sender, form_data, **kwargs):
            self.name = form_data['name']

        # prepare fake data
        form_data = {'name': 'Jan Nowak'}

        # connect & send the signal
        signals.question_posted.connect(question_posted_listener, sender='test')
        signals.question_posted.send(sender='test', form_data=form_data)

        # check results
        eq_(self.name, 'Jan Nowak')

Ответ 2

Самый простой способ сделать то, что вы просили в 2015 году:

from unittest.mock import patch

@patch('full.path.to.signals.question_posted.send')
def test_question_posted_signal_triggered(self, mock):
    form = YourForm()
    form.cleaned_data = {'name': 'Jan Nowak'}
    form.save()

    # Check that your signal was called.
    self.assertTrue(mock.called)

    # Check that your signal was called only once.
    self.assertEqual(mock.call_count, 1)

    # Do whatever else, like actually checking if your signal logic did well.

И с этим вы только что протестировали, что ваш сигнал был правильно запущен.

Ответ 3

У меня есть альтернативное предложение, использующее библиотеку mock, которая теперь является частью стандартной библиотеки unittest.mock в Python 3 (если вы используете Python 2, вам придется pip install mock).

try:
    from unittest.mock import MagicMock
except ImportError:
    from mock import MagicMock

def test_form_should_post_proper_data_via_signal(self):
    """
    Assert signal is sent with proper arguments
    """ 

    # Create handler
    handler = MagicMock()
    signals.question_posted.connect(handler, sender='test')

    # Post the form or do what it takes to send the signal
    signals.question_posted.send(sender='test', form_data=form_data)

    # Assert the signal was called only once with the args
    handler.assert_called_once_with(signal=signals.question_posted, form_data=form_data, sender="test")

Основная часть предложения заключается в том, чтобы смоделировать приемник, а затем проверить, передается ли ваш сигнал этому приемнику и вызывается только один раз. Это замечательно, особенно если у вас есть пользовательские сигналы или вы написали методы, которые отправляют сигналы, и вы хотите убедиться, что они отправляются в ваших модульных тестах.

Ответ 4

Вам необходимо:

  • утверждать, что сигнал был испущен с соответствующими аргументами и,
  • определенное количество раз и,
  • в соответствующем порядке.

Вы можете использовать mock_django приложение, которое обеспечивает mock для сигналов.

Пример:

from mock import call


def test_install_dependency(self):
    with mock_signal_receiver(post_app_install) as install_receiver:
        self.env.install(self.music_app)
        self.assertEqual(install_receiver.call_args_list, [
            call(signal=post_app_install, sender=self.env,
                app=self.ukulele_app),
            call(signal=post_app_install, sender=self.env,
                app=self.music_app),
        ])

Ответ 5

Целью этого является не проверка базового механизма сигнализации, а важная unit test, чтобы гарантировать, что любой сигнал, который должен испускать ваш метод, фактически испускается соответствующими аргументами. В этом случае это кажется немного тривиальным, поскольку он является внутренним сигналом джанго, но представьте, если бы вы написали метод, который излучал пользовательский сигнал.

Ответ 6

Почему вы тестируете свою инфраструктуру? Django уже имеет модульные тесты для диспетчера сигналов. Если вы не верите, что ваша инфраструктура в порядке, просто прикрепите ее модульные тесты к вашему тестовому бегуну.