Как выполнить юнит-тестирование в игровом движке?

23

К моему большому стыду, я никогда не писал надлежащих модульных тестов, только небольшие неорганизованные тестовые программы, которые я бы затем утилизировал после успешного прохождения теста. У меня нет четкого представления о том, как проводить юнит-тестирование в игровом проекте. (Мой язык - C ++.)

Должен ли я иметь отдельный проект для каждой подсистемы в моем движке и связанный с ним тест, а затем иметь более крупный проект / решение, которое создает реальный движок? Скажем, например, у меня есть eventмодуль в моем двигателе; как мне справиться с этим?

Пол Манта
источник
Интересный вопрос: когда вы разрабатываете свой движок, тестировать функциональность довольно легко, но как насчет большого проекта в тесте игры?
Евгений
2
Не позорься: юнит-тесты автоматически не являются хорошей вещью.
о0 '.
1
Если вы никогда не пробовали использовать юнит-тесты, это определенно позор.
Кристофер Джонсон

Ответы:

18

Во-первых, вам понадобится среда модульного тестирования. В прошлом я использовал UnitTest ++ и Google Test . Первый очень легкий, а второй - более функциональный, но несколько более громоздкий. Он хорошо интегрируется с Google Mock, если вам когда-нибудь понадобятся подобные вещи. Есть, конечно, много других вариантов: см. Этот список (автором возможного UnitTest ++) и Википедию, например.

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

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

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

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

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


источник
3
If you have to [...] spend significantly more time writing the tests [...] than it took you to author the module... Тогда ваш модуль слишком сложен. Упростите это сейчас, вы будете благодарны в будущем!
Джесс Телфорд
3
@Jess Модуль, который непропорционально сложно протестировать, не обязательно должен быть упрощен. Есть много областей, где модульное тестирование просто неэффективно использует время. Это включает в себя графику, где выходные данные могут отличаться и по-прежнему приемлемы; код, который вряд ли изменится в будущем; или код, в котором вид абстрактного, несвязанного проекта, который был бы необходим для облегчения модульного тестирования, намного уродливее, более подвержен ошибкам, менее производителен или менее интуитивен.
Кейси Родармор
@rodarmor - согласился. Существует скользящая шкала того, что уместно, а что нет. Как и во всех подобных ответах, один размер не подходит всем :)
Джесс Телфорд
Для UnitTest ++ перейдите на github.com/unittest-cpp/unittest-cpp . Все остальное устарело.
Маркус
4

«Единица» - это наименьший тестируемый фрагмент кода, обычно это отдельная функция или класс. Модульный тест - это еще один фрагмент кода, который использует этот блок кода для обеспечения его правильного поведения. Одна единица кода может иметь много тестов, чтобы охватить все случаи.

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

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

Джедедия
источник