
Привет, Хабр! Вот уже больше четырех лет я занимаюсь ручным и автоматизированным тестированием биллинговых систем Badoo. А биллинг Badoo — один из самых развитых (и сложных) в мире, и тестировать его — чаще всего интересная и неординарная задача. Сегодня я хочу вам рассказать, почему эти системы такие интересные и могучие, чему я научился за все эти годы и почему тестировать биллинг — это не (очень) страшно. И заодно поделюсь с вами очередной партией интересных историй (да, я это дело очень люблю). Большинство вещей будет применимо не только к нашему конкретному случаю, но и к любой другой сложной платежной системе (и не только платежной, если честно).
Что же такое наш биллинг? Это система обработки платежей в социальной сети, в которой более 330 миллионов зарегистрированных пользователей. Мы принимаем платежи во всех странах мира, поддерживаем свыше тридцати активных платежных методов (а за все время их было имплементировано около ста) и обрабатываем порядка 1500 запросов в секунду. Биллинг Badoo является самостоятельным выделенным сервисом, работающим с десятком разных клиентов (разные платформы, разные приложения). Достаточно любопытная база для развития тестирования, не так ли?
Объект тестирования
Итак, для начала вкратце расскажу, что именно нам приходится тестировать. Все наши клиенты (веб, мобильные приложения и некоторые back-end сервисы) общаются с биллингом с помощью API. Сам же биллинг располагается на отдельном кластере в каждом из наших дата-центров и ведет общение с различными платежными системами (посылает запросы на оплату, получает нотификации с результатом обработки запросов и т.д.). В кластере располагаются машины для обработки обращений клиентов и платежных систем, машины для запуска CLI-скриптов (например, для обновления истекающих подписных сервисов), наш собственный сервер обработки платежей банковскими картами и базы данных.

Разработчики биллинга занимаются решением задач нескольких видов:

- разработка нового функционала: новые платные сервисы, промо-кампании, различные фичи для подписчиков;
- разработка новых интеграций с платежными сервисами (всегда можно найти кого-то с более низкими комиссиями или более высокой конверсией);
- актуализация имеющихся интеграций (наши партнеры тоже развиваются);
- исправление багов (давайте признаем — у всех они бывают!);
- задачи по оптимизации и решению технического долга (всегда можно сделать сервис чуть-чуть лучше);
- решение задач технической поддержки (очень любим самых хитрых пользователей, которые умудряются создать десяток подписок на разных платежных сервисах в разных странах и потом путаются, как же отменить ненужные).
И все это «добро» в конечном счете приходит на тестирование нашей небольшой команде. Кроме задач непосредственно от биллинговых разработчиков, мы получаем задачи и от других команд, если они как-либо касаются платежей: например, изменения и новые фичи на клиентах или сервере мобильных приложений.
Что же именно мы тестируем? Можно разбить это все на три категории:
- пользовательские интерфейсы: всевозможные платежные окна (мы называем их «визардами») на разных платформах, окна настроек, рекламные баннеры, промо-окошки и т.д.;
- «админку» и конфигурационные инструменты: настройки цен, промо-кампаний, экспериментов и инструменты для техподдержки (которыми мы еще и очень активно пользуемся при тестировании);
- биллинговый back end: обработка платежей, очереди оказания услуг и проведение различных отложенных операций (самая сложная и «сочная» часть).
Постараюсь вам обо всем этом рассказать по порядку.
Пользовательские интерфейсы

Что же здесь можно протестировать? Да море всего! Каждый платежный метод должен отображаться корректно при любом выбранном варианте сервиса. Список самих вариантов должен соответствовать желаемому, на каждом из них должна быть указана заданная в настройках биллинга цена, при этом формат цены и валюты должен соответствовать принятому в стране стандарту: например $6,49, 125,00 MXN или 17.64BYN.
Каждое платежное окно должно сопровождаться подробными условиям оказания сервиса. Каждое промо-окошко тоже должно содержать все необходимое или вести к следующему шагу с полным описанием условий (вот это, кстати, одна из самых частых проблем, про которую так легко забыть).
Любое действие пользователя в таких окнах должно сопровождаться корректными сообщениями, причем не только об успешных платежах, но и об ошибках (нужно уметь отличать ситуации, когда пользователь отменил платеж на стороне партнера, а когда реально ввел некорректную информацию).


В остальных случаях строить песочницы нам приходится самим, эмулируя различные ответы и нотификации. Но даже это получается не везде, и приходится руками собирать нотификации, делать какие-то подмены в коде и отправлять их себе https-запросами.

И давайте даже не будем здесь говорить о том, какие неудобные песочницы у Apple и Google, особенно при попытках тестировать подписки.
Между прочим, сам факт работы со внешними партнерами приносит с собой немало проблем. Их платежные окна могут открываться долго и тормозить тестирование, они могут содержать в себе самые обычные баги (которые ты, как уважающий себя тестировщик, первым делом приписываешь собственным разработчикам). Любые действия, требующие сотрудничества с их стороны (фиксы тех же багов, расширение протокола) тоже зачастую затягиваются, причем они могут самостоятельно делать какие-то изменения, не поставив нас в известность (о чем мы узнаём только по возросшим графикам ошибок), и предоставлять нам неполную или даже некорректную документацию.
Админка
Ничуть не менее важная составляющая биллинга полностью скрыта от глаз наших пользователей. Это все то, что позволяет нашему менеджменту регулировать цены и доступность сервисов и запускать промо-кампании, а труженикам службы технической поддержки — выявлять причины проблем пользователя (и убеждаться в том, что они не пытаются просто получить сервис «на халяву») и максимально простым и безопасным способом их решать. К тому же все эти средства помогают нам в тестировании (воспроизводить многие кейсы исключительно действиями в интерфейсе пользователя либо достаточно сложно, либо очень долго).


Back end
А вот тут как раз начинается самое интересное. То, что скрыто от глаз обычных пользователей; то, о чем даже не хотят ничего знать менеджеры; то место, где воплощаются самые чудовищные фантазии наших разработчиков — внутренняя логика обработки платежей и оказания сервисов

Здесь тестируется просто уйма всевозможных вещей.
- Обращения к партнерским системам: проверка статусов подписок (иногда мы никак не можем управлять ими со своей стороны, и остается только проверять, что они всё еще активны), запросы на обновления и отмены подписок и многое другое.
- Обработка нотификаций от партнеров: мы должны правильно обработать каждую нотификацию (а ведь у каждого партнера свой собственный формат и протокол!), определить юзера, сервис и все возможные параметры, чтобы ничего не перепутать. Иногда нотификации вообще ничего не значат: «Смотрите, мы всё еще не смогли списать деньги с пользователя!»;, иногда они противоречат сами себе: «Пользователь отменил платеж :( А нет, вот и деньги пришли!»; иногда они совершенно не актуальны: «Помните ту подписку три года назад? Так вот, она все еще истекла!» — и мы должны придумать правильный «флоу» для каждого возможного случая.
- Оказание услуг: чтобы не потерять в случае проблем заказы пользователей, услуги оказываются через очереди. Если что-то пошло не так — событие откладывается, и любая услуга в любом случае должна быть доставлена до пользователя. Вот это «в любом случае» мы и должны гарантировать при тестировании.
- Обновление подписок: если пользователь подписан на определенные услуги, он должен их получать вовремя. Мы не должны «чарджить» его раньше (или позже) времени, с него всегда должна списываться именно та сумма, на которую он подписывался. Кроме того, у нас существует много разной логики выбора времени обновления подписок в разных странах (либо это наши эксперименты, либо требования регуляторов). Например, где-то мы «чарджим» пользователей только в рабочее время, где-то только в определенные дни недели.
- Платежи по имеющимся данным: как и в любой уважающей себя платежной системе, у нас пользователь может сохранить детали своего платежного метода для того и в следующий раз платить быстрее. Мы должны проверять, что детали хранятся безопасно (для банковских карт, например, нам нужно соблюдать PCI DSS), что платежи проходят и корректно обрабатываются случаи, когда детали более не валидны (например, карточка пользователя заблокирована).
- И так далее, и тому подобное.
Количество различной логики в серверном коде просто безгранично. Каждая новая задачка превращается в занимательный квест вида «Разберись, как оно работает => Разберись, как оно ДОЛЖНО работать => Разберись, как заставить систему так работать». Какими способами этого нужно добиваться?
Во-первых, нужно читать код. Тестировать биллинг как черный ящик практически невозможно: только имея представление о том, как работает система, можно понять, какие кейсы здесь можно протестировать. Кроме того, очень часто для успешного тестирования нужно делать изменения в коде: убирать обращения к агрегаторам (чтобы мы не спрашивали у них статус несуществующей тестовой подписки), подменять проверку подписи для нотификаций (чтобы не нужно было каждый раз ее генерировать) или «хардкодить» выбор определенного варианта в A/B тесте (чтобы не регистрировать десятки пользователей, попадающих в нужные группы). К счастью, мы всеми силами развиваем тестировочные утилиты, чтобы эти процессы упростить.
Во-вторых, нужно не бояться тестировать вещи неочевидными способами. Нельзя наверняка воспроизвести кейс из интерфейса? Можно написать функциональный тест! Можно полезть в тестовую базу «ручками» и заполнить нужные данные! Можно собрать нотификацию от партнера вручную и отправить ее на собственный адрес! Главное — не бояться забираться в дебри.

Автоматическое тестирование

- юнит-тесты: пишутся разработчиками во время работы над задачей. В нашем процессе задача не считается решенной, пока она не покрыта тестами;
- интеграционные тесты: пишутся разработчиками (и иногда тестировщиками) на этапе тестирования для проверки трудновоспроизводимых мест. Продолжают подменять часть кода, как и юнит-тесты, но работают с гораздо более широким пластом сущностей одновременно;
- системные Selenium- и Calabash-тесты: тестируют клиент так, как его видит пользователь. Не идеально стабильные, достаточно медленные, но очень полезные, так как позволяют находить еще и проблемы, вызванные задачами других отделов;
- системные curl-тесты: достаточно новое направление. Они проверяют общую работоспособность системы на тысячах различных кейсов: мы получаем платежные визарды всех сервисов, всех их вариантов, в каждой стране мира, на каждом платежном методе. Перетестирование как оно есть.
Когда эти тесты запускаются? В разных комбинациях это происходит постоянно:
- разработчики запускают тесты вручную при работе над задачей;
- они автоматически запускаются при переходе задачи в статус «Готово»;
- QA-инженеры запускают их вручную при тестировании;
- они запускаются каждый раз при сборке каждой новой версии билда;
- в конечном счете они постоянно и регулярно запускаются на препродакшене.

Мониторинг
Работа тестировщика над задачей не прекращается сразу же в тот момент, как задача отправляется на продакшен. Убедиться в том, что она выдерживает напряжение работы в боевом окружении, можно только путем внимательного мониторинга. Не появились ли в логах новые неожиданные ошибки (да, ожидаемые ошибки бывают, это нормально)? Не выросла ли нагрузка на биллинговый кластер? Не начала ли падать (или резко расти, что тоже обычно странно) прибыль в какой-нибудь стране или в каком-нибудь платежном методе? В Badoo есть замечательный отдел мониторинга, который круглосуточно следит за всеми метриками в ручном и автоматическом режимах. Однако им в любом случае понадобится какое-то время для того, чтобы самостоятельно выяснить причины тех или иных аномалий. Поэтому QA-инженер обязан внимательно проводить свою задачу в (последний) бой.
Для этих целей мы используем несколько различных систем, важнейшими из которых являются три:
- RRD Tool: в RRD мы храним логи ошибок и дебага, графики огромного множества основных метрик (прибыль, количество платежей, количество оказанных сервисов, размеры очередей);
Splunk: восхитительная система, с помощью который мы в реальном времени анализируем все биллинговые события, можем строить различные графики о количестве тех или иных запросов к биллингу по времени и многое-многое другое;
- Anomaly Detection: наша собственная система для обнаружения аномалий, автоматически сообщающая о неожиданном поведении той или иной метрики. В отличие от первых двух систем эта работает в полностью автоматическом режиме.
Что же можно считать аномалиями на биллинговых графиках? Давайте посмотрим вот на этот график в Польше. Каждая точка показывает суммарную прибыль за последние сутки, масштаб графика — тоже сутки.

Кошмар, жуткое падение прибыли, надо бить во все колокола! Но что это такое? Открываем график за месяц…

Что за безобразие? Оказывается, так работают мобильные агрегаторы в Польше. Они проводят все обновления подписок только в конкретный день недели, например, во вторник. Если юзер подписался в понедельник на неделю, то… его все равно «зачарджат» во вторник! Такие уж в Польше порядки. И каждый пик — «заветный» день недели того или иного агрегатора.
Смотрим дальше. Аналогичный график прибыли от AppleStore за неделю c 24 числа по 1 число следующего месяца:

Начинаем сразу же пугаться? Конечно! Такое падение, никакого роста за сутки — однозначная проблема! Пока мы сломя голову носимся по офису и вопим, проходят сутки. И что же мы видим?

График восстановился сам собой! Магия? Катастрофические ошибки? Заговор рептилоидов? Вовсе нет, это политика Apple. Они всегда совершают обновления подписок в тот же день месяца, в который подписка была заведена. Но что же происходит в феврале с теми, кто начинал подписки 30 или 31 числа: они счастливо сидят целый месяц бесплатно? Конечно, нет, их «чарджат» 28 февраля. И с тех пор начинают чарджить только 28 числа. Потому на конец месяца приходятся вот эти два пика (28 число для февраля и 30 число для всех остальных «коротких» месяцев), а 31 числа не обновляются вообще никакие подписки со сроком более месяца.
Как видите, мониторить тоже нужно с умом. Как я уже говорил, перетестировать — это не так плохо, но наловить тумаков от разработчиков за излишнее паникерство тоже можно.
Вместо заключения
Тестирование биллинга — интересное и занимательное дело. В нем есть много неординарных вещей, подводных камней и никому толком не известных закоулков, но решение почти каждой задачи — настоящий квест, по завершению которого испытываешь абсолютное ощущение триумфа. Очень жаль, что про эту сферу тестирования говорится не так много (а на конференциях я неоднократно слышал вещи типа «А биллинг мы тестируем на продакшене»). Рассчитываю, что моя статья поможет кому-нибудь иначе взглянуть на процессы тестирования в своей компании и, быть может, решить чуть плотнее тестировать свои платежные системы. Да и вообще любые низкоуровневые вещи. Поверьте мне, это действительно не скучно!
Кудинов Илья, Sr. QA Engineer