Термин «нефункциональные» никогда мне не нравился. Некоторые подпадающие под него понятия представляются весьма функциональными по своей природе! Одна из моих коллег, Сара Тарапоревалла (Sarah Taraporewalla), придумала вместо него словосочетание «межфункциональное тестирование» (Cross-Functional Requirements (CFR)), которому я всецело отдаю предпочтение. Оно говорит скорее о том, что эти элементы поведения системы действительно проявляются только в результате большого объема комплексной работы.
Многие, если не большинство CFR-требований могут быть соблюдены только в ходе работы в производственном режиме. Из этого следует, что нужно определить тестовые стратегии, помогающие понять, насколько мы приблизились к соответствию намеченным целям. Эта разновидность тестов попадает в сектор тестирования свойств. Хорошим примером таких тестов может послужить тест производительности, который мы вскоре рассмотрим более подробно.
Выполнение некоторых CFR-требований, возможно, придется отследить на отдельном сервисном уровне. Например, может быть принято решение, что вам необходима более высокая живучесть сервиса платежей, но вполне устраивает более продолжительный простой сервиса музыкальных рекомендаций, поскольку известно, что основной бизнес может сохранить живучесть, если вы не сможете порекомендовать исполнителей, похожих на Metallica, в течение десяти минут или около того. Эти компромиссы окажут большое влияние на принципы конструирования и развития вашей системы, и здесь снова высокая степень детализации, присущая системам на основе использования микросервисов, даст вам высокие шансы успешно справиться с этими компромиссами.
Тесты выполнения CFR-требований также должны вписываться в пирамидальную схему. Некоторые из них должны носить сквозной характер, например тесты работы при полной нагрузке, другие же не должны быть сквозными. Например, при обнаружении в результате проведения сквозного теста работы при полной нагрузке узких мест, снижающих производительность, следует написать тест с более узкой областью действия, помогающий определить причину возникновения проблемы в будущем. Другие проверки выполнения CFR-требований вполне вписываются в быстрые тесты. Помнится, мне приходилось работать над проектом, где мы настаивали на обеспечении использования HTML-разметки соответствующих функций, помогающих пользоваться сайтом людям с ограниченными возможностями. Проверка созданной разметки на присутствие соответствующих элементов управления может быть проведена очень быстро и без какого-либо обмена данными по сети.
Зачастую бывает так, что размышлять об CFR-требованиях начинают слишком поздно. Я настоятельно рекомендую рассматривать CFR-требования как можно раньше, а также регулярно заниматься их пересмотром.
Тесты производительности. Есть смысл вызывать тесты производительности непосредственно как способ убедиться в соблюдении некоторых межфункциональных требований. При разбиении систем на более мелкие микросервисы повышается количество вызовов, производимых через сетевые границы. Там, где прежде операция могла повлечь за собой один вызов базы данных, теперь она может стать причиной трех или четырех вызовов других сервисов через сетевые границы с соответствующим количеством вызовов баз данных. Все это может снизить скорость работы системы. При этом отслеживание источников задержек приобретает особую важность. Когда имеется последовательность из нескольких синхронных вызовов, замедление работы любой из частей этой последовательности затрагивает всю ее целиком, что потенциально приводит к существенному отрицательному воздействию. Это придает еще большую важность наличию какого-либо способа проведения теста производительности приложений, чем это могло бы быть при использовании более монолитной системы. Зачастую смысл выполнения такого тестирования возникает не сразу, поскольку изначально у системы для него недостаточно компонентов. Суть данной проблемы мне понятна, но довольно часто это приводит к совершенно необоснованному затягиванию и проведению тестов производительности непосредственно перед первым выпуском средства в производственную среду или же вообще к игнорированию этих тестов! Не попадайтесь на эту удочку.
Как и в случае с функциональными тестами, может понадобиться проведение неких тестовых комбинаций. Можно прийти к решению о необходимости выполнения тестов производительности, изолирующих отдельные сервисы, но начать с тестов, проверяющих основные маршруты, существующие в системе. Вам может представиться возможность взять сквозные тесты маршрутов и провести их в полном объеме.
Для получения полноценных результатов данные сценарии зачастую нужно будет запускать с постепенным увеличением количества имитируемых клиентов. Это позволит увидеть изменение задержек вызовов по мере роста рабочей нагрузки. Следовательно, выполнение тестов производительности может занять довольно много времени. Кроме того, чтобы гарантировать отображение в полученных результатах той производительности, которой можно ожидать при работе в производственном режиме, потребуется максимально приблизить систему к производственным параметрам. Это может означать, что вам потребуется достичь более похожего на производственную нагрузку объема данных и понадобится большее количество машин, чтобы соответствовать производственной инфраструктуре, а выполнить подобные задачи может быть весьма нелегко. Даже если вам трудно приблизить параметры тестовой среды к производственным, тесты все равно будут иметь ценность, выражающуюся в выявлении узких мест системы. Но все же нужно знать, что при этом вы можете получать недостоверные негативные или, что еще хуже, недостоверные позитивные результаты.
Из-за большого количества времени, затрачиваемого на проведение тестов производительности, возможность их выполнения в каждом контрольном случае представляется не всегда. Согласно сложившейся практике, запускать поднабор тестов нужно ежедневно, а более крупный набор — еженедельно. Но какой бы из подходов вы ни выбрали, следует запускать эти тесты как можно регулярнее. Чем дальше вы продвинетесь в своей работе без тестов производительности, тем сложнее будет отследить виновников ее снижения. Проблемы производительности весьма трудно устранить, поэтому, если есть такая возможность, нужно уменьшить количество изменений, требующих внимания, с целью выявления новых проблем, и тогда ваша работа станет значительно легче.
И непременно вникайте в результаты! Я был крайне удивлен количеством встреченных мною команд, тративших массу усилий на разработку и выполнение тестов и никогда не анализирующих получаемые значения. Зачастую это происходит по причине незнания того, как должны выглядеть приемлемые результаты. Вам нужны четко поставленные цели. Тогда вы сможете, основываясь на результатах, сделать сборку красной или зеленой и понять, что нужно сделать с красной (не прошедшей тесты) сборкой.
Тесты производительности должны выполняться в сочетании с мониторингом реальной производительности системы (который более подробно рассматривается в главе 8), и в идеале в среде проведения тестов производительности для визуализации поведения системы должны применяться те же инструменты, которые используются и при работе в производственном режиме. Это может существенно упростить сравнение работы в режиме тестирования и в производственном режиме.
Все затронутое в данной главе обобщенно можно назвать целостным подходом к тестированию, рассмотрение которого, я надеюсь, даст вам ряд верных направлений проведения таких тестов в ваших собственных системах. Повторим основные положения.
• Проводите оптимизацию в целях получения быстрых ответных результатов и соответствующего разделения тестов на типы.
• Избегайте использования сквозных тестов там, где можно воспользоваться контрактами на основе запросов потребителей.
• Используйте контракты на основе запросов потребителей для фокусировки вокруг них переговоров между командами разработчиков.
• Постарайтесь добиться разумного компромисса и решить, к чему все же следует прикладывать больше усилий — к тестированию или к ускоренному выявлению проблемных моментов при работе в производственном режиме (проводя оптимизацию либо под MTBF, либо под MTTR).
Если вы заинтересованы в получении дополнительных сведений о тестировании, я могу порекомендовать книгу Agile Testing (Addison-Wesley), написанную Лизой Криспин (Lisa Crispin) и Джанет Грегори (Janet Gregory), в которой, кроме всего прочего, более подробно рассмотрены вопросы использования секторов тестирования.
Основное внимание в данной главе уделялось приобретению уверенности в том, что код работает еще до того, как он попадет в работу в производственном режиме, но нам также нужно знать, как убедиться в том, что код будет работоспособен после развертывания. В следующей главе мы посмотрим, как проводить мониторинг систем, основанный на применении микросервисов.
8. Мониторинг
Я надеюсь, мне уже удалось показать вам, что разбиение системы на более мелкие, имеющие более высокую степень детализации микросервисы приводит к получению многочисленных преимуществ. Но при этом усложняется мониторинг систем, работающих в производственном режиме. В данной главе будут рассмотрены трудности, связанные с мониторингом и выявлением проблем в наших имеющих более высокую степень детализации системах, а также намечены некоторые подходы, которые можно применить для достижения вполне приемлемых результатов!
Представим следующую ситуацию. Пятница, вторая половина дня, команда уже собралась пораньше улизнуть в какой-нибудь бар, чтобы развеяться и славно встретить предстоящие выходные дни. И тут вдруг приходит сообщение по электронной почте: сайт стал чудить! В Twitter полно гневных посланий в адрес компании, ваш босс рвет и мечет, а перспективы спокойных выходных медленно тают.
В чем нужно разобраться в первую очередь? Что, черт возьми, пошло не так?