Как стать автором
Обновить

HTTP MITMProxy — помощник в разработке и тестировании

Уровень сложностиПростой
Время на прочтение6 мин
Количество просмотров5.9K
Всего голосов 1: ↑1 и ↓0+1
Комментарии13

Комментарии 13

ЗакрепленныеЗакреплённые комментарии

Сейчас попробую описать более конкретный пример.

Допустим есть программная система, реализующая полный цикл процессов продажи каких-либо билетов. Естественно, эта система берет билеты не из собственной БД. Она интегрирована с множеством различных поставщиков, которые их предлагают.
За продажу билета система берет какую-то динамечески определяемую наценку, которая включется в стоимость билета еще на этапе его поиска.

Цена у поставщика может измениться, это случай достаточно редкий, но возможный. Поэтому в момент бронирования, мы должны актуализировать данные о билете, чтоб не продать его себе в минус. Если цена в момент актуализации увеличилась, система должна уведомить об этом клиента, а процесс бронирования прерывается, возможно новая цена его не устроит. Если же цена уменьшилась, то система может заработать доп. прибыль, т.к. клиенту можно и не сообщать об изменении в меньшую сторону, а разницу забрать себе.

Или же другая ситация, в момент актуализации информации о билете, цена остается прежней, но меняются каки-то важные для клиента условия, и система должна клиента об этом уведомить.

Мы написали логику, которая реализует все описанные выше требования. Задача уходит на тестирование в QA-отдел. Но т.к. подобная ситуация происходит крайне редко, задача зависает в тестировании на долго. Рано или поздно к разрабочику приходит QA-специалист и говорит: "Хоть убей, не могу воспроизвести случай, когда изменятся условия.. Помоги, а?".

И тут разработчик становится перед выбором:
- брать на себя ответственность и давать добро лить правки в прод без апрува от QA отдела, т.к. они этот кейс проверить не могут
- начинает придумывать какие-то костыли на тестовом окружении, для того чтоб имитировать возникновение этой ситуации

Инструмент, описываемый в статье, нужен как-раз для того, чтоб разработчик не вставал перед таким выбором. Чтоб он вообще не был вовлечени в процесс тестирования, а спокойно продолжал заниматься разработкой своих задач и не отвлекался от работы, а QA могли сами без его помощи имитировать любые трудновоспроизводимые ситуации.

Идея подменять что то в запросах ходящих в проде плохая и опасная.

Логи и сквозной requestId должны давать возможность понимания что пошло не так.

Так речь и не о проде)

Логи и сквозной requestId должны давать возможность понимания что пошло не так.

Давать возможность понимания, и давать возможность повторения крайне редко возникающей ситуации - разные вещи


Смысл в предоставлении возможности интерактивной модификации запросов/ответов, ходящих не от клиента к серверу, а между сервером и другими системами, на тех окружениях, на которых разработчик сочтет это нужным (stage, dev, test - решает уже разработчик, а статья описывает возможности инструмента)

Если не прод, то тесты на контракты каждого сервиса будут эффективней

Мы видимо говорим о разных проблемах.

  • Тест контракта сервиса покроет структуру ответа, и с ней все может быть ок, но конкретные ее элементы могут иметь динамические значения, которые могут приводить к ошибкам в другом сервисе. В этом случае тест контракта не поможет.

  • Проблема может возникать не при взаимодействии внутренних сервисов, а при взаимодействии сервиса с внешней системой.

НЛО прилетело и опубликовало эту надпись здесь

Т.е. для того, что бы найти багу в уровне приложения

Не обязательно найти багу, скорее для воспроизведения ситуаций, которые могут приводить к этой баге (или чему-то еще), и для упрощения их тестирования

Сейчас попробую описать более конкретный пример.

Допустим есть программная система, реализующая полный цикл процессов продажи каких-либо билетов. Естественно, эта система берет билеты не из собственной БД. Она интегрирована с множеством различных поставщиков, которые их предлагают.
За продажу билета система берет какую-то динамечески определяемую наценку, которая включется в стоимость билета еще на этапе его поиска.

Цена у поставщика может измениться, это случай достаточно редкий, но возможный. Поэтому в момент бронирования, мы должны актуализировать данные о билете, чтоб не продать его себе в минус. Если цена в момент актуализации увеличилась, система должна уведомить об этом клиента, а процесс бронирования прерывается, возможно новая цена его не устроит. Если же цена уменьшилась, то система может заработать доп. прибыль, т.к. клиенту можно и не сообщать об изменении в меньшую сторону, а разницу забрать себе.

Или же другая ситация, в момент актуализации информации о билете, цена остается прежней, но меняются каки-то важные для клиента условия, и система должна клиента об этом уведомить.

Мы написали логику, которая реализует все описанные выше требования. Задача уходит на тестирование в QA-отдел. Но т.к. подобная ситуация происходит крайне редко, задача зависает в тестировании на долго. Рано или поздно к разрабочику приходит QA-специалист и говорит: "Хоть убей, не могу воспроизвести случай, когда изменятся условия.. Помоги, а?".

И тут разработчик становится перед выбором:
- брать на себя ответственность и давать добро лить правки в прод без апрува от QA отдела, т.к. они этот кейс проверить не могут
- начинает придумывать какие-то костыли на тестовом окружении, для того чтоб имитировать возникновение этой ситуации

Инструмент, описываемый в статье, нужен как-раз для того, чтоб разработчик не вставал перед таким выбором. Чтоб он вообще не был вовлечени в процесс тестирования, а спокойно продолжал заниматься разработкой своих задач и не отвлекался от работы, а QA могли сами без его помощи имитировать любые трудновоспроизводимые ситуации.

А почему бы не реализовать прокси для api поставщика, которое будет при необходимости что-то подменять и включать это прокси в конфиге приложения для тестирования по необходимости?

А можешь чуть детальнее раскрыть свою идею?

есть апи поставщика http://provider.com/api который возвращает json, с которым работает приложение

есть конфиг приложения, который использует это апи:
$apiUrl = "http://provider.com/api"

Реализовываем прокси http://provider.local задачи которого

  1. получить запрос к поставщику, как пришел от приложения

  2. отправить его в http://provider.com/api

  3. получить ответ от поставщика http://provider.com/api

  4. отдать ответ приложению

меняем конфиг тестового окружения приложения на:
$apiUrl = "http://provider.local"

теперь между пунктами 1 и 2, а также 3, 4 - делаем какие угодно преобразования запроса/ответа (внутри прокси provider.local, надо лишь реализовать интерфейс, который будет делать подмену значений)

допустим, в json ответе заменяем "доллар" на "зеленый":
в пункте 3 пришел доллар, делаем замену на зеленый, отдаем приложению модифицированный ответ

А если поставщиков 2, 3 ... 5? Это ведь все сторонние системы, с разными API. Имхо, идти по этому пути и под каждую систему писать новый proxy API - замахаешься.

К тому же, в твоем варианте решения этой проблемы, отсутствуют самые ключевые черты, которых я хотел добиться, а именно:

1. Полная независимость QA от отдела разработки.
QA сам новый прокси не напишет, на реализацию каждого такого прокси API нужно привлечь разработчика.

2. Ускорение процесса тестирования.
Если каждый раз, когда нам нужно будет проверить какой-то редкий кейс, для этого нужно будет писать целый сервис, обеспечивающий подмену данных, реализующий даже небольшую часть API поставщика, то ИМХО, проще уже обойтись костылями о которых я писал в статье, это будет гораздо проще и быстрее.

3. Возможность интерактивной модификации данных.
На самом деле, я рассматривал варианты мока API, перед тем как делать этот инструмент. Поверхностно ковырял такие штуки как mock-servers в Postman и Hoverfly, но того чего хотел, я там не нашел.

Чтоб воспроизвести какой-то кейс - нужно сначала подменить подключения к API, сделать запрос, записать дамп ответа, потом отредактировать его нужным образом и настроить mock метод API. Много рутины, не удобно, не гибко, и сложность настройки возрастает кратно росту сложности самого воспроизводимого кейса.

С помощью предлагаемого мной инструмента, достаточно 1 раз настроить на нужном окружении бэкэнд. После этого QA может отслеживать все отправляемые бэкэндом запросы, налету подменять их данные и данные ответов на них. Все это происходит в реал-тайм, без сложной конфигурации всяких-там mock, proxy серверов и т.д.

Конечно, все это можно было бы сделать и в предлагаемом вами мок-API, но это не такая и тривиальная задача, и если их будет несколько, то нужно будет думать как ее решать.

С http-client-mitmproxy этих проблем не возникает.

Я всего лишь описал идею. А дальше уже вопрос реализации и масштабирования.

Например, пишем абстрактный прокси, который по домену или урлу понимает, куда надо переслать данные:
http://proxy.local/provider1.com/
http://proxy.local/provider2.com/
и прописываем в конфигах приложения их.

Делаем интерфейс для QA, который содержит два инпута: что на что заменить.

Можно перед выполнением запроса подготовить маппинг "доллар->зеленый", можно заставить приложение ожидать и вообще в реалтайме менять ответ от поставщика.

  1. Прокси пишет разработчик и дает qa интерфейс.

  2. Не нужно реализовывать "небольшую часть API поставщика", proxy может передавать данные в точности так, как передает приложение. Банально regexpом делать замену одних данных на другие в ответе поставщика. Прокси не нужно понимать, как работать с конкретным поставщиком, чтобы просто передать данные дальше.

  3. Прокси позвоялет интерактивно менять данные (вопрос будет только в таймауте приложения): получили ответ от поставщика, дали интерфейс для QA, чтобы посомтреть на него, поменять, послать в приложение. Для приложения это будет просто тупящий запрос.

Главный минус твоего подхода - нужно модифицировать исходный код приложения. Вставлять такой код опасно, даже подразумевая, что он на прод не попадет/работать там не будет. Это потенциальная дыра.

Это звучит уже гораздо интереснее, такое описание реализации закрывает большую часть обсужденных выше проблем. Возможно через какое-то время эволюционным путём приду к чему-то подобному. Спасибо.

Вставлять такой код опасно, даже подразумевая, что он на прод не попадет/работать там не будет. Это потенциальная дыра.

С этим отчасти согласен, но если к задаче подойти с умом, то дыра маловероятная. Если так рассуждать, то и в конфиге прода можно подключение к proxy API настроить и это тоже будет потенциальная дыра.

В общем, вашу идею я понял, еще раз спасибо за дискуссию. Этот разговор подкинул мне парочку интересных мыслей)

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации