Экзотические баги и их устранение |
20.02.2024 00:00 |
Оригинал опубликован в блоге на Хабре РСХБ-Интех сотрудником Ахметовым Андреем Меня зовут Андрей Ахметов, я ведущий инженер и тестировщик системы ЕСПП в ООО «РСХБ-Интех», технологической дочке Россельхозбанка. Сегодня расскажу вам шесть небольших историй о том, какие экзотические баги бывают и как их устранять. ЕСПП (единая система приема платежей) — мидл‑решение, расположенное в центре хитросплетений систем РСХБ. Подробнее о том, что это за система и с какими сервисами она взаимодействует можно почитать в отдельном материале на Хабре. Добавлю лишь, что за последние годы она нам стала практически родной. Для тестирования ЕСПП мы используем широкий набор инструментов, начиная с привычного всем Postman и заканчивая самописным ПО, созданным для конкретных задач. В процессе работы мы ловим самые разные баги. Некоторые из них удостоились упоминания в этом материале. «Батин жигуль»Почему жигуль? Зимой машину нужно прогреть, иначе она никуда не поедет. Кроме того, жигуль обладает непростым характером, как и процесс импортозамещения. В рамках импортозамещения мы решили перенести основной функционал с систем Windows в Docker-контейнеры. Заодно появилась возможность оптимизации процесса работы и избавления от ненужных костылей. Это интересный поэтапный процесс со своими нюансами и трудностями внешнего и внутреннего взаимодействия систем. Последние несколько месяцев мы занимаемся реализацией возможности проведения блокировок и активаций сервисов СБП. У нас блокировки происходят как автоматически, со стороны систем антифрода, так и вручную, когда номера, на которые запрещен перевод, настраивает оператор или кассир банка. Итак, ситуация. Настроили блокировки, начали тестировать, и первая же С2С (customer-to-customer) операция завершается успешно, хотя должна заблокироваться. Пытаемся повторить кейс — он не воспроизводится. Заводим баг, продолжаем работу. На следующий день тестируем другие услуги, и первая же операция снова завершается успешно, хотя должна была заблокироваться. В этот раз ошибка снова не повторяется, завели баг. Подобные дефекты копились в течение всего цикла тестирования — более 10 случаев за несколько недель. Изначально мы не видели между ними связи и просто фиксировали их в рабочем порядке. Часть дефектов вендор отклонил с комментарием «не удалось воспроизвести». Со временем мы смогли выявить закономерности.
После локализации проблемы удалось добиться стабильности в воспроизведении дефекта. Информацию передали вендору, и он уже на своей стороне проверил, что именно идёт не так. В итоге проблема оказалась в следующем: функция, отвечающая за взаимодействие с NATS, после первого запуска или «с холодного старта» не успевала успешно законнектиться к NATS и проанализировать полученное сообщение. При всех последующих взаимодействиях (соединение с NATS уже было установлено) анализ производился за считанные милисекунды, и проблема более не воспроизводилась. С имеющейся информацией мы уже свежим взглядом прошлись по ранее заведенным багам, закрыли те, что были связаны с этой проблемой, и создали новый баг со ссылками на ранее заведенные и уже закрытые дефекты. Его мы назвали “Проблема с прогревом”: отсюда, собственно, и пошел жигуль. Мораль этой истории:
«Принятие неизбежного»Часто ли вы испытываете стресс на работе? А при работе с дефектами? Помните это внутреннее ликование, когда баг, наконец, пойман и отдан на растерзание? Нашей команде больно было узнать, что так случается не всегда. Со стороны пользователей СБП неразрывно связана со смартфонами, поэтому нам приходится тестировать мобильные приложения. Смартфоны — это отдельный мир, где мы встретились с дефектом, который подрезал нам крылья. Наша команда проверяла процесс взаимодействия между внутренними системами Банка и национальной системой платежных карт — НСПК. Нам нужно было два разных приложения на двух смартфонах. Оплата проходила по NFC. Модель оплаты была следующей.
С виду все просто. Ох, если бы! Перейдем к нашим стадиям принятия неизбежного. ОтрицаниеМы получили первые сборки тестовых приложений, установили их на смартфоны, проверили все преднастройки, включили NFC, сгенерировали платежную ссылку. Приложили смартфоны друг к другу для оплаты, и... ничего. Тишина! Буквально, не происходило ничего. Схватить блокер на старте, это, наверное, самое печальное, что может случиться в работе тестировщика. У нас длинный цикл разработки, и когда продукт доходит до нас, он должен работать. Могут быть разве что ошибки в настройках. Не верилось, что все может закончиться, даже не начавшись. Мы начали все перепроверять. Через стороннее приложение по считыванию NFC-меток мы выяснили, что смартфон передавал корректную платежную ссылку. Возможно, проблемы на считывающем устройстве? Наш коллега отправился в магазин электроники, приобрел несколько NFC-меток. Мы записали на одну из них тестовую платежную ссылку и... Смартфон клиента ее успешно считывал. Складывалось впечатление, что просто те смартфоны не дружат между собой. Поэтому, мы решили добавить в тестирование третий смартфон, на который установили сразу два приложения. ГневДобавление третьего смартфона почти ничем нам не помогло. Реакция у него при взаимодействии с первыми двумя смартфонами была другой, но все еще не той, которую мы ожидали. С одного смартфона третий смог считать ссылку, но не смог открыть ее в целевом приложении. Со второго смартфона третий не смог считать ничего. Как говорится, если не находишь закономерностей в происходящем, то просто добавь больше итераций и исходных данных! Мы добавили четвертый и пятый смартфоны. И в течение нескольких дней терли их друг об друга, проверили десятки сценариев, провели сотни итераций, собрали тонны логов и построили матрицы соответствий. Гнев застилал нам глаза! И вот, наконец, нам удалось найти сочетание, при котором можно было продолжать тестирование. Однако, мысль о том, что разные смартфоны не дружат между собой слишком часто, не давала нам покоя. Торг В процессе локализации дефекта нас сопровождал вендор. С его стороны мы получали много информации о том, как отрабатывают устройства. В частности, вендор сообщал, что с их стороны бóльшая часть устройств работает корректно. Но для банка вариант «бóльшая» никак не подходит. Ответ на вопрос, в чем же заключается проблема, прозвучал для нас как гром среди ясного неба. Выяснилось, что для корректной работы требовалась поддержка определенных протоколов именно со стороны NFC-чипов. Существует огромное количество смартфонов со своей собственной моделью чипа. В них могут быть разные наборы поддерживаемых протоколов. И информации об этом нет в открытом доступе. У нас возникали серьезные проблемы: нам требовалось как-то отключать возможность оплаты по NFC, если чип не поддерживал необходимые протоколы. К счастью, вендор достаточно быстро предложил решение: при запуске приложения была добавлена проверка наличия поддержки необходимых протоколов. Решение не самое элегантное, но действенное и способное предотвратить появление дефекта в промышленной среде. ДепрессияС этим решением мы продолжили тестирование. Проблема была успешно локализована. Реализован максимально человечный воркэраунд. Но не было радости. Как это обычно бывает в работе тестировщика: находишь ошибку, понимаешь, что это баг, охотишься на него, ловишь, даешь на растерзание разработчикам, и все исправляется, на душе радость. В этот раз было не так. Баг мы нашли, но исправить его не смогли. Горький осадок безысходности все же остался и в таком состоянии легкой грусти мы продолжали работать, параллельно наполняя базу знаний информацией по NFC-чипам и сопутствующей им документацией. Долго в таком состоянии пребывать невозможно и вот, наконец... ПринятиеМы приняли неизбежность того, что не каждый баг может быть исправлен. Мы не всемогущи, и иногда приходится перекрывать дефекты костылями или искать обходные пути. Главное, чтобы конечный продукт достиг пользователя. Ведь если наше ПО сделало кому-то жизнь легче, то это уже отлично. «Работает - не трогай!»Банк — это большой организм с долгосрочными планами. В процессе работы над задачей, вводные могут поменяться: вышел новый закон, изменились условия работы и т.д. А это значит, что придется внести срочные правки в код, менять саму концепцию приложения, иногда даже полностью отменять выпуск в промышленную среду уже готового продукта. Те, кто занимается тестированием, знают, что перед выпуском релиза, для личного спокойствия вновь и вновь прогоняются до боли знакомые тесты, хотя все уже проверено и внесено в протокол. Так было и в тот раз. Ничего не предвещало беды. Релиз выпустили в пром, и… К нам пришли с багом. В промышленной среде остановилась работа важного сервиса с критической ошибкой после перезагрузки. Критическая ошибка на проме в банке — это очень серьезно. Мы проверили кейс: в тестовой среде после перезагрузки работа сервиса возобновилась корректно. Ситуация загадочная. Был заведен инцидент и началось расследование. В первую очередь проверили версионность компонентов и корректность их установки в промышленную среду. Отклонений не выявлено, всё соответствовало документации. Затем начались повторные проверки в тестовой среде. Но, несмотря на все ухищрения тестировщиков в попытках его сломать, сервис работал как часы. Ситуация выглядела тупиковой и абсолютно необъяснимой. Поиски неуловимого бага привели команду к единственному оставшемуся пути — перебору. Было выполнено помодульное сравнение тестовой среды с промышленной, и в итоге выявлено единственное несоответствие! В тестовой среде присутствовал маленький и уже неактуальный модуль, выполняющий функцию по заполнению текстовой формы. Он был установлен за год до разбора текущего инцидента и не имел прямой связи с сервисом, в котором обнаружена ошибка. Модуль отключили и попытались сломать упорный сервис. Каково же было удивление команды, когда ошибка воспроизвелась! Информацию сразу передали разработчикам и выяснилось, что в код была ошибочно внесена проверка на наличие всех модулей, прямо или косвенно взаимодействующих с сервисом. Ранее это нужно было для стабильности. А в промышленную среду этот модуль не был установлен, т. к. после приемки не был сочтен необходимым. Вывод простой — тестовая среда должна соответствовать промышленной настолько, насколько это технически возможно. Если какой-то компонент не был установлен в промышленную среду, эти изменения должны быть обязательно отражены в тестовой среде. Никогда не верьте документации на слово. Как видно на этом примере: необязательный модуль, может оказаться обязательным. Бывает такое, что убираешь ненужный костыль, а на нем то все и держалось. «Семь бед, один reset»Как и любое изобретение человечества, программное обеспечение несовершенно. Иногда баг может появиться из-за человеческого фактора, неучтенных нюансов эксплуатации, или из-за простой вероятности. Слышали про "эффект пестицида"? Эффект пестицида — это термин из области тестирования. Простыми словами, это ситуация, которая возникает, когда раз за разом выполняешь одни и те же проверки. Глаз замыливается и легко перепутать серьезный баг с ошибкой настройки тестового контура и использовать одни и те же данные для проверки. Такое бывает, например, когда коллеги работают в одном контуре и постоянно все всё шатают. Команда получила обычную задачу — стандартное обновление одного из самых часто используемых модулей. Обновление было небольшим, прошло основные этапы тестирования за считанные дни без единого дефекта и уже готовилось к установке в промышленную среду. Параллельно коллеги тестировали другую задачу (у нас общий контур), и в ходе тестирования им было необходимо многократно перезагружать сервер. После одного из рестартов сервер не запустился. Такое часто бывает во время тестирования, однако, внимание привлекла причина ошибки: ее вызвал наш успешно протестированный модуль, который не смог стартовать и не давал запускаться серверу. Заявлять, что это баг нашего компонента, было рано, ведь он не был связан с тестированием функционала. Команда начала сверять конфигурации, пытаясь понять, что изменилось. Почему стабильный компонент повел себя таким образом? Никаких изменений в конфигурацию не вносилось, он не был связан с новым функционалом. Оставалось одно: попытаться воссоздать условия воспроизведения, а именно - многократные перезагрузки сервера. Разумеется, делать это в рабочее время в разгар цикла тестирования не получалось. Как минимум, это некрасиво по отношению к коллегам. Сразу после завершения рабочего дня ответственный доброволец принялся перезагружать сервер, и после нескольких десятков попыток ошибка повторилась. Радость была недолгой: ошибка есть, но нет ни малейшего понимания ее природы. Ситуация была передана на анализ. После долгих изысканий выяснилось, что причина крылась в обновленной версии транспортной библиотеки у одного из сторонних компонентов. Но было все еще неясно, как это связано с нашим модулем. Дана рекомендация повысить версию библиотеки нашего модуля и повторить проверку. Идея прекрасная. Но процесс воспроизведения был весьма ресурсоемким и требовал отсутствия работ на стенде. Нужно было каждый раз вручную перезагружать сервер, а ведь мы даже не знали, сколько раз придется это делать. Подход не самый рациональный. Хорошо в нашей команде есть ребята, умеющие работать с кодом. Была разработана небольшая рестарт-утилита для автоматизации процесса. Ее функционал был прост: осуществить заданное количество итераций перезапуска сервера с фиксацией логов на момент запуска и остановки. Тестовый запуск был назначен на ночь, и прошел он блестяще: утилита осуществила около 600 рестартов и выявила интересную статистику. Ошибка вновь воспроизвелась в 2% случаев, но уже с другим модулем. Появилась новая информация, анализ продолжился. В итоге нам открылась прелюбопытнейшая архитектурная особенность системы: модули загружаются по порядку, а библиотеки - нет. В системе более сотни модулей. У всех, кроме измененных, была старая версия библиотеки. И если первой загружалась старая версия библиотеки, то все работало корректно. А если новая — происходила ошибка, поскольку старые версии были с ней несовместимы, что и было в нашем случае. Таким образом команда сумела найти и не пропустить в пром баг, завязанный практически на случайном событии, и обзавелась утилитой, которая с тех пор активно применяется в каждом цикле РТ для поиска ошибок инициализации. В процессе работы в тестовых контурах очень легко замыливаются глаза. И порой настоящую ошибку очень просто принять за издержки стабилизации или отладочные работы смежных систем. Но наша задача — не терять бдительность и отличать одно от другого. «О человечности»Все, что мы делаем, мы делаем для людей. И нашим ПО пользуются тоже люди. Эта история касается человечности. Вышел очередной релиз кассового ПО. Принципиальных изменений приложение не претерпело, и тестирование прошло практически по шаблону: давно знакомые тест-кейсы вопросов не вызывали, функционал отработал без замечаний. Но спустя несколько дней после релиза начали поступать жалобы от кассиров о недокументированных изменениях. Это негативно влияет их работу. Сразу причину жалоб установить не удалось, у нас все было в порядке и в рамках заданного ТЗ. Команда обратилась к одному из кассиров для уточнения деталей. Выяснилось следующее: в обновленной версии при запуске сценария оплаты курсор стоял не в первом по списку поле «ввода», а в самом низу в поле «сумма», что приводило к необходимости возвращать фокус на первое поле. Учитывая плотность обращений, это повышало трудозатраты кассиров. Казалось бы, секундное действие, но если его умножить на несколько сотен операций, то уже получается существенное количество времени. Немного посчитаем: 1 сек * 100 операций * 5 кассиров * 1400 филиалов = 700000 или 194 часа в день. Это время, которое тратится впустую. Ситуацию, разумеется, быстро исправили и в течение недели передали коллегам обратно. Порой мы слишком углубляемся в технические требования и забываем о простых истинах, которые прописаны в любой книжке: обязательно ставьте себя на место конечного пользователя и обращайте внимание на заведомо неудобные моменты. «О расширении границ»Иногда экзотичным бывает не столько сам баг, сколько ситуация, в которой он был открыт. Как я уже говорил, ЕСПП – это хаб. Он находится в центре взаимодействия десятка разнообразных систем и обработчиков. У каждого из них свои требования к взаимодействию и свои настройки, которые периодически меняются. В этой мешанине баги могут скрываться годами. Как-то раз к нам пришли с прома со следующей ошибкой: «Наименование ЮЛ имеет лимит 140 символов в теге <имя>». Начали разбираться, выяснилось, что одна из наших систем принимает названия юрлица не длиннее 140 символов. Это очень старая настройка, просто за полгода работы с момента релиза никто не регистрировал такие названия, как: «Местная Религиозная Организация Православный Приход Троице-Сергиева Храма, Подворья Заволжского Мужского Монастыря в Честь Честного и Животворящего Креста Господня г.о. Самара Самарской Епархии Русской Православной Церкви (Московский Патриархат)» Ошибка, естественно, была исправлена, и поле было приведено к стандарту в 512 символов согласно текущим требованиям взаимодействия. Мораль — в жизни бывает всякое и нужно быть готовым и к взлетам, и к падениям! В завершение хотелось бы спросить — какие экзотические баги встречались вам и как вы с ними справлялись? |