Тестирование, как важный процесс разработки программного обеспечения, пришёл в индустрию не случайно: по мере роста сложности программных продуктов и их частых изменений становилось невозможно поддерживать работоспособность сборки без проверки многочисленных узлов приложения. Изменения в одном модуле могли приводить к поломкам в другом, причём совершенно не связанным с тем, который менялся. Короче говоря, тесты были нужны настолько, что в какой-то момент даже стала популярна парадигма разработки-через-тестирование, когда написание кода предварялось разработкой тестов, на основании которых писался код.
И хотя идея, изначально, была вполне здравой, то в процессе использования появился некоторый карго-культ тестов, который привёл к не совсем ожидаемым результатам. Если коротко, то в борьба с недостаточностью тестов привела к проблемам избыточности, когда тестами покрывалось всё, что нужно и не нужно и малейшие изменения приводили к гарантируемым поломкам. В этом случае суть изменений в коде начинала сводиться, по большей части, не к исправлению какой-то ошибки или добавлению новой функции, а к правке многочисленных (порой лишённых смысла) тестов.
Что же, тестирование не обошло и разработку игр.
Для начала, давайте уточним, что есть много разновидностей тестов и называют их по-разному. Иногда под разными названиями стоят одни и те же процессы, иногда немного отличающиеся, иногда принципиально разные. Мы же рассмотрим два вида тестов: логические и визуальные (названия мои, чтобы не путать никого ничем).
Тесты логические
Юнит тесты, тестирование бизнес-логики и ... придумайте сами, как ещё можно назвать - отвечают за проверку работоспособности основного кода, проверяя, что функционал всегда предсказуемо реагирует на входные данные (например, при тестирование функции, складывающих 2 целых числа, 2 + 2 всегда будет 4).
Игра же - это почти целиком и полностью математика. Вычисление траекторий, кривых изменения скоростей или обнаружение столкновений объектов - всегда возвращают весьма предсказуемые наборы данных. Поэтому тестирование большей части кода - всего лишь уточнение, что функция отрабатывает правильно.
Более того, тесты способны дать понять, что что-то работает неверно: количество вариантов использования любого функционала, обычно, ограничено весьма стандартными шаблонами (например, вращение объекта с может инициализироваться лишь определёнными значениями - скорость вращения не может быть отрицательной), поэтому заранее зная, какие значения должны получиться и проведя через тестирование моделирование ситуаций - можно выяснить, что какой-то функционал работает неверно.
Хм, получается немного суховато. Попробую добавить пример. Скажем, у нас есть машинка, которая передвигается по плоскости и может столкнуться с препятствием. Вид сверху, столкновение определяется засчёт "столкновений коробочек" вокруг машинки и препятствий. Машинка может поворачивать на 45 градусов - тогда коробка вокруг машинки становится шире и это может привести к тому, что в какой-то достаточно узкий проезд машинка проехать не сможет, хотя визуально будет казаться, что должна протиснуться.
И вот, для подобных случаев, тесты помогут ещё на этапе разработки определить проблему.
Визуальное тестирование
Это когда тестируется сама среда. Например, в веб-разработке очень популярны системы тестирования на базе Selenium. Однако, подобные тесты всегда ориентируются на какие-то справочные узлы (поле ввода, какой-то блок или кнопка), по наличию или отсутствию которых определяется правильная или неправильная работа.
Такие тесты весьма трудоёмки в написании, потому что то, что мы делаем не задумываясь, кликая мышкой, тут приходится описывать набором вызовов, которые не всегда очевидно. И это на веб странице! А теперь представьте, как написать скрипт, который переместит персонажа к замку по извилистой дорожке и поставит перед воротами так, чтобы не была видна бойница... и подобных тестов надо написать сотни.
Вдобавок, подобное тестирование упускает из виду многое другое: например, неверное отображение цветов, фонов или текстур. Тестирование "слепо" по отношению к тому, что не входит в зону его интересов и даже серьёзная ошибка, не охваченная визуальным тестом - будет проигнорировано и тесты пройдут успешно.
Может показаться, что я отговариваю от написания таких вот визуальных тестов... нет, скорее призываю использовать их для строго определённых задач и крайне ограничено. Не следует распыляться, создавая тесты, которые, возможно, мало что тестируют.
А вот, например, управление персонажем в сложных условиях - было бы не лишним охватить тестами. Особенно, если это управление очень зависит от среды или навыков игрока.
Охватить тестами всё - нельзя
Вернее можно, но на это уйдёт примерно бесконечное количество времени. Кроме того, надо ли? Тесты, проверяющие основополагающие механики и ключевой код, безусловно, будут полезными, так как изменения будут гарантировать, что они ничего не поломали.
Осталось лишь провести границу, отделив необходимое от вторичного и постараться не оставить за скобками некоторые непредсказуемые случаи (хотя их, зачастую, добавляют постфактум).
Тестирование с человеческим лицом
И всё же наилучшего результата пока что можно достичь усилиями тестировщиков - живых, мягких, раздражающе-любопытных, ломающих то, что вроде отлично работало во время разработки.
Пожалуй, слишком много получилось про тестирование. Увы, ничего нового я не сказал и, думаю, много чего пропустил. Но, тем не менее, подведу итог:
- Покрывайте тестами критически важные части кода;
- Старайтесь рассмотреть разные шаблоны поведения, чтобы предусмотреть нестандартные (но возможные) ситуации;
- Не следует писать слишком много тестов;
- Граница "слишком мало" и "слишком много" - очень расплывчата, так что руководствуйтесь здравым смыслом;
- Покрывать тестами всё - нет никакого смысла, лучше доверить это тестировщику (для игр это особенно актуально по причине огромного простора для разных ошибок).