Pull to refresh

Comments 21

А в чем все-таки преимущество вашего решения перед BDD?
Ваши сценарии менеджеры тоже не будут и читать и писать и также придется следить за спецификациями и реализациями.
По-моему тема «Ну и зачем тогда Catcher?» не раскрыта.
UFO just landed and posted this here
Верно.
Я лишь сделал упор на большое количество стандартных модулей и легкость их добавления, чтобы минимизировать количество кода, который должен написать конечный пользователь.
В идеале пользователь просто пишет свой тест, не задумываясь о необходимости что-то программировать, т.к. все модули уже написаны.
Да я же джва года такую штуку ждал!
Её вполне себе можно и для интеграционных тестов применять.
Самое близкое по идеологии что есть, на мой взгляд — только Postman.
Ещё в стандартные модули нужен модуль «сервер», который поднимает сервер, ждёт какую-либо нотификацию и её проверяет.
Спасибо за интересную статью.
Пара вопросов:
1. Сколько сейчас у вас есть тестов, использующих Catcher?
2. Верно ли, что все члены вашей команды пишут end-to-end тесты на этом инструменте?
3. Как давно вы применяете этот инструмент?
4. Минус `возможны дополнительные требования к квалификации разработчиков` никуда не делся. Теперь им требуется квалификация в использовании Catcher.
5. Сложилось ощущение, что вы заново реализуете логику запуска тестов (все эти сетапы, тирдауны...) и логику ассертов. Это действительно нужно? Я не знаю, что там в экосистеме Питона. Но, кажется, должно быть что-то готовое. (PyUnit?)
1. в текущей компании 2 интеграционных теста, которые проверяют взаимодействие 5и сервисов (не так много тестировать). В предыдущей было 3-4 теста (я только начал применять там этот инструмент) для проверки взаимодействия 10+ сервисов.
2. мы используем только этот инструмент для e2e, однако он не включает проверку фронтенда (на данный момент у нас нет нормальных тестов для фронтенда). Также не стоит путать юнит/интеграционные тесты и е2е. Все разработчики пишут юнит/интеграционные тесты, каждый стандартную технологию своего ЯП (pyunit/pytest/junit/eunit...). Но только избранные пишут е2е тесты, т.к. это трудоемкий процесс, требующий понимания всей бизнес-логики.
3. использую этот инструмент уже около года, с тех пор как он появился.
4. да, требуется знание DSL кэтчера. Однако, он не привязан к какому-либо ЯП и по сути это просто стандартный yaml/json + спецификации шагов. Я специально сделал кэтчер простым и расширяемым. Свой первый тест можно написать за несколько минут.
5. не путайте е2е и интеграционные тесты. Вторые находятся непосредственно в бэкэнде и реализуются на стандартных технологиях для своего ЯП, с ассертом и моками. Запускаются на пул реквест при изменении этого бэкэнда и ничего не знают о зависимых сервисах (только моки). е2е же запускается сам по себе, обычно после деплоя на дев, либо по таймеру периодически и проверяет все сервисы в системе. Он изолирован от кода и тестирует API по принципу черного ящика.
Про 4 и 5.
Я вроде не путаю e2e и интеграционные тесты :)
Это я к чему написал. Верно ли, что разработать DSL, степы и логику работы с ними было оправданнее, чем просто написать эту логику на питоне? Тем более, если тестов немного (3-4, как вы пишете).
3-4 теста быстрее написать на любом скриптовом ЯП. Однако, через несколько лет к этим тестам добавятся еще тесты.
А еще через несколько лет в коде будет мешанина из-за бизнес логики тестов и реализации шагов (в 2ух компаниях уже на такое натыкался). И по итогу будет рефакторинг всего велосипеда, для разделения бизнес логики (увеличение читаемости и поддерживаемости самих тестов) и реализации доступа к сервисам/базам/другим компонентам.
Вот я и подумал, хочу ли я каждый раз изобретать кэтчер. Всего 4 таких тулза и я понял, что лучше что-то сделать 1 раз, чем каждый раз писать с 0.
Ну и польза для других опять таки. У меня сейчас 3-4 теста, а у кого-то, может, под 40.
На мой взгляд, вы в п.5 ошиблись насчёт интеграционных тестов (вероятно, имелись в виду юнит-тесты). e2e тесты и интеграционные — суть одно и то же, только e2e ближе к пользователю, а интеграционные — к бекенду. Интеграционные они так и называются, что тестируют интеграцию компонентов, а не один компонент с моками.

У Фаулера хорошо описаны типы тестов. Вот здесь про интеграционные.
На практике, я не использую все те тесты, что он описал, т.к. не вижу смысла. Они часто друг друга дублируют, что не есть хорошо.
Обычно у меня есть:


  • юнит тесты. Проверяют отдельные сложные алгоритмы (математика и т.п.). Обычно их мало.
  • функциональные тесты. Проверяют какую-либо бизнес-функцию отдельного сервиса (на service-layer). Все другие сервисы, база данных и внешние сервисы замоккированы.
  • интеграционные тесты. Проверяют всю бизнес-логику по принципу черного ящика без моков базы данных и service layer. Внешние зависимости все еще замоккированы. Можно относиться к ним, как к Controller тестам с реальным service layer и базой данных, но заглушками для внешних сервисов, если мы говорим об http-бэкэндах
  • end-to-end тесты. Проверяют основную бизнес логику вместе со всеми зависимыми сервисами.

Первые 3 запускаются при изменении кода и локально. Для запуска им особо ничего не нужно (интеграционным нужна база данных/кеш, CI запускает через docker-compose).


Последние обычно запускаются на тестовом окружении (либо полностью поднимая все окружение в docker-compose, что может быть нереально) и им нужны все сервисы, задействованные в тесте (это главное отличие от интеграционных). Их время выполнения намного превышает все предыдущие вместе взятые.

Я с вам не согласен. У вас корректное описание интеграционных тестов, но некорректный вывод, что для интеграционных тестов не нужны все сервисы. Почему не нужны? Интеграционные тесты так же проводятся на все сервисы. У них и название такое «интеграционные» — проверятся интеграция между сервисами.

Отличие интеграционных и e2e в том, что у e2e нет mock внешних сервисов, а у интеграционных — есть.
Возможно, мы с вами друг друга не понимаем ещё и потому, что интеграционные тесты можно проводить не только для какой-то подсистемы с набором микросервисов, но и интеграционные высшего уровня — интеграция между этими подсистемами.

И интеграционные — это не дорого. Как раз Catcher их упрощает. Дорого интеграционные писать на используемом ЯП.
И вот если в Catcher добавить сервер, получающий ответы — то это его превратит в отличную систему и для интеграционных тестов, где адрес этого сервера будет служить для моков.
В целом e2e тестов микросервисов вполне себе подходят обычные либы для юнит-тестирования аля junit + либа для запуска окружения в докере. для джава это, например, testcontainers. Либо уже действительно BDD и cucmber, если нужна человекочитаемость. Велосипедостроение — это всегда хорошо и похвально. Но насчет того, чем данная штука лучше уже существующих решений и почему вы не взяли их, тема не раскрыта.
Надеюсь что я ответил на ваш вопрос в хвосте статьи (см. обновление).
Чем это отличается от скриптового ЯП?
Можно без проблем реализовать все интеграционные тесты на питоне\руби\баш. Я описал этот вариант в статье.
Разница в том, что:
* DSL кэтчера — это стандартный json/yaml, который знает большинство.
* Тестируемая логика не зашита в сам инструмент тестирования. По моему опыту, года через 4 скриптовой ЯП с тестами будет напоминать кашу бизнес логики и реализации шагов (драйверы доступа к базам, очередям, хранилищам). И разработчик так или иначе попытается отделить реализацию от бизнес логики. Т.о. каждый, кто начнет со скриптового ЯП в итоге закончит своим собственным кэтчером.
Знает большинство, это как python знает большинство )
Не плохое решение для контрактных тестов… В конце статьи описывалось что такой инструмент был создан на определенном проекте и в определенных условиях, чтобы минимизировать количество кода… Я думаю надо было бы больше описать ваш частный случай или условия — по пунктам, при которых инженеры могли
бы его использовать.
А еще я вам предлагаю подщаманить его, написать небольшой парсер, или еще небольшую часть фреймворка, чтобы указывая путь на 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"


Тогда многие бы точно двинулись пользоваться им, и работа фреймворка была бы похожа больше на магию!)) Как идейка!)
У вас съехал синтаксис.
Идея хорошая.
Я поставлю ее в очередь. Не вижу ничего сложного в автогенерации тестов для вашего случая.
На данный момент я работаю над Web-UI для упрощения отладки и интеграции с CI.
Спасибо.
Интересно, но из статьи не очень понятно, что же в итоге выйдет протестировать.

Возьмем ваш проект, после регистрации пользователя почти в каждом из микросервисов должно же что-то произойти, где-то должны записаться данные в базу, где-то должен быть вызван внешний сервис, где-то отправлено сообщение в MQ, где то письмо и т.д. причем наверняка асинхронно. Как это все проверять непонятно, все эти микросервисы наружу таких API не представляют и представлять не должны. А проверка, что сервис ответил 2xx дает лишь ложную уверенность в протестированности.

Можно протестировать всю систему.
Разумеется каждый сервис в цепи задействованных сервисов изменяет данные по результатам своей работы (база/MQ/ftp/письмо). Catcher позволяет проверить любое изменение в базе данных или очереди сообщений с помощью соответствующих модулей.


В моем проекте на определенные запросы регистрации REST бэкэнд меняет данные в базе и/или посылает сообщения в кафку. Далее сервисы, которые подписаны на этот топик, получают сообщение, делают свои черные дела и пишут данные в базу/ftp/в другой топик. Третьи сервисы получают данные от вторых сервисов и опять что-то делают...


В регистрационном тесте по сообщениям в кафке и данным в базах я проверяю:


  • Были ли задействаны все необходимые сервисы?
  • Был ли пользователь реально зарегистрирован, или просто вернулось 200, а банковский счет не создался.
  • Был ли порядок обработки сообщений правильным или кто-то опять перепутал топики.
  • Правильно ли сервисы работают с данными, совместимы ли версии и схемы.
    Все происходит асинхронно. Но для теста разницы нет. Мы последовательно проверяем выполнение бизнес логики. От начала регистрации до открытия банковского счета и посылки письма пользователю.

Вот тут описан пример такого теста для IOT сервисов. А тут реализован е2е тест с Travis интеграцией.

Очень похоже на Karate DSL. Не рассматривали его?
Но возможно я ошибаюсь, еще не сильно разбираюсь в автоматизации.
Sign up to leave a comment.

Articles