Як розробити програмне забезпечення гри таким чином, щоб його було легко провести?


25

Чи практично використовувати тестовий фреймворк типу JUnit в ситуації розвитку ігор? Яких міркувань щодо дизайну ви можете дотримуватися, щоб зробити вашу гру більш відчутною? Які частини гри можна / слід перевірити, а які частини слід / потрібно залишити для тестування на людях?

Наприклад, якщо ігровий цикл інкапсульований однією функцією, здається, що це було б дуже важко перевірити. Мені подобається переробляти функцію "оновлення", яка займає дельту часу і рухається вперед в ігровій логіці; це дозволяє зробити такі цікаві хитрощі, як можливість уповільнити гру, подаючи її фальшиві, повільніші дельти часу.


6
Навіщо витрачати людино-годинні написання тестів на одиниці, коли у вас є практично нескінченна армія рабської праці, щоб зробити для вас ігрові ігри? I kid, I kid ...;)
Майк Стробель

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

3
Тестування блоку не обов'язково полягає в тому, щоб переконатися, що ваша програма працює в цілому (тобто функціональне тестування). Це більше про те, щоб майбутні зміни не порушували існуючу функціональність. Звичайно, користувач може бачити, коли космічний корабель перевернутий ногами, але коли алгоритм маршрутизації вимкнений на .001, ефекти можуть не бути очевидними, поки гра не відбудеться протягом 200 годин. Ось такі речі, які можуть виявити одиничні тести, перш ніж код не вийде з дверей.
Вейд Вільямс

1
Ігри - це найпростіше програмне забезпечення, яке дозволяє користувачам грати , але граючи! = Тестування . Отримати хороші звіти про помилки досить складно. Крім того, відстеження того, де в коді виникає помилка, і перевірка того, що нові зміни не порушують існуючий код, приносять користь від автоматизованих тестів.
чудовий

Відповіді:


25

Одне з принципів TDD полягає в тому, що ви дозволяєте TDD в деяких випадках впливати на ваш дизайн. Ви пишете тест для системи, потім пишете код, щоб зробити тестовий прохід, підтримуйте залежності якомога дрібніше.

Для мене є лише дві речі, які я не тестую в рамках одиничного тестування:

По-перше, я не перевіряю візуальні елементи та те, як виглядають речі. Я перевіряю, що об'єкт буде знаходитись у потрібному місці після його оновлення, що камера буде скидати об'єкт поза його межами, що трансформації (принаймні ті, що виконуються поза шейдерами) виконуються належним чином перед передачею графічному двигуну , але як тільки він потрапляє у графічну систему, я малюю лінію. Мені не подобається намагатися знущатися над такими предметами, як DirectX.

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


6
Перший абзац є ключовим. Справа в тому, що TDD вимагає, щоб ви створили свій код краще, ніж у вас без нього, просто щоб дозволити тестування. Звичайно, багато хто думає, що це експерти в галузі дизайну, але, звичайно, ті, хто найбільше вражений їхніми власними навичками, - це, як правило, ті, хто найбільше навчається ...
dash-tom-bang

2
Я не погодився б, що в результаті код обов'язково розробляється краще. Я бачив безліч гидот, коли попередньо чистий інтерфейс потрібно було розбити, а інкапсуляцію зламати, щоб ввести залежність, яку можна перевірити.
Kylotan

4
Я вважаю, що це трапляється більше у випадках, коли тести написані для попередньо існуючих класів, а не навпаки.
Джефф

@Kylotan - це, мабуть, більше симптом неправильного дизайну / поганий дизайн тесту. Refactor та використовуйте макети, щоб робити чисті тести, не зламайте код у гіршому стані; це протилежне тому, що повинно відбутися.
тимокслі

2
Інкапсуляція - це добре, але важливіше зрозуміти, ЧОМУ це хороша річ. Якщо ви просто використовуєте його для приховування залежностей та великого некрасивого інтерфейсу, то це дуже сильно кричить навантаження, що ваш дизайн під кришкою, ймовірно, не дуже приємний. Інкапсуляція - це, перш за все, не про приховування некрасивого коду та залежностей, це в першу чергу про те, щоб полегшити розуміння вашого коду та дозволити споживачеві отримати менше шляхів для його просування, коли він намагається міркувати про код.
Мартін Оделій

19

Ноель Льопис охопив тестування одиниці, наскільки я вважаю, що ви шукаєте:

Що стосується тестування всього циклу гри, є ще одна методика запобігання функціональних регресій у вашому коді. Ідея полягає у тому, щоб ваша гра сама грала через систему повторного відтворення (тобто спочатку записує входи програвача, а потім відтворює їх протягом іншого виконання). Під час відтворення ви створюєте знімок стану кожного об'єкта для кожного кадру. Цю колекцію держави потім можна назвати «золотим образом». Під час рефакторингу коду, ви запускаєте повтор знову та порівнюєте стан кожного кадру із золотим зображенням. Якщо вона відрізняється, тест не вдався.

Переваги цієї методики очевидні, є кілька речей, з якими потрібно бути обережними:

  • Ваша гра повинна бути детермінованою, тому вам слід бути обережними з такими речами, як залежно від вашого системного годинника, системних / мережевих подій, генераторів випадкових чисел, які не є детермінованими. тощо.
  • зміни вмісту після створення золотого зображення можуть спричинити законні відмінності у вашому золотому зображенні. Не обійтися цим способом - при зміні вмісту вам потрібно відродити свій золотий образ.

+1 Також варто зазначити, що цінність такого підходу безпосередньо пов'язана з довжиною «золотого зображення»: якщо він недостатньо довгий, ви можете легко пропустити помилок; якщо це занадто довго, у вас чекатиме багато чекати. Важливо спробувати змусити гру запускати, можливо, на порядок швидше в цьому режимі, ніж ви б за звичайних обставин виконувати час, щоб відголити час. Пропуск рендерінгу може допомогти!
Інженер

9

Я погоджуюся з коментарями Джеффа та jpaver. Я також хотів додати, що прийняття компонентної моделі для вашої архітектури значно підвищує її доцільність. У компонентній моделі кожен компонент повинен виконувати одну одиницю роботи і повинен бути перевірений ізольовано (або з обмеженими макетними об'єктами).

Крім того, інші частини гри, які покладаються на сутність, повинні покладатися лише на підмножину компонентів, які функціонують. На практиці це означає, що ви можете зазвичай знущатися з декількох підроблених компонентів, щоб полегшити тестування цих областей, або ви можете просто скласти часткові об'єкти для цілей тестування. наприклад, ви не залишаєте компоненти для візуалізації та введення, оскільки вони не потрібні для перевірки фізики.

Нарешті, я б ігнорував поради щодо продуктивності, які ви отримуєте від деяких користувачів ігрового співтовариства щодо інтерфейсів. Напишіть код добре з інтерфейсами, і якщо у вас виникнуть проблеми з продуктивністю в дорозі, ви зможете легко профайлювати, ідентифікувати та рефактор для вирішення проблеми. Мене не переконували занепокоєння Ноеля щодо впливу інтерфейсів на продуктивність або складності, які вони додали.

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


Зауважте, хоч ви, здається, не є новим для SX, що відповіді не впорядковані, і сказати щось на кшталт "обидва вищевказані коментарі" обов'язково швидко застаріть, оскільки зараз це на один голос попереду одного з двох інших відповідей наразі. :)
Ricket

Дякую, я не думав про це, коментуючи. З тих пір я оновив коментар, щоб вибрати окремі коментарі.
Алекс Шерер

3

Я думав, що додам другу відповідь, відповідаючи на коментар ОП про те, що користувач може замінити одиничні тести. Я вважаю, що це абсолютно неправильно, оскільки мета одиничних тестів - не гарантувати якість. Якщо ви хочете провести тести, щоб забезпечити якість вашої програми, ви, швидше за все, слід вивчити тести сценаріїв або інвестувати в чудовий моніторинг.

(За умови чудового моніторингу та продукту, що працює як послуга, дійсно можливо натиснути на "тестування" на клієнта, але вам потрібно мати складну систему, яка швидко виявляє помилки та скасовує відповідні зміни. Швидше за все, це занадто багато для невелика команда розвитку.)

Основна перевага модульних тестів полягає в тому, що вони змушують розробника написати краще розроблений код. Акт тестування кидає виклик розробнику відокремити проблеми та інкапсулювати дані. Це також заохочує розробника використовувати інтерфейси та інші абстракції, щоб він перевіряв лише одне.


Погодьтеся, за винятком того, що одиничні тести не змушують розробників писати хороший код. Є ще один варіант: дійсно погано написані тести. Потрібна прихильність до ідеї одиничних тестів ваших кодерів, щоб вони не зациклювалися.
tenpn

2
Звичайно, але це не привід викидати дитину разом з водою з ванни. Використовуйте інструменти відповідально, але спочатку використовуйте інструменти.
Алекс Шерер
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.