Тестування гри через методологію BDD з використанням Gherkin та Pytest-BDD

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

Статті будуть поділені на такі теми:
1 — Тестування гри через методологію BDD з використанням Gherkin та Pytest-BDD
2 — Пишемо реалізацію деяких логічних об’єктів гри, включаючи інтелект для пошуку найкращого ходу
3 — Пишемо мікросервіс для віддаленої зміни моків/запуску тестів у відповідність до будь-якої події у грі

Перед використанням методології BDD мене мучили сумніви, тому що не було практичного досвіду і не розумів, чому б не вдатися до TDD. Якось Боб Мартін сказав — не дослівно (нижче буде скріншот) «БДД і є ТДД, але з гарним неймiнгом».

Можливо, раніше я б з ним і погодився, але зараз маю таку відповідь — «Ні, Дядечку Бобе, ви помиляєтесь. TDD і BDD є абсолютно два різних підходи, і нижче я спробую показати чому».

Не вдаючись до мого пояснення, хочу взяти цитату зі статті «BDD is like TDD if».

Оригiнал — BDD the same as TDD? Yes. If you’re a programmer, and your entire team is programmers, and all your stakeholders are programmers and you have a single Subject Matter Expert embedded in the team. Which was true of the Chrysler C3 team and other early XP teams. -

Важлива частина — BDD такий самий, як TDD? Так. Якщо ви програміст, і вся ваша команда — програмісти, і всі зацікавлені сторони — програмісти.

Що саме хотів сказати цим автор статті? — Давайте з’ясуємо.

Чому ми обрали BDD, а не TDD

Чому було обрано BDD, а не TDD? З однієї простої причини це гнучкість роботи з тестами.

Гнучкість BDD

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

Те саме стосується і CEO/інших працівників, які захочуть зайти і подивитися, які частини гри були покриті, або навіть написати особисто свої тести.

Яким чином це досягається? Як ми можемо написати тести так, щоб їх розумів кожен? — Тут все дуже просто, BDD будується на 3 принципах



Given — Те, що дається для проходження тестування

When — Коли відбувається подія

Then — Отримання очікуваного результату


Все, цього буде достатньо, щоб описувати наші тестові сценарії. Давайте розглянемо простий сценарій.

У чому суть сценарію — негативне тестування функції на неможливість знищення порожньої клітини.

Given Ігрове поле, порожні клітини позначаються 0, iншi цифри це рівень будинку від 1 до 10.

[

[1,2,3,4,5,0]

[0,1,2,3,4,5]

[0,1,2,3,4,5]

[01,2,3,4,5]

]

Given Одна можливість використовувати функції destruction

When Коли користувач намагається знищити будь-яку клітинку з значенням 0

Then Нічого не станеться

Then(або and) У користувача не забереться одна можливість видалити будинок


Плюси

  • Проводимо тестування з погляду користувача
  • Читаємо
  • Може писати кожен
  • Тести не залежать від мови
  • Легко змінюється

Мінуси

  • Може коштувати дорожче нiж TDD
  • Вимагає залучення фахівців на етапі розробки вимог

Python Pytests BDD and Gherking

Що таке Gherkin

Мова для опису поведінки системи, яка легко читається. Вона має просту структуру, яка використовує відступи. Сценарій у Gherkin — це інструкції для бізнесу/документації/аналітика.

Має в собі 10 ключових слів, 3 вище, які ми описували ( Give, Then, When ) і доповнення у вигляді:

  • But
  • Scenario
  • Feature
  • Background
  • Scenario Outline
  • Examples
  • And

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

Опис взаємодії нашої гри з тестами


У нас є гра, в якій відбуваються якісь події, як тільки ця подія відбувається ми передаємо інформацію про неї на наш мікросервіс, написаний на Python. Він його приймає, запускає тести пов’язані з цією подією, генеруючи імітацію даних користувача. У разі помилки створюємо автоматичний баг репорт, логуючи всі дії від А до Я.

Проблема, з якою ми зіткнулися

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


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

А самі тести запускаються дуже просто:

  • Прокидаємо у глобальну фікстуру функцію для взяття шляху до файлу з читанням даних із нього.
  • Передаємо фікстуру в функцію, шляхом буде змінна в Gherkin.


Все готово. Можна запускати тести зі зміною файлів (у майбутньому ще й автоматично), при цьому не торкаючись логіки роботи самих тестів. Круто!

Що ми отримаємо в результаті

  1. Можливість автоматизувати наше тестування, зменшуючи роботу тестувальників у рази.
  2. Базу даних із десятків тисяч різних даних для тестування поведінки нашого користувача (відмінно підходить для регресійного прогону).
  3. Легкість написання нових тестів.
  4. Легкість зміни mock файлів.
  5. Читання тестів.
  6. Зрештою, економимо час тестувальників (з точки бізнесу гроші) і направляємо їх у потрібне русло.
  7. Легше допилювати оновлення, кількість багів мінімальна.

Матеріал

  1. TDD IS BDD IF
  2. BDD in Action_ behavior-driven development for the whole software lifecycle (John Ferguson Smart)

Підписуйтеся на Telegram-канал @gamedev_dou, щоб не пропустити найважливіші статті і новини про геймдев

👍ПодобаєтьсяСподобалось3
До обраногоВ обраному3
LinkedIn
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

Був досвід.
Єдиний кейс де цей рівень абстракції нормально працював це таблиці. Якщо треба прогнати багато різноманітних данних воно добре працювало.

По своєму досвіду скажу, що Gherkin — це зайвий рівень абстракції, який робить тести складнішими, і просто забирає додатковий час та зусилля на написання мапінгу текста в функції. Той же самий given-when-then можна описати прямо в коді, що буде швидше і більш гнучко.

Проблема в тому, що ніхто, крім програмістів та тестувальників, не пише тести (а по факту ніхто інший і не може це якісно зробити, бо треба знати теорію тестування). Тобто BDD прекрасне, але воно розбивається об реальність.
Сама нотація given-when-then гарна, і може бути прочитана в коді навіть тими, хто не вміє програмувати (особливо, якщо фреймворк її підтримує). Наприклад, Spock:

def "Should credit empty bank account"() {
    given: "an empty bank account"
    // ...
    when: "the account is credited $10"
    // ...
    then: "the account's balance is $10"
    // ...
}

Я перепрошую, але почати статтю з «BDD це Behavior-driven development» було б значно комфортніше для читача (замість того щоб відправляти його в Google).

Підписатись на коментарі