Должен ли я утверждать одинаковые значения в каждом тесте? - PullRequest
0 голосов
/ 15 января 2019

У меня есть простой класс с публичным методом build, который я хочу проверить.В настоящее время я утверждаю все значения, которые он возвращает в каждом тесте.Это хорошая практика, или я должен написать один тест для статических значений, а в других тестах проверять только те значения, которые меняются в зависимости от ввода?

Реализация

class FiltersAttachment:
    TYPE_OPTIONS = [
        {"text": "All types", "value": "all"},
        {"text": ":link: Webpages", "value": "web_pages"}
    ]

    STATUS_OPTIONS = [
        {"text": "Available / Unavailable", "value": "all"},
        {"text": ":white_circle: Available", "value": "available"},
        {"text": ":red_circle: Unavailable", "value": "unavailable"}
    ]

    @classmethod
    def _filter_options(cls, options, selected):
        return list(filter(lambda t: t['value'] == selected, options))

    @classmethod
    def build(cls, check_type='', status=''):
        return {
            'fallback': 'Filters',
            'callback_id': 'resource_filters',
            'color': '#d2dde1',
            'mrkdwn_in': ['text'],
            'actions': [
                {
                    'name': 'resource_type',
                    'text': 'Type',
                    'type': 'select',
                    'options': cls.TYPE_OPTIONS,
                    'selected_options': cls._filter_options(
                        cls.TYPE_OPTIONS, check_type)
                },
                {

                    'name': 'resource_status',
                    'text': 'Status',
                    'type': 'select',
                    'options': cls.STATUS_OPTIONS,
                    'selected_options': cls._filter_options(
                        cls.STATUS_OPTIONS, status)
                }
            ]
        }

Тесты

class TestFiltersAttachment(TestCase):
    def assert_attachment(self, attachment):
        self.assertEqual(attachment['fallback'], 'Filters')
        self.assertEqual(attachment['callback_id'], 'resource_filters')
        self.assertEqual(attachment['color'], '#d2dde1')
        self.assertEqual(attachment['mrkdwn_in'], ['text'])

        type_action = attachment['actions'][0]
        self.assertEqual(type_action['name'], 'resource_type')
        self.assertEqual(type_action['text'], 'Type')
        self.assertEqual(type_action['type'], 'select')
        self.assertEqual(type_action['options'][0]['text'], 'All types')
        self.assertEqual(type_action['options'][0]['value'], 'all')
        self.assertEqual(type_action['options'][1]['text'], ':link: Webpages')
        self.assertEqual(type_action['options'][1]['value'], 'web_pages')

        status_action = attachment['actions'][1]
        self.assertEqual(status_action['name'], 'resource_status')
        self.assertEqual(status_action['text'], 'Status')
        self.assertEqual(status_action['type'], 'select')
        self.assertEqual(status_action['options'][0]['text'], 'Available / Unavailable')
        self.assertEqual(status_action['options'][0]['value'], 'all')
        self.assertEqual(status_action['options'][1]['text'], ':white_circle: Available')
        self.assertEqual(status_action['options'][1]['value'], 'available')
        self.assertEqual(status_action['options'][2]['text'], ':red_circle: Unavailable')
        self.assertEqual(status_action['options'][2]['value'], 'unavailable')

    def test_all_type_selected(self):
        attachment = FiltersAttachment.build(check_type='all')
        self.assert_attachment(attachment)

        selected_type = attachment['actions'][0]['selected_options'][0]
        self.assertEqual(selected_type['text'], 'All types')
        self.assertEqual(selected_type['value'], 'all')

    def test_all_status_selected(self):
        attachment = FiltersAttachment.build(status='all')
        self.assert_attachment(attachment)

        selected_status = attachment['actions'][1]['selected_options'][0]
        self.assertEqual(selected_status['text'], 'Available / Unavailable')
        self.assertEqual(selected_status['value'], 'all')
        ...

1 Ответ

0 голосов
/ 19 января 2019

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

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

Следовательно, каждый тест должен проверять один конкретный аспект, так что провал теста дает наиболее конкретную информацию. Это достигается сочетанием следующих двух принципов:

  • Каждый тест должен проверять один конкретный аспект.
  • Не должно быть избыточных тестов для одного и того же аспекта.

Превратить каждое утверждение в собственное тестирование можно удобно с помощью так называемых параметризованных тестов. Некоторые подсказки для Python можно найти по этому вопросу: Как генерировать динамические (параметризованные) модульные тесты в python?

...