Привет!
Ретро проекта Э идёт прям тяжело (тупо прокрастинирую его), поэтому решил написать микроретро очередного релиза.
В этом релизе, мы среди прочего сделали две большие штуки:
. Реализовали поддержку множества сессий пользователей - 73 файла, ~1200 строк изменений (ввели понятие сессии и привязали рефреш-токен к ней, а не пользователям. Плюс сделали бесшовную миграцию токенов);
. Серьёзно отрефакторили модуль наблюдения, поправив логические и технические ошибки в изначальной модели - 129 файлов, ~2300 строк изменений.
Ещё хочу напомнить, что месяц назад у нас в проекте всего было 23,944 строк кода и 730 классов.
То есть в этом релизе релизе мы потрогали процентов 15 всей кодов базы.
При этом:
. Багов, найденных командой QA за 3 дня тестирования релиз-кандидата - 0 (ноль);
. Багов, найденных заказчиком и пользователями за 5 дней использования релиза - 0 (ноль);
. Багов, найденных разработчиком по коду после мёржа в мастер - 1 (один);
Лично я считаю это выдающимся достижением.
Это, безусловно, преимущественно заслуга разработчиков, но и ЭП тоже внёс существенный вклад, на мой взгляд.
Как минимум в части тестов без моков и сфокусированных на проверке наблюдаемого поведения системы.
#why_ergo_approach@ergonomic_code #ergo_testing@ergonomic_code #project_e@ergonomic_code #case@ergonomic_code
Ретро проекта Э идёт прям тяжело (тупо прокрастинирую его), поэтому решил написать микроретро очередного релиза.
В этом релизе, мы среди прочего сделали две большие штуки:
. Реализовали поддержку множества сессий пользователей - 73 файла, ~1200 строк изменений (ввели понятие сессии и привязали рефреш-токен к ней, а не пользователям. Плюс сделали бесшовную миграцию токенов);
. Серьёзно отрефакторили модуль наблюдения, поправив логические и технические ошибки в изначальной модели - 129 файлов, ~2300 строк изменений.
Ещё хочу напомнить, что месяц назад у нас в проекте всего было 23,944 строк кода и 730 классов.
То есть в этом релизе релизе мы потрогали процентов 15 всей кодов базы.
При этом:
. Багов, найденных командой QA за 3 дня тестирования релиз-кандидата - 0 (ноль);
. Багов, найденных заказчиком и пользователями за 5 дней использования релиза - 0 (ноль);
. Багов, найденных разработчиком по коду после мёржа в мастер - 1 (один);
Лично я считаю это выдающимся достижением.
Это, безусловно, преимущественно заслуга разработчиков, но и ЭП тоже внёс существенный вклад, на мой взгляд.
Как минимум в части тестов без моков и сфокусированных на проверке наблюдаемого поведения системы.
#why_ergo_approach@ergonomic_code #ergo_testing@ergonomic_code #project_e@ergonomic_code #case@ergonomic_code
👍2🔥2👌2
Привет!
Вчера в Проекте Э пришлось подравить пару МРов своими собственными руками (редкое событие в последнее время, к сожалению), чтобы успеть заталкать в релиз.
И в обоих случаях ТДД спасло меня от внесения багов.
В первом случае мне надо было замапить ошибку нарушения уникальности констрейнта с 500 на доменно-специфичную. Я как и положено начал с теста, починил, увидел зелёный тест и пошёл рефакторить. И сломал. Благо тест отловил.
Во втором случае, я в оригинальном МРе убрал часть логики (обновление времени действия пользователя в одном из кейсов). А потом выяснилось что всё-таки обновлять время надо. На этот кейс теста не было, поэтому я опять же начал с него. Вернул оригинальный код и. Тест не прошёл. Там был баг. Который я благополучно починил.
В общем прям советую взять в практику разработку через тесты. А чтобы это не было мучитльно больно - писать тесты без моков и на максимально высоком уровне абстракции (с позиции пользователя)
#project_e@ergonomic_code #tdd@ergonomic_code #ergo_testing@ergonomic_code
Вчера в Проекте Э пришлось подравить пару МРов своими собственными руками (редкое событие в последнее время, к сожалению), чтобы успеть заталкать в релиз.
И в обоих случаях ТДД спасло меня от внесения багов.
В первом случае мне надо было замапить ошибку нарушения уникальности констрейнта с 500 на доменно-специфичную. Я как и положено начал с теста, починил, увидел зелёный тест и пошёл рефакторить. И сломал. Благо тест отловил.
Во втором случае, я в оригинальном МРе убрал часть логики (обновление времени действия пользователя в одном из кейсов). А потом выяснилось что всё-таки обновлять время надо. На этот кейс теста не было, поэтому я опять же начал с него. Вернул оригинальный код и. Тест не прошёл. Там был баг. Который я благополучно починил.
В общем прям советую взять в практику разработку через тесты. А чтобы это не было мучитльно больно - писать тесты без моков и на максимально высоком уровне абстракции (с позиции пользователя)
#project_e@ergonomic_code #tdd@ergonomic_code #ergo_testing@ergonomic_code
👍4🤔1
Привет!
Потока сознания пост
У нас тут в Проекте Э был аццкий баг на андроиде. Который заключался в том, что приложение случайным образом переставало подключаться к девайсу по блютузу. Угробили на него кучу времени, сил, денег, нервов, подключились всех кого можно включая меня. В результате фикс получился в 10 символов.
Изначальный код был примерно такой:
Видите баг? Фильтр мапит список на переменную, а потом проверяет что он содержит эту переменную. Очевидно он срабатывал для любого не пустого списка. Добавили в маппинг it.device.address и всё заработало. Я до сих пор не понимаю как - если есть эксперты по андроиду/бле - напишите, пожалуйста:)
Это мне напомнило тезис, что баги - это неверные предположения разработчика. В данном случае разработчик предполагал, что после фильтра у нас в результатах скана будет нужный нам девайс, а его не было.
Во втором баге из вчерашнего поста тоже было ошибочное предположение разработчика. Там в двух разных местах использовалось одно и то же поле для обновления времени последнего действия и разработчик предполагал, что в обоих случаях поле будет содержать текущее время. Что оказалось не так в одном из случаев.
Соответственно мысль №1 - хорошие тесты должны проверять предположения разработчика относительно кода. Например, сохранение сущности значит, что её потом можно достать по иду - вот это и надо проверять. А не то что ид обновился, или что был вызван метод репоза.
Отсюда мысль №2 - моки вносят дополнительный слой предположений. Стабая что-то, разработчик предполагает что вернёт за стабанный код. И может облажаться. Мокая и верифицируя что-то, разработчик предполагает что замоканный код пережуёт то, что разработчик ему дал и породит нужный разработчику эффект. И так же может облажаться.
Я не думаю что возможно (и экономически целесообразно) жить и кодить вообще без предположений и вообще все предположения проверять. Но рефлексировать на эту тему - точно хорошее упражнение.
#case@ergonomic_code #project_e@ergonomic_code #ergo_testing@ergonomic_code
Потока сознания пост
У нас тут в Проекте Э был аццкий баг на андроиде. Который заключался в том, что приложение случайным образом переставало подключаться к девайсу по блютузу. Угробили на него кучу времени, сил, денег, нервов, подключились всех кого можно включая меня. В результате фикс получился в 10 символов.
Изначальный код был примерно такой:
scanner.startScan(filters, settings)
.filter { foundDevices->
foundDevices.map { address }
.contains(address)
}
.take(1)
Видите баг? Фильтр мапит список на переменную, а потом проверяет что он содержит эту переменную. Очевидно он срабатывал для любого не пустого списка. Добавили в маппинг it.device.address и всё заработало. Я до сих пор не понимаю как - если есть эксперты по андроиду/бле - напишите, пожалуйста:)
Это мне напомнило тезис, что баги - это неверные предположения разработчика. В данном случае разработчик предполагал, что после фильтра у нас в результатах скана будет нужный нам девайс, а его не было.
Во втором баге из вчерашнего поста тоже было ошибочное предположение разработчика. Там в двух разных местах использовалось одно и то же поле для обновления времени последнего действия и разработчик предполагал, что в обоих случаях поле будет содержать текущее время. Что оказалось не так в одном из случаев.
Соответственно мысль №1 - хорошие тесты должны проверять предположения разработчика относительно кода. Например, сохранение сущности значит, что её потом можно достать по иду - вот это и надо проверять. А не то что ид обновился, или что был вызван метод репоза.
Отсюда мысль №2 - моки вносят дополнительный слой предположений. Стабая что-то, разработчик предполагает что вернёт за стабанный код. И может облажаться. Мокая и верифицируя что-то, разработчик предполагает что замоканный код пережуёт то, что разработчик ему дал и породит нужный разработчику эффект. И так же может облажаться.
Я не думаю что возможно (и экономически целесообразно) жить и кодить вообще без предположений и вообще все предположения проверять. Но рефлексировать на эту тему - точно хорошее упражнение.
#case@ergonomic_code #project_e@ergonomic_code #ergo_testing@ergonomic_code
👍3
Привет!
У меня для вас снова поучительная история про тесты.
У нас есть эндпоинт выдачи списка лекарств за разработкой которого я не много не доглядел и там разработчик не сделал сортировку. Этот список год не менялся и изначально данные в него внесли в правильном порядке, поэтому никто не замечал проблему.
А тут поменяли и ой.
И я пошёл добавлять сортировку своими мозолистыми руками.
Добавил, думаю надо тестом покрыть, покрыл, думаю надо увидеть как он превращается из красного в зелёный, сломал продовый код, а тест прошёл.
Смотрю - прошёл по той же причине, что и в проде год проблемы не было.
Ну думаю и ладно, чему там не работать, закоммитал, запушил, вмёржил вмастер.
Подтягиваю, мастер в ветку где это надо - а она не собирается О_О Тест не проходит. Потому что данные поменялись. А я продовый код не вернул перед коммитом 🤦♂️
Мораль этой басни - очень важно видеть как тест превращается из красного в зелёный.
Самый рациональный и надёжный способ это делать - писать сначала тесты.
Если вы пишите сначала продовый код - надо хотя бы ломать его после тестов, и убеждаться что они красные, а потом становятся зелёными.
Ну а если вы написали продовый код, написали тесты, они сразу прошли и вы на этом остановились - ну чтож, удачи в проде:)
#case@ergonomic_code #ergo_testing@ergonomic_code #tdd@ergonomic_code
У меня для вас снова поучительная история про тесты.
У нас есть эндпоинт выдачи списка лекарств за разработкой которого я не много не доглядел и там разработчик не сделал сортировку. Этот список год не менялся и изначально данные в него внесли в правильном порядке, поэтому никто не замечал проблему.
А тут поменяли и ой.
И я пошёл добавлять сортировку своими мозолистыми руками.
Добавил, думаю надо тестом покрыть, покрыл, думаю надо увидеть как он превращается из красного в зелёный, сломал продовый код, а тест прошёл.
Смотрю - прошёл по той же причине, что и в проде год проблемы не было.
Ну думаю и ладно, чему там не работать, закоммитал, запушил, вмёржил вмастер.
Подтягиваю, мастер в ветку где это надо - а она не собирается О_О Тест не проходит. Потому что данные поменялись. А я продовый код не вернул перед коммитом 🤦♂️
Мораль этой басни - очень важно видеть как тест превращается из красного в зелёный.
Самый рациональный и надёжный способ это делать - писать сначала тесты.
Если вы пишите сначала продовый код - надо хотя бы ломать его после тестов, и убеждаться что они красные, а потом становятся зелёными.
Ну а если вы написали продовый код, написали тесты, они сразу прошли и вы на этом остановились - ну чтож, удачи в проде:)
#case@ergonomic_code #ergo_testing@ergonomic_code #tdd@ergonomic_code
👍5
Привет!
У меня за топиками декомпозиции ретро Проекта Э не получается раскрыть тему тестирования. И вот какой-то добрый человек сделал это за меня. С реализацией я не во всём согласен (в частности на Gherkin я со скепсисом смотрю), но концептуально - фокус на компонентных тестах и тестирование сценариев - полностью согласен.
#posts@ergonomic_code #ergo_testing@ergonomic_code
У меня за топиками декомпозиции ретро Проекта Э не получается раскрыть тему тестирования. И вот какой-то добрый человек сделал это за меня. С реализацией я не во всём согласен (в частности на Gherkin я со скепсисом смотрю), но концептуально - фокус на компонентных тестах и тестирование сценариев - полностью согласен.
#posts@ergonomic_code #ergo_testing@ergonomic_code
Хабр
Как писать полезные тесты для микросервисов
Привет! Меня зовут Гриша и я бэкенд разработчик на .net С друзьями мы часто обсуждаем процессы разработки, в том числе как пишутся автотесты. Я часто слышу о подходах, которые несут боль...
🔥3
Привет!
Молния⚡️
Нас всех обманывали!!!
Они говорили, что моки нужны в том числе для того чтобы ускорять тесты. Но это не правда - тесты с моками (на выборке из одного) в три раза медленнее практически е2е теста, который идёт через HTTP в БД и парсит ответный HTML!
Может, конечно, дело в JIT-е, и если таких тестов будет больше - они разгонятся, но сам факт 🤯
Вобщем скорость тестов больше не является аргументом в пользу моков.
#ergo_testing@ergonomic_code #whynomocks@ergonomic_code
Молния
Нас всех обманывали!!!
Они говорили, что моки нужны в том числе для того чтобы ускорять тесты. Но это не правда - тесты с моками (на выборке из одного) в три раза медленнее практически е2е теста, который идёт через HTTP в БД и парсит ответный HTML!
Может, конечно, дело в JIT-е, и если таких тестов будет больше - они разгонятся, но сам факт 🤯
Вобщем скорость тестов больше не является аргументом в пользу моков.
#ergo_testing@ergonomic_code #whynomocks@ergonomic_code
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6❤2🔥2
Привет!
Опубликовал первый пост про тестирование TA с общими идеями и принципами (но уже здесь с иллюстрациями реальным кодом из TA).
#trainer_advisor@ergonomic_code #ergo_testing@ergonomic_code
Опубликовал первый пост про тестирование TA с общими идеями и принципами (но уже здесь с иллюстрациями реальным кодом из TA).
#trainer_advisor@ergonomic_code #ergo_testing@ergonomic_code
👍2
Привет!
Опубликовал второй кусочек описания тестирования Trainer Advisor - сетап system under test.
#trainer_advisor@ergonomic_code #ergo_testing@ergonomic_code
Опубликовал второй кусочек описания тестирования Trainer Advisor - сетап system under test.
#trainer_advisor@ergonomic_code #ergo_testing@ergonomic_code
🔥7❤1
И опубликовал очередной кусочек описания тестирования Trainer Advisor - формирование фикстурных объектов и их вставка в БД.
Там из 34К знаков 14К - код, почти половина:).
P.s. сбросьте кэш браузера, чтобы подтянуть css с выделеним строк в некоторых из сниппетов
#trainer_advisor@ergonomic_code #ergo_testing@ergonomic_code
Там из 34К знаков 14К - код, почти половина:).
P.s. сбросьте кэш браузера, чтобы подтянуть css с выделеним строк в некоторых из сниппетов
#trainer_advisor@ergonomic_code #ergo_testing@ergonomic_code
👍3
Привет!
Второй или третий раз смотрю де-факто один и тот же доклад про ТДД и не устаю его рекомендовать - в этот раз по мотивам доклада у меня снова родилась пачка мыслей.
Мысль №1
В докладе мужик привёл пару определений:
> Падение юнит-теста подразумевает сбой ровно в одном юните (методе, классе, модуле, пакете)
> Падение девелоперского теста подразумевает ошибку в последнем изменении кода
И мысль ещё из Бековской TDD by Example - кол-во кода, которое вы пишите между запусками тестов зависит от вашей уверенности в умении писать такой код.
И аналогия с вождением машины - чем увереннее вы себя чувствуете, тем быстрее вы едете.
И это прям хорошо легло на мой свежий опыт:
1. В Trainer Advisor у меня примерно 3-4 теста на HTTP-эндпоинт. И ~95% - работают либо через хттп, либо через конторллер
2. А недавно я написал один хттп эндпоинт, с 22 тестами из которых <50% работают через http.
В чём разница? В TA львиная доля эндпоинтов - примитивный КРУД - перегнать ДТО в сущность, сохранить сущность; вычитать ДТО из БД, вернуть - я это пишу спинным мозгом и там граничных случаев ноль целых хрен десятых.
А в методе из п.2 был не совсем тривиальный алгоритм с пачкой граничных условий и я не был уверен, что сходу напишу всё правильно.
В этом и разница.
—
Мысль №2
Что переход на более низкий уровень абстракции, что использование мока - снижают устойчивость тестов к рефакторингу и, как следствие, увеличивают стоимость разработки (читай: вашу нервотрёпку). Но, при этом снижают стоимость разработки самих тестов. И надо стараться искать оптимальное соотношение разных типов тестов, которое обеспечит минимальную стоимость разработки (читай: вашей нервотрёпки). Пока могу предложить это только в качестве лозунга - как конкретно искать этот баланс я не знаю.
—
Мысль №3
Возможно молодые подписчики ещё не сталкивались с http://wiki.c2.com/. Это самая первая вики в мире из 1995 года. От чувака, который придумал гексагональную архитектуру. И в которой в старые добрые времена тусила вся старая гвардия - начиная с самого Кокберна и продолжая анкл Бобом, Фаулером, Беком, Коплейном. Можно выделить вечерок и пошататься по ней впитывая мудрость древних.
—
Мысль №4
Чёт то ли я туплю, то ли у мужика не стыковка - он сначала пинает тесты с моками, за то что они мешают рефакторингу. А в конце доклада предлагает писать тесты на код интеграций с моками. Чтобы их потом не рефакторить?
—
Мысль №5
Мужик топит, за то, что код с вводом-выводом надо тестировать как-то по другому, потому что он медленный и хрупкий. И, видимо, раз я решил проблемы скорости и хрупкости такого кода, то мне можно и для него писать нормальные тесты. Можно же?
—
Мысль №6
У мужика в докладе ни строчки кода нет. А у меня есть ~150 "developer tests", которые "tests behaviour, not functions" и для которых процентов на 30 готово описание идей и техник как, такие тесты писать
#talks@ergonomic_code #ergo_testing@ergonomic_code #tdd@ergonomic_code #whynomocks@ergonomic_code
Второй или третий раз смотрю де-факто один и тот же доклад про ТДД и не устаю его рекомендовать - в этот раз по мотивам доклада у меня снова родилась пачка мыслей.
Мысль №1
В докладе мужик привёл пару определений:
> Падение юнит-теста подразумевает сбой ровно в одном юните (методе, классе, модуле, пакете)
> Падение девелоперского теста подразумевает ошибку в последнем изменении кода
И мысль ещё из Бековской TDD by Example - кол-во кода, которое вы пишите между запусками тестов зависит от вашей уверенности в умении писать такой код.
И аналогия с вождением машины - чем увереннее вы себя чувствуете, тем быстрее вы едете.
И это прям хорошо легло на мой свежий опыт:
1. В Trainer Advisor у меня примерно 3-4 теста на HTTP-эндпоинт. И ~95% - работают либо через хттп, либо через конторллер
2. А недавно я написал один хттп эндпоинт, с 22 тестами из которых <50% работают через http.
В чём разница? В TA львиная доля эндпоинтов - примитивный КРУД - перегнать ДТО в сущность, сохранить сущность; вычитать ДТО из БД, вернуть - я это пишу спинным мозгом и там граничных случаев ноль целых хрен десятых.
А в методе из п.2 был не совсем тривиальный алгоритм с пачкой граничных условий и я не был уверен, что сходу напишу всё правильно.
В этом и разница.
—
Мысль №2
Что переход на более низкий уровень абстракции, что использование мока - снижают устойчивость тестов к рефакторингу и, как следствие, увеличивают стоимость разработки (читай: вашу нервотрёпку). Но, при этом снижают стоимость разработки самих тестов. И надо стараться искать оптимальное соотношение разных типов тестов, которое обеспечит минимальную стоимость разработки (читай: вашей нервотрёпки). Пока могу предложить это только в качестве лозунга - как конкретно искать этот баланс я не знаю.
—
Мысль №3
Возможно молодые подписчики ещё не сталкивались с http://wiki.c2.com/. Это самая первая вики в мире из 1995 года. От чувака, который придумал гексагональную архитектуру. И в которой в старые добрые времена тусила вся старая гвардия - начиная с самого Кокберна и продолжая анкл Бобом, Фаулером, Беком, Коплейном. Можно выделить вечерок и пошататься по ней впитывая мудрость древних.
—
Мысль №4
Чёт то ли я туплю, то ли у мужика не стыковка - он сначала пинает тесты с моками, за то что они мешают рефакторингу. А в конце доклада предлагает писать тесты на код интеграций с моками. Чтобы их потом не рефакторить?
—
Мысль №5
Мужик топит, за то, что код с вводом-выводом надо тестировать как-то по другому, потому что он медленный и хрупкий. И, видимо, раз я решил проблемы скорости и хрупкости такого кода, то мне можно и для него писать нормальные тесты. Можно же?
—
Мысль №6
У мужика в докладе ни строчки кода нет. А у меня есть ~150 "developer tests", которые "tests behaviour, not functions" и для которых процентов на 30 готово описание идей и техник как, такие тесты писать
#talks@ergonomic_code #ergo_testing@ergonomic_code #tdd@ergonomic_code #whynomocks@ergonomic_code
YouTube
TDD Revisited - Ian Cooper - NDC Porto 2023
This talk was recorded at NDC Porto in Porto, Portugal. #ndcporto #ndcconferences #testing #tdd #softwaredeveloper
Attend the next NDC conference near you:
https://ndcconferences.com
https://ndcporto.com/
Subscribe to our YouTube channel and learn…
Attend the next NDC conference near you:
https://ndcconferences.com
https://ndcporto.com/
Subscribe to our YouTube channel and learn…
👍5❤1
Привет!
Опубликовал пост с последним кусочком описания сетапа фикстуры Trainer Advisor - сетап тестовых дублей.
В этом посте для полноты картины я добавил бонус-трек с описанием сетапа тестовых дублей для тестирования работы с внешними веб-сервисами, кроликом, кафкой и MQTT-брокером.
И под это дело добавил соответствующий бонус-трек в пост с описанием запуска инфраструктуры.
#trainer_advisor@ergonomic_code #ergo_testing@ergonomic_code #whynomocks@ergonomic_code
Опубликовал пост с последним кусочком описания сетапа фикстуры Trainer Advisor - сетап тестовых дублей.
В этом посте для полноты картины я добавил бонус-трек с описанием сетапа тестовых дублей для тестирования работы с внешними веб-сервисами, кроликом, кафкой и MQTT-брокером.
И под это дело добавил соответствующий бонус-трек в пост с описанием запуска инфраструктуры.
#trainer_advisor@ergonomic_code #ergo_testing@ergonomic_code #whynomocks@ergonomic_code
❤5👍2
Привет!
Я в Project Mariotte сделал страшное - перешёл на MockMvc.
Изначальная мотивация была в том, чтобы сэкономить секунду на запуске Tomcat.
Потом выяснилось, что инициализация RestAssured занимает ещё секунду, которую тоже можно сэкономить
Но последним аргументом стало то, что со WebTestClient можно переехать на работу через HTTP затри четыре простых шага.
И это навело меня на мысли об эволюции ЭП от сложного к простому за последние 4 года.
В конце 19-ого - начале 20-ого года можно было сказать, что ЭП = модульный монолит + тесты без моков + ДДД + чистая архитектура + railway-oriented programming на монадах.
И на тот момент, это всё (на мой взгляд) были маргинальные идеи, не имеющие широкого распространения.
Но за прошедшие 4 года, они все если не вошли, то сильно приблизились к мейнстриму, на мой взгляд.
А я с ЭП за эти же 4 года то ли ушёл вперёд, то ли откатился назад:
1. К модульному монолиту добавились цитадели, а для самого монолита появилось ограничение, что типовой тест должен отрабатывать не больше чем за 30 секунд
2. В тестировании добавилось разрешение на использование моков для симуляции ошибок инфраструктуры и для дорогой инфраструктуры. И свеженькое разрешение на использование MockMvc, при условии, что код самих клиентв (тест-кейсов) на него не завязан.
3. От ДДД осталась только декомпозиция модели на агрегаты, но по более приземлённой технологии на базе жизненного цикла сущностей и транзакционного анализа; а вместо ограниченных контекстов - декомпозиция на базе эффектов;
4. Чистую архитектуру я заменил на тщательное проектирование интерфейсов;
5. ROP на монадах, наконец, я заменил на Guard clause.
И при этом Эргономичный подход остаётся совместимым со всеми этими идеями там, где это надо:
1. Цитадель оказалась плохой затеей? Затолкать её обратно в монолит - вообще не проблема;
2. Тестов на моках стало слишком много или появилось слишком много багов в обработке ошибок? Поменять моки на стабы - уже сложнее, но тоже вполне решаемая задача;
3. В проекте появилась сложная предметная область и/или эксперт по ней? Перейти на ограниченные контексты и агрегаты на базе инвариантов - без проблем, вся инфраструктура и структура кодовой базы готовы;
4. В проекте появилась необходимость менять инфраструктуру без пересборки/перезапуска? Вытащить интерфейс из существующего класса - дело 5 минут. С реализацией сложнее, но это другой вопрос;
5. В проекте появилась потребность на лету собирать пайплайны? Обернуть имеющиеся вызовы эффективных методов в монады не составит труда.
А прямо сейчас, в моменте, ваш код будет максимально простым, без лишних сложностей и архитектуры.
Изначально Эргономичный подход был глотком свежего воздуха для тех, кто устал от хаоса и багов императивной слоёнки с тестами на моках.
Теперь Эргономичный подход стал глотком свежего воздуха для тех, кто устал от поисков стороны, с которой подойти к ДДД, церемоний чистой архитектуры и сложностей объяснения монад простым смертным.
В общем, покой нам только снится:)
#ergo_approach@ergonomic_code #project_mariotte@ergonomic_code #tdd@ergonomic_code #ergo_testing@ergonomic_code #mocks@ergonomic_code #clean_architecture@ergonomic_code #functional_architecture@ergonomic_code #ddd@ergonomic_code #rop@ergonomic_code
Я в Project Mariotte сделал страшное - перешёл на MockMvc.
Изначальная мотивация была в том, чтобы сэкономить секунду на запуске Tomcat.
Потом выяснилось, что инициализация RestAssured занимает ещё секунду, которую тоже можно сэкономить
Но последним аргументом стало то, что со WebTestClient можно переехать на работу через HTTP за
И это навело меня на мысли об эволюции ЭП от сложного к простому за последние 4 года.
В конце 19-ого - начале 20-ого года можно было сказать, что ЭП = модульный монолит + тесты без моков + ДДД + чистая архитектура + railway-oriented programming на монадах.
И на тот момент, это всё (на мой взгляд) были маргинальные идеи, не имеющие широкого распространения.
Но за прошедшие 4 года, они все если не вошли, то сильно приблизились к мейнстриму, на мой взгляд.
А я с ЭП за эти же 4 года то ли ушёл вперёд, то ли откатился назад:
1. К модульному монолиту добавились цитадели, а для самого монолита появилось ограничение, что типовой тест должен отрабатывать не больше чем за 30 секунд
2. В тестировании добавилось разрешение на использование моков для симуляции ошибок инфраструктуры и для дорогой инфраструктуры. И свеженькое разрешение на использование MockMvc, при условии, что код самих клиентв (тест-кейсов) на него не завязан.
3. От ДДД осталась только декомпозиция модели на агрегаты, но по более приземлённой технологии на базе жизненного цикла сущностей и транзакционного анализа; а вместо ограниченных контекстов - декомпозиция на базе эффектов;
4. Чистую архитектуру я заменил на тщательное проектирование интерфейсов;
5. ROP на монадах, наконец, я заменил на Guard clause.
И при этом Эргономичный подход остаётся совместимым со всеми этими идеями там, где это надо:
1. Цитадель оказалась плохой затеей? Затолкать её обратно в монолит - вообще не проблема;
2. Тестов на моках стало слишком много или появилось слишком много багов в обработке ошибок? Поменять моки на стабы - уже сложнее, но тоже вполне решаемая задача;
3. В проекте появилась сложная предметная область и/или эксперт по ней? Перейти на ограниченные контексты и агрегаты на базе инвариантов - без проблем, вся инфраструктура и структура кодовой базы готовы;
4. В проекте появилась необходимость менять инфраструктуру без пересборки/перезапуска? Вытащить интерфейс из существующего класса - дело 5 минут. С реализацией сложнее, но это другой вопрос;
5. В проекте появилась потребность на лету собирать пайплайны? Обернуть имеющиеся вызовы эффективных методов в монады не составит труда.
А прямо сейчас, в моменте, ваш код будет максимально простым, без лишних сложностей и архитектуры.
Изначально Эргономичный подход был глотком свежего воздуха для тех, кто устал от хаоса и багов императивной слоёнки с тестами на моках.
Теперь Эргономичный подход стал глотком свежего воздуха для тех, кто устал от поисков стороны, с которой подойти к ДДД, церемоний чистой архитектуры и сложностей объяснения монад простым смертным.
В общем, покой нам только снится:)
#ergo_approach@ergonomic_code #project_mariotte@ergonomic_code #tdd@ergonomic_code #ergo_testing@ergonomic_code #mocks@ergonomic_code #clean_architecture@ergonomic_code #functional_architecture@ergonomic_code #ddd@ergonomic_code #rop@ergonomic_code
GitHub
GitHub - ergonomic-code/Project-Mariotte: Демонстрационный проект Эргономичного подхода - сервис бронирования номеров в отелях
Демонстрационный проект Эргономичного подхода - сервис бронирования номеров в отелях - ergonomic-code/Project-Mariotte
👌2
Эргономичный код
Привет! Я в Project Mariotte сделал страшное - перешёл на MockMvc. Изначальная мотивация была в том, чтобы сэкономить секунду на запуске Tomcat. Потом выяснилось, что инициализация RestAssured занимает ещё секунду, которую тоже можно сэкономить Но последним…
После Project Mariotte я перенёс подход с MockMVC на другой (закрытый) проект и словил там проблему - по дефолту настройки секьюрити не подтянутся.
Для того чтобы их прикрутить надо:
1. Не забыть добавить зависимость
2. Донастроить webTestClient:
Возможно там где-то дальше ещё какие-то грабли есть, но меня утешает мысль, что вернуться к тестам через HTTP можно будет лёгким движением руки
#ergo_testing@ergonomic_code #tdd@ergonomic_code #mockmvc@ergonomic_code #springsecurity@ergonomic_code #webtestclient@ergonomic_code
Для того чтобы их прикрутить надо:
1. Не забыть добавить зависимость
testImplementation("org.springframework.security:spring-security-test")
2. Донастроить webTestClient:
client = MockMvcWebTestClient
.bindToApplicationContext(applicationContext)
.apply(springSecurity(FilterChainProxy(securityFilterChain)))
.configureClient()
.defaultHeader("Content-Type", "application/json")
.build()
Возможно там где-то дальше ещё какие-то грабли есть, но меня утешает мысль, что вернуться к тестам через HTTP можно будет лёгким движением руки
#ergo_testing@ergonomic_code #tdd@ergonomic_code #mockmvc@ergonomic_code #springsecurity@ergonomic_code #webtestclient@ergonomic_code
👍4
Привет!
Сроки по Проекту Р уже полыхают синим пламенем но я, тем не менее, повыкраивал по чуть-чуть времени на микропост с описанием того, как я добился сетапа свежей БД на 300+ таблиц за 1.5 секунды.
#ergo_testing@ergonomic_code #tdd@ergonomic_code #integration_tests@ergonomic_code #project_r@ergonomic_code
Сроки по Проекту Р уже полыхают синим пламенем но я, тем не менее, повыкраивал по чуть-чуть времени на микропост с описанием того, как я добился сетапа свежей БД на 300+ таблиц за 1.5 секунды.
#ergo_testing@ergonomic_code #tdd@ergonomic_code #integration_tests@ergonomic_code #project_r@ergonomic_code
👍5
Привет!
Говорят, чёрный пиар - это тоже пиар, поэтому надеюсь пацаны из Spring АйО (Саша, привет! 👋 ) не сильно обидятся, что я их пост разнесу чутка:)
Пример теста в посте имеет две проблемы
Проблема первая - непонятно, что тестирует этот тест
Вообще, вроде как, он должен тестировать клиента внешней системы. Но фактически, он тестирует не клиента внешней системы, а просто фиксирует вызовы Spring-овго АПИ (читай: детали реализации).
И если внешняя система поменяет формат ответа на json - код сломается, а тест продолжит проходить.
А если я перепишу клиента на restTemplate (и проверю руками) - код будет работать, а тест сломается.
Проблема вторая - он нарушает хрестоматийное правило тестов с моками
Мокайте только собственные типы (см. Growing Object-Oriented Software, Guided by Tests, Chapter 8)
—
Как это надо было делать
Вариант №1: идеальный
Поднять в тестконтейнере latest-версию внешней системы и написать тест, который бы работал с ней.
Такой тест:
1. ни как бы не был завязан на реализацию - вы с внешней системой могли бы хоть на protobuf перейти и в самом тесте вообще ничего менять бы не пришлось
1.1. Как следствие он бы подстраховал вас и если бы вы решили поменять либу для работы с хттп (на тот же RestTemplate, например)
2. поймает ошибки обратной совместимости внешнего АПИ, особенно если его регулярно на CI запускать
3. поймает регрессии в Spring
4. Ну и, очевидно, поймает если нарушите контракт (например, при рефакторинге идея затупит и поменяет слово в пути)
5. а ещё вы сможете его использовать в процессе разработки и соответственно быстро итерироваться с кодом реализации клиента, не рестаруя всё приложение целиком или не костыляя какой-то отдельный main-метод для этих целей
В общем он будет вашим другом - когда и если вы захотите поменять код клиента, он не будет вам мешать просто так и подскажет, если вы что-то сломаете.
Но это (внешняя система в докере) - практически нереальный вариант.
Вариант №2: реальный
Соответственно следующий вариант - написать тест, который работает с тестовым контуром внешней системы. Скорее всего, его придётся засунуть под флаг и запускать только на CI.
Он продолжит быть вашим другом, но и принесёт ряд проблем:
1. скорее всего он будет медленный
2. возможно он будет мигать
3. сообщать о проблемах он будет позже, чем хотелось бы
Вариант №3: cомнительно, но окей
Если варианты выше не возможны, либо не приемлемы (слишком медленно, слишком часто мигает) - можно взять WireMock.
В этом варианте вы потеряете контроль соблюдения контракта вами и внешней системой, но хотя бы останется контроль, соблюдения контракта вами и Spring-ом. Соответственно такой тест подстрахует вас, если вы решите поменять либу работы с ХТТП, либо обновите версию Spring.
Но я бы на такие тесты вообще не заморачивался - это всё будет покрыто тестами, клиентов нашего клиента, которым для работы надо будет, чтобы InspirationalQuotesClient смог взять данные.
Вариант №4: кто-то в интернете считает, что так правильно, но он не прав
Собственно мокисты считают, что правильно:
1. InspirationalQuotesClient покрыть интеграционным тестом (варианты 1-3 выше), либо не покрывать тестами вообще
2. А в тесте клиента InspirationalQuotesClient замокать уже сам InspirationalQuotesClient, а не WebClient
Но на самом деле правильно:
1. операцию, в которой задействован InspirationalQuotesClient покрыть одним интеграционным тестом, который:
1.1. всю управляемую инфраструктуру (БД, очередь сообщений, внутренние сервисы) поднимает в тест контейнерах и работает с ней
1.2. везде где возможно для неуправляемой инфраструктуры поднимает фейки на транспортном уровне (WireMock)
1.3. В самом крайнем случае мокает свои типы, которые абстрагируют внешнюю инфру, которую по другому не симулировать никак
2. Эту операцию сделать сбалансированной
3. И получить возможность всю бизнес-логику (которая даже косвенно через интерфейсы не зависит от внешних систем) покрыть чистыми юнит тестами, без спринга, моков, тестконтейнеров и т.д.
#ergo_testing@ergonomic_code
Говорят, чёрный пиар - это тоже пиар, поэтому надеюсь пацаны из Spring АйО (Саша, привет! 👋 ) не сильно обидятся, что я их пост разнесу чутка:)
Пример теста в посте имеет две проблемы
Проблема первая - непонятно, что тестирует этот тест
Вообще, вроде как, он должен тестировать клиента внешней системы. Но фактически, он тестирует не клиента внешней системы, а просто фиксирует вызовы Spring-овго АПИ (читай: детали реализации).
И если внешняя система поменяет формат ответа на json - код сломается, а тест продолжит проходить.
А если я перепишу клиента на restTemplate (и проверю руками) - код будет работать, а тест сломается.
Проблема вторая - он нарушает хрестоматийное правило тестов с моками
Мокайте только собственные типы (см. Growing Object-Oriented Software, Guided by Tests, Chapter 8)
—
Как это надо было делать
Вариант №1: идеальный
Поднять в тестконтейнере latest-версию внешней системы и написать тест, который бы работал с ней.
Такой тест:
1. ни как бы не был завязан на реализацию - вы с внешней системой могли бы хоть на protobuf перейти и в самом тесте вообще ничего менять бы не пришлось
1.1. Как следствие он бы подстраховал вас и если бы вы решили поменять либу для работы с хттп (на тот же RestTemplate, например)
2. поймает ошибки обратной совместимости внешнего АПИ, особенно если его регулярно на CI запускать
3. поймает регрессии в Spring
4. Ну и, очевидно, поймает если нарушите контракт (например, при рефакторинге идея затупит и поменяет слово в пути)
5. а ещё вы сможете его использовать в процессе разработки и соответственно быстро итерироваться с кодом реализации клиента, не рестаруя всё приложение целиком или не костыляя какой-то отдельный main-метод для этих целей
В общем он будет вашим другом - когда и если вы захотите поменять код клиента, он не будет вам мешать просто так и подскажет, если вы что-то сломаете.
Но это (внешняя система в докере) - практически нереальный вариант.
Вариант №2: реальный
Соответственно следующий вариант - написать тест, который работает с тестовым контуром внешней системы. Скорее всего, его придётся засунуть под флаг и запускать только на CI.
Он продолжит быть вашим другом, но и принесёт ряд проблем:
1. скорее всего он будет медленный
2. возможно он будет мигать
3. сообщать о проблемах он будет позже, чем хотелось бы
Вариант №3: cомнительно, но окей
Если варианты выше не возможны, либо не приемлемы (слишком медленно, слишком часто мигает) - можно взять WireMock.
В этом варианте вы потеряете контроль соблюдения контракта вами и внешней системой, но хотя бы останется контроль, соблюдения контракта вами и Spring-ом. Соответственно такой тест подстрахует вас, если вы решите поменять либу работы с ХТТП, либо обновите версию Spring.
Но я бы на такие тесты вообще не заморачивался - это всё будет покрыто тестами, клиентов нашего клиента, которым для работы надо будет, чтобы InspirationalQuotesClient смог взять данные.
Вариант №4: кто-то в интернете считает, что так правильно, но он не прав
Собственно мокисты считают, что правильно:
1. InspirationalQuotesClient покрыть интеграционным тестом (варианты 1-3 выше), либо не покрывать тестами вообще
2. А в тесте клиента InspirationalQuotesClient замокать уже сам InspirationalQuotesClient, а не WebClient
Но на самом деле правильно:
1. операцию, в которой задействован InspirationalQuotesClient покрыть одним интеграционным тестом, который:
1.1. всю управляемую инфраструктуру (БД, очередь сообщений, внутренние сервисы) поднимает в тест контейнерах и работает с ней
1.2. везде где возможно для неуправляемой инфраструктуры поднимает фейки на транспортном уровне (WireMock)
1.3. В самом крайнем случае мокает свои типы, которые абстрагируют внешнюю инфру, которую по другому не симулировать никак
2. Эту операцию сделать сбалансированной
3. И получить возможность всю бизнес-логику (которая даже косвенно через интерфейсы не зависит от внешних систем) покрыть чистыми юнит тестами, без спринга, моков, тестконтейнеров и т.д.
#ergo_testing@ergonomic_code
Telegram
Эргономичный код
🔗 Создание Deep Stubs в Mockito
При юнит-тестировании часто требуется проверить методы, которые используют цепочки вызовов, например, в WebClient из Spring WebFlux.
⚠️ Если задача позволяет, лучше воспользоваться MockWebServer или WireMock для гибкого тестирования…
При юнит-тестировании часто требуется проверить методы, которые используют цепочки вызовов, например, в WebClient из Spring WebFlux.
⚠️ Если задача позволяет, лучше воспользоваться MockWebServer или WireMock для гибкого тестирования…
👍4❤3
Что ещё почитать на тему тестирования
Принципы юнит тестирования - самая крутая книга на эту тему
TDD Revisited - Ian Cooper - NDC Porto 2023 - суть здорового тестирования за час пятнадцать
Пачка постов у меня про тестирование Trainer Advisor
Подборки постов у меня в канале - #tdd #nomocks
#ergo_testing@ergonomic_code #books@ergonomic_code #talks@ergonomic_code #posts@ergonomic_code
Принципы юнит тестирования - самая крутая книга на эту тему
TDD Revisited - Ian Cooper - NDC Porto 2023 - суть здорового тестирования за час пятнадцать
Пачка постов у меня про тестирование Trainer Advisor
Подборки постов у меня в канале - #tdd #nomocks
#ergo_testing@ergonomic_code #books@ergonomic_code #talks@ergonomic_code #posts@ergonomic_code
www.piter.com
Принципы юнит-тестирования
Практика модульного тестирования - это практическое руководство по современным методам модульного тестирования.
👍9
Карта канала
Добро пожаловать на канал "Эргономичный код" — канал о разработке поддерживаемых кодовых баз в общем и моём подходе к этой задаче — Эргономичном подходе.
Что такое Эргономичный подход?
По большому счёту это небольшой набор принципов, взятых в основном из классической школы TDD, функциональной архитектуры и DDD, и большой набор рецептов — моделей, методик и шаблонов —, которые позволяют команде быстро создавать кодовые базы, соответствующие этим принципам и, как следствие, лёгкие в поддержке.
Подробности на сайте Эргономичного подхода
В Эргономичном подходе есть что-то уникальное?
Да. Идея представления системы как модели её эффектов в виде диаграммы эффектов и методика проектирования на базе этой модели.
"Слова дёшевы, покажи мне код!"
Trainer Advisor — некоммерческий, но реальный (~17K строк Котлин кода, 15 таблиц, 2 настоящих пользователя, горки костылей, "компромиссных решений" и исторических наслоений) проект с открытым исходным кодом, разрабатываемый по Эргономичному подходу. В этот проект можно поконтрибьютить и на своём опыте прочувствовать работу с эргономичной кодовой базой.
Project Mariotte — минимальный демонстрационный пример кодовой базы, написанной по Эргономичному подходу, на примере операции бронирования номера в отеле
Есть что посмотреть или послушать?
Да, все мои публичные выступления собраны на одной странице
А почитать, кроме канала?
Да, в блоге
В блоге и канале есть подборки:
- Кейсы (в блоге, в канале #case@ergonomic_code)
- Примеры кода (в блоге)
- Эргономичный подход (в блоге, в канале #ergo_approach@ergonomic_code)
- Эргономичное тестирование (в блоге, в канале #ergo_testing@ergonomic_code)
- Функциональная архитектура (в блоге, в канале #functional_architecture@ergonomic_code)
- Эргономиный персистанс (в блоге, в канале #ergo_persistance@ergonomic_code)
- Что ещё почитать (в блоге, в канале #books@ergonomic_code, #posts@ergonomic_code, #papers@ergonomic_code)
- Что ещё посмотреть (в блоге, в канале #talks@ergonomic_code)
А у меня вопрос!
Приходите в группу - там целому сообществу (более 100 крутых инженеров) можно задать любой вопрос по тематике канала - Эргономичный подход, классическая школа ТДД, ФА, ФП, в целом дизайн модели и системный дизайн
Добро пожаловать на канал "Эргономичный код" — канал о разработке поддерживаемых кодовых баз в общем и моём подходе к этой задаче — Эргономичном подходе.
Что такое Эргономичный подход?
По большому счёту это небольшой набор принципов, взятых в основном из классической школы TDD, функциональной архитектуры и DDD, и большой набор рецептов — моделей, методик и шаблонов —, которые позволяют команде быстро создавать кодовые базы, соответствующие этим принципам и, как следствие, лёгкие в поддержке.
Подробности на сайте Эргономичного подхода
В Эргономичном подходе есть что-то уникальное?
Да. Идея представления системы как модели её эффектов в виде диаграммы эффектов и методика проектирования на базе этой модели.
"Слова дёшевы, покажи мне код!"
Trainer Advisor — некоммерческий, но реальный (~17K строк Котлин кода, 15 таблиц, 2 настоящих пользователя, горки костылей, "компромиссных решений" и исторических наслоений) проект с открытым исходным кодом, разрабатываемый по Эргономичному подходу. В этот проект можно поконтрибьютить и на своём опыте прочувствовать работу с эргономичной кодовой базой.
Project Mariotte — минимальный демонстрационный пример кодовой базы, написанной по Эргономичному подходу, на примере операции бронирования номера в отеле
Есть что посмотреть или послушать?
Да, все мои публичные выступления собраны на одной странице
А почитать, кроме канала?
Да, в блоге
В блоге и канале есть подборки:
- Кейсы (в блоге, в канале #case@ergonomic_code)
- Примеры кода (в блоге)
- Эргономичный подход (в блоге, в канале #ergo_approach@ergonomic_code)
- Эргономичное тестирование (в блоге, в канале #ergo_testing@ergonomic_code)
- Функциональная архитектура (в блоге, в канале #functional_architecture@ergonomic_code)
- Эргономиный персистанс (в блоге, в канале #ergo_persistance@ergonomic_code)
- Что ещё почитать (в блоге, в канале #books@ergonomic_code, #posts@ergonomic_code, #papers@ergonomic_code)
- Что ещё посмотреть (в блоге, в канале #talks@ergonomic_code)
А у меня вопрос!
Приходите в группу - там целому сообществу (более 100 крутых инженеров) можно задать любой вопрос по тематике канала - Эргономичный подход, классическая школа ТДД, ФА, ФП, в целом дизайн модели и системный дизайн
Эргономичный подход
Способ быстро создавать кодовые базы, которые легко менять для поддержки новых требований
🔥6❤4👍3
Привет!
Добавил на вики пару заглушек паттернов тестирования:
1. Тестирование генерации xlsx-документов с помощью Apache POI
2. Используйте фейковый кодировщик паролей
#ergo_testing@ergonomic_code #ergowiki@ergonomic_code
Добавил на вики пару заглушек паттернов тестирования:
1. Тестирование генерации xlsx-документов с помощью Apache POI
2. Используйте фейковый кодировщик паролей
#ergo_testing@ergonomic_code #ergowiki@ergonomic_code
Эргономичный подход
Тестирование генерации xlsx-документов с помощью Apache POI (v0.0.0)
Тестирование кода генерации xlsx-документов является достаточно сложной задачей.
Верификация состояния XSSFWorkbook вручную будет очень громоздкой и сложной для чтения.
О существовании какого-то DSL-я, который бы позволял лаконичного и читаемо описывать корректные…
Верификация состояния XSSFWorkbook вручную будет очень громоздкой и сложной для чтения.
О существовании какого-то DSL-я, который бы позволял лаконичного и читаемо описывать корректные…
🔥5
Привет!
Мне тут на Хабре заминусили коммент про отказ от моков в пользу интеграционного тестирования.
В ответ на это я собрался мокистам ответить подборкой цитат классиков и экспертов по ТДД о моках и оказалось, что у меня её нет.
Теперь есть:)
Берите себе на вооружение, в своей борьбе за простое девелоперское счастье и здоровый ночной сон:)
#posts@ergonomic_code #whynomocks@ergonomic_code #ergo_testing@ergonomic_code
Мне тут на Хабре заминусили коммент про отказ от моков в пользу интеграционного тестирования.
В ответ на это я собрался мокистам ответить подборкой цитат классиков и экспертов по ТДД о моках и оказалось, что у меня её нет.
Теперь есть:)
Берите себе на вооружение, в своей борьбе за простое девелоперское счастье и здоровый ночной сон:)
#posts@ergonomic_code #whynomocks@ergonomic_code #ergo_testing@ergonomic_code
Алексей Жидков
Эксперты об интеграционном тестировании и моках - Алексей Жидков
https://azhidkov.pro/
1👍11🔥6❤4
Эргономичный код
Привет!
Баги, найденные командой QA это:
Баги, найденные командой QA это:
Понимаю, что на самом деле сильно зависит от, но хочу понять общее отношение к багам в сообществе - выберите вариант который вам по духу ближе, пожалуйста.
#ergo_testing@ergonomic_code
#ergo_testing@ergonomic_code