Атака клонов.
Эпизод: покер.
По одной команде, без промедления, несколько тысяч клонов ринулись по узким сетевым коридорам, не ведая сомнений и страха поражения! Для того, чтобы сойтись в поединке и победить! Клоны, в большинстве своем не мастера, но запрограммированные на победу, просто четко выполняют инструкции, которые в случае удачи, ведут их к цели. Правила для всех одни, каждый сам за себя, но нет ни одного шанса выстоять и победить у человека, оказавшегося в этом месиве…
Это не эпизод легендарной саги «Звёздные войны» и не превью фантастической повести. Это описание нагрузочного тестирования сервера (построенного на технологиях Java), проведенного в ходе разработки игрового приложения «Покер» для социальных сетей.
Нагрузочному тестированию предшествовала реализация основной функциональности сервера: набора команд, сетевого интерфейса (Apache MINA), игрового движка и базы данных (Hibernate, MySQL). В процессе разработки использовалась непрерывная интеграция (сервер непрерывной интеграции Hudson), модульное тестирование (JUnit), интеграционное тестирование базы данных, нагрузочное тестирование сетевого интерфейса и логики приложения. В условиях, когда флеш-клиент игры находился в стадии начала разработки, стояла задача проведения интеграционного и нагрузочного тестирования игрового сервера. Был описан алгоритм инструкций для ботов покера, где поведение клона зависело от текущего состояния игровой ситуации, набора карт. С учетом того, что не было цели создать автоматического игрока с высоким мастерством, алгоритм был простым для реализации, но эффективным. Это позволило проводить тестирование игрового сервера посредством автоматических игроков наряду с реальными игроками. И клоны зачастую брали победу у людей числом, а не умением.
Как выше уже отмечалось, при разработке использовалось модульное тестирование, позволяющее проверить функциональность отдельных классов. Не обошлось без него и при разработке «мозга» движка — расчета покерной «руки» (определение выигрышной комбинации карт в ходе раздач карт). Для каждой комбинации были написаны тесты, позволяющие их проверить. Правила покера определяют следующие выигрышные комбинации:
- Старшая карта;
- Пара (две карты одного ранга);
- Две пары (две пары одного ранга и еще две карты одного ранга);
- Сет (три карты одного ранга);
- Стрит (последовательность из пяти карт разной масти);
- Флэш (любые пять карт одной масти);
- Фул-хауз (три карты одного ранга и две карты тоже одного ранга);
- Карэ (четыре карты одной и той же деноминации);
- Стрит-флэш (последовательность из пяти карт одной и той же масти);
- Флэш-рояль (пять старших карт какой-либо одной масти).
Таким образом имеются 10 выигрышных комбинаций карт и в простом случае максимально за 10 циклов расчета можно найти решение. Но даже начинающий игрок покера заметит, что часть игровых комбинаций имеет общие свойства, например, стрит-флэш владеет свойством стрит (последовательность из пяти карт...) и флеш (… одной масти). Таким образом число циклов расчета удалось сократить до 4. И у нас был набор юнит тестов на каждую комбинацию..., но уверенности в правильности расчета не было. Эта проблема была решена написанием теста, который использовал статистику по покерным комбинациям (вероятность выпадения покерной комбинации):
================================================================
| Тест выигрышных комбинаций
================================================================
| HIGH_CARD | 17.497% | 34994 |
| ONE_PAIR | 43.847% | 87694 |
| TWO_PAIR | 23.4185% | 46837 |
| SET | 4.8045% | 9609 |
| STRAIGHT | 4.653% | 9306 |
| FLUSH | 2.989% | 5978 |
| FULL_HOUSE | 2.581% | 5162 |
| QUADS | 0.175% | 350 |
| STRAIGHT_FLUSH | 0.033% | 66 |
| ROYAL_FLUSH | 0.0020% | 4 |
================================================================
handsNumber: 200000
В данном тесте идет расчет 200000 случайных комбинаций, представлено число их выпадения в процентном соотношении и в численном (например, сет выпал в тесте 9609 в ~4.81% случаев). Расхождение между результатами этого теста и статистическими данными указало на ошибку, возникающую в результате того, что изначально не учли ряд особых правил в комбинациях, которые опытным игрокам прекрасно известны.
Таким образом, еще раз была подтверждена эффективность автоматического тестирования (модульного, интеграционного, нагрузочного) разрабатываемых приложений.
Автор: dcheremnov