Ортогональность юнит-тестов против краткости юнит-тестов

14

Я пишу юнит-тесты для системы рулевого управления для видеоигры. Система имеет несколько вариантов поведения (избегайте этой области по причине A, избегайте этой области по причине B, каждый из которых добавляет немного контекста к карте региона. Затем отдельная функция анализирует карту и производит желаемое движение.

У меня проблемы с решением, как написать модульные тесты для поведения. Как предполагает TDD, меня интересует только то, как поведение влияет на желаемое движение. Например, избегание по причине причины A должно привести к отходу от предполагаемой плохой позиции. Меня не волнует, как и почему поведение добавляет контекст на карту, только то, что желаемое движение находится вдали от позиции.

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

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

Однако, если я протестирую напрямую по результатам поведения путем макетирования карты, то наверняка я слишком тесно связан с реализацией? Если я могу получить то же самое желаемое движение с карты, используя немного другое поведение, тогда тесты все равно должны пройти.

Так что теперь я страдаю от когнитивного диссонанса. Каков наилучший способ структурировать эти тесты?

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

Ответы:

10

В идеальном мире у вас действительно будет набор совершенно ортогональных модульных тестов, все на одном уровне абстракции.

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

Я не думаю, что это плохо. Суть в том, чтобы ваш код был протестирован наилучшим образом, который соответствует вашему проекту и вашей ситуации, а не придерживаться «идеального пути».

Петер Тёрёк
источник
Я предполагаю, что основная мысль автора заключалась в том, должны ли вы использовать заглушки / насмешки или реальные реализации для этих высокоуровневых тестов
SiberianGuy
2

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

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

Если бы вы включили несколько примеров карт или поведения, возможно, кто-то мог бы привести примеры издевательств, которые вы могли бы написать. Не я, поскольку я никогда не программировал более продвинутую видеоигру, чем Понг, и даже тогда я следил за книгой, но, возможно, кто-то хорошо разбирался в юнит-тестировании и разработке игр.

trysis
источник
0

Я думаю, что вы пытаетесь проверить вещи, которые намного выше уровня, чем юнит.

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

Энона
источник
Вот почему я упомянул краткость. Я могу очень легко написать небольшие модульные тесты для тестирования отдельных строк кода в поведении, и это было сделано, но это зависит от чтения выходных данных функции синтаксического анализа карты. Ни один из моих тестов поведения не является большим, каждый из них тестирует только одну часть функциональности поведения.
tenpn