Комментарии 21
Ваши сценарии менеджеры тоже не будут и читать и писать и также придется следить за спецификациями и реализациями.
По-моему тема «Ну и зачем тогда Catcher?» не раскрыта.
Я лишь сделал упор на большое количество стандартных модулей и легкость их добавления, чтобы минимизировать количество кода, который должен написать конечный пользователь.
В идеале пользователь просто пишет свой тест, не задумываясь о необходимости что-то программировать, т.к. все модули уже написаны.
Её вполне себе можно и для интеграционных тестов применять.
Самое близкое по идеологии что есть, на мой взгляд — только Postman.
Ещё в стандартные модули нужен модуль «сервер», который поднимает сервер, ждёт какую-либо нотификацию и её проверяет.
Пара вопросов:
1. Сколько сейчас у вас есть тестов, использующих Catcher?
2. Верно ли, что все члены вашей команды пишут end-to-end тесты на этом инструменте?
3. Как давно вы применяете этот инструмент?
4. Минус `возможны дополнительные требования к квалификации разработчиков` никуда не делся. Теперь им требуется квалификация в использовании Catcher.
5. Сложилось ощущение, что вы заново реализуете логику запуска тестов (все эти сетапы, тирдауны...) и логику ассертов. Это действительно нужно? Я не знаю, что там в экосистеме Питона. Но, кажется, должно быть что-то готовое. (PyUnit?)
2. мы используем только этот инструмент для e2e, однако он не включает проверку фронтенда (на данный момент у нас нет нормальных тестов для фронтенда). Также не стоит путать юнит/интеграционные тесты и е2е. Все разработчики пишут юнит/интеграционные тесты, каждый стандартную технологию своего ЯП (pyunit/pytest/junit/eunit...). Но
3. использую этот инструмент уже около года, с тех пор как он появился.
4. да, требуется знание DSL кэтчера. Однако, он не привязан к какому-либо ЯП и по сути это просто стандартный yaml/json + спецификации шагов. Я специально сделал кэтчер простым и расширяемым. Свой первый тест можно написать за несколько минут.
5. не путайте е2е и интеграционные тесты. Вторые находятся непосредственно в бэкэнде и реализуются на стандартных технологиях для своего ЯП, с ассертом и моками. Запускаются на пул реквест при изменении этого бэкэнда и ничего не знают о зависимых сервисах (только моки). е2е же запускается сам по себе, обычно после деплоя на дев, либо по таймеру периодически и проверяет все сервисы в системе. Он изолирован от кода и тестирует API по принципу черного ящика.
Я вроде не путаю e2e и интеграционные тесты :)
Это я к чему написал. Верно ли, что разработать DSL, степы и логику работы с ними было оправданнее, чем просто написать эту логику на питоне? Тем более, если тестов немного (3-4, как вы пишете).
А еще через несколько лет в коде будет мешанина из-за бизнес логики тестов и реализации шагов (в 2ух компаниях уже на такое натыкался). И по итогу будет рефакторинг всего велосипеда, для разделения бизнес логики (увеличение читаемости и поддерживаемости самих тестов) и реализации доступа к сервисам/базам/другим компонентам.
Вот я и подумал, хочу ли я каждый раз изобретать кэтчер. Всего 4 таких тулза и я понял, что лучше что-то сделать 1 раз, чем каждый раз писать с 0.
Ну и польза для других опять таки. У меня сейчас 3-4 теста, а у кого-то, может, под 40.
У Фаулера хорошо описаны типы тестов. Вот здесь про интеграционные.
На практике, я не использую все те тесты, что он описал, т.к. не вижу смысла. Они часто друг друга дублируют, что не есть хорошо.
Обычно у меня есть:
- юнит тесты. Проверяют отдельные сложные алгоритмы (математика и т.п.). Обычно их мало.
- функциональные тесты. Проверяют какую-либо бизнес-функцию отдельного сервиса (на service-layer). Все другие сервисы, база данных и внешние сервисы замоккированы.
- интеграционные тесты. Проверяют всю бизнес-логику по принципу черного ящика без моков базы данных и service layer. Внешние зависимости все еще замоккированы. Можно относиться к ним, как к Controller тестам с реальным service layer и базой данных, но заглушками для внешних сервисов, если мы говорим об http-бэкэндах
- end-to-end тесты. Проверяют основную бизнес логику вместе со всеми зависимыми сервисами.
Первые 3 запускаются при изменении кода и локально. Для запуска им особо ничего не нужно (интеграционным нужна база данных/кеш, CI запускает через docker-compose).
Последние обычно запускаются на тестовом окружении (либо полностью поднимая все окружение в docker-compose, что может быть нереально) и им нужны все сервисы, задействованные в тесте (это главное отличие от интеграционных). Их время выполнения намного превышает все предыдущие вместе взятые.
Отличие интеграционных и e2e в том, что у e2e нет mock внешних сервисов, а у интеграционных — есть.
Возможно, мы с вами друг друга не понимаем ещё и потому, что интеграционные тесты можно проводить не только для какой-то подсистемы с набором микросервисов, но и интеграционные высшего уровня — интеграция между этими подсистемами.
И интеграционные — это не дорого. Как раз Catcher их упрощает. Дорого интеграционные писать на используемом ЯП.
И вот если в Catcher добавить сервер, получающий ответы — то это его превратит в отличную систему и для интеграционных тестов, где адрес этого сервера будет служить для моков.
Разница в том, что:
* DSL кэтчера — это стандартный json/yaml, который знает большинство.
* Тестируемая логика не зашита в сам инструмент тестирования. По моему опыту, года через 4 скриптовой ЯП с тестами будет напоминать кашу бизнес логики и реализации шагов (драйверы доступа к базам, очередям, хранилищам). И разработчик так или иначе попытается отделить реализацию от бизнес логики. Т.о. каждый, кто начнет со скриптового ЯП в итоге закончит своим собственным кэтчером.
бы его использовать.
А еще я вам предлагаю подщаманить его, написать небольшой парсер, или еще небольшую часть фреймворка, чтобы указывая путь на swagger.yaml он мог парсить подобные файлы и делать проверки на данные эндполинты которые описаны в таком формате:
schemes:
- "https"
- "http"
paths:
/pet:
post:
tags:
- "pet"
summary: "Add a new pet to the store"
description: ""
operationId: "addPet"
consumes:
- "application/json"
- "application/xml"
produces:
- "application/xml"
- "application/json"
parameters:
- in: "body"
name: "body"
description: "Pet object that needs to be added to the store"
required: true
schema:
$ref: "#/definitions/Pet"
responses:
405:
description: "Invalid input"
security:
- petstore_auth:
- "write:pets"
- "read:pets"
put:
tags:
- "pet"
summary: "Update an existing pet"
description: ""
operationId: "updatePet"
consumes:
- "application/json"
- "application/xml"
produces:
- "application/xml"
- "application/json"
parameters:
- in: "body"
name: "body"
description: "Pet object that needs to be added to the store"
required: true
schema:
$ref: "#/definitions/Pet"
responses:
400:
description: "Invalid ID supplied"
404:
description: "Pet not found"
405:
description: "Validation exception"
security:
- petstore_auth:
- "write:pets"
- "read:pets"
Тогда многие бы точно двинулись пользоваться им, и работа фреймворка была бы похожа больше на магию!)) Как идейка!)
Возьмем ваш проект, после регистрации пользователя почти в каждом из микросервисов должно же что-то произойти, где-то должны записаться данные в базу, где-то должен быть вызван внешний сервис, где-то отправлено сообщение в MQ, где то письмо и т.д. причем наверняка асинхронно. Как это все проверять непонятно, все эти микросервисы наружу таких API не представляют и представлять не должны. А проверка, что сервис ответил 2xx дает лишь ложную уверенность в протестированности.
Можно протестировать всю систему.
Разумеется каждый сервис в цепи задействованных сервисов изменяет данные по результатам своей работы (база/MQ/ftp/письмо). Catcher позволяет проверить любое изменение в базе данных или очереди сообщений с помощью соответствующих модулей.
В моем проекте на определенные запросы регистрации REST бэкэнд меняет данные в базе и/или посылает сообщения в кафку. Далее сервисы, которые подписаны на этот топик, получают сообщение, делают свои черные дела и пишут данные в базу/ftp/в другой топик. Третьи сервисы получают данные от вторых сервисов и опять что-то делают...
В регистрационном тесте по сообщениям в кафке и данным в базах я проверяю:
- Были ли задействаны все необходимые сервисы?
- Был ли пользователь реально зарегистрирован, или просто вернулось 200, а банковский счет не создался.
- Был ли порядок обработки сообщений правильным или кто-то опять перепутал топики.
- Правильно ли сервисы работают с данными, совместимы ли версии и схемы.
Все происходит асинхронно. Но для теста разницы нет. Мы последовательно проверяем выполнение бизнес логики. От начала регистрации до открытия банковского счета и посылки письма пользователю.
Вот тут описан пример такого теста для IOT сервисов. А тут реализован е2е тест с Travis интеграцией.
Но возможно я ошибаюсь, еще не сильно разбираюсь в автоматизации.
End-to-end тестирование микросервисов c Catcher