Size: a a a

Software Design/Architecture/Zen

2021 May 26

В

Виктор in Software Design/Architecture/Zen
понял, пасиб
источник

SP

Sergey Protko in Software Design/Architecture/Zen
но идеи хорошие воровать у него можно
источник

V

Viktor in Software Design/Architecture/Zen
благодарю, буду ждать обновлений
источник

SP

Sergey Protko in Software Design/Architecture/Zen
https://simpleprogrammer.com/back-to-basics-why-unit-testing-is-hard/ - вот еще. Там примеры конечно надуманные сильно, больше to make a point так скажем. Но от этого сама идея с "уровнями сложности тестов" не девается никуда
источник

SP

Sergey Protko in Software Design/Architecture/Zen
в частности почему так сложно когда появляются зависимости. Я это пока объясняю тем что мы эти все вещи не разделяем и потому не пытаемся искать подходящие практики для нужной ситуации. Все хотят простой алгоритм на все случаи жизни
источник

АГ

Алексей Гевондян... in Software Design/Architecture/Zen
с моками очень много возни всегда, да
источник

SP

Sergey Protko in Software Design/Architecture/Zen
не очень если знаешь что делаешь
источник

SP

Sergey Protko in Software Design/Architecture/Zen
и если понимаешь разницу между фэйками, стабами, моками, спаями, и прочими дамми
источник

SP

Sergey Protko in Software Design/Architecture/Zen
если с моками много возьни то значит ты не понимаешь как зависимости в твоей системе появляются обычно...
источник

SP

Sergey Protko in Software Design/Architecture/Zen
юнит тесты это все ж про внутреннее качество, дизайн... Они призваны показать тебе границы модулей и проектировать их с точки зрения "тех кто будет твой модуль юзать"
источник

В

Виктор in Software Design/Architecture/Zen
а есть публичные примеры на гитхабе, где как тебе кажется это показетльно сделано?
источник

SP

Sergey Protko in Software Design/Architecture/Zen
не, я в целом не искал специально, но в целом на гитхабе редко хорошие примеры чего-либо есть. Реальность такова что "красиво только в книжках, как путевая звезда которая недостижима но стремиться стоит". А в реальности есть return of investment который чаще всего вызывает компромисы
источник

SP

Sergey Protko in Software Design/Architecture/Zen
тесты не цель, это средство. Если тесты позволяют тебе уверенно вносить изменения в систему, если ты можешь запилить фичу и выкатить ее в прод и все quality gates автоматизированы - то это то ради чего это все и нужно. Помимо тестов есть другие практики. Есть еще SRE практики вроде error budget - мол мы можем забить на качество пока проблем нет :)
источник

АГ

Алексей Гевондян... in Software Design/Architecture/Zen
стабы мне нравятся больше чем моки, но писать какой-то код чисто ради тестов, как по мне это вообще такой антипаттерн. сюда же интерфейсы с единственной не тестовой реализацией ради тестов
источник

SP

Sergey Protko in Software Design/Architecture/Zen
что значит нравится не нравится?

если зависимость возвращает результат какой-то от которых зависит работа тестируемого кода - стабы. Если зависимость делает сайд эффект (void, ничего не возвращает) - то моки.
источник

SP

Sergey Protko in Software Design/Architecture/Zen
вместо стабов для "воспитания себя" можно делать фэйки. С одной простой мотивацией - заставить себя реализовать весь контракт а не только "кусочек который тестируемый код юзает". Многие этим болеют и это то из-за чего тесты хрупкими становятся.
источник

SP

Sergey Protko in Software Design/Architecture/Zen
ну и да, SOLID-ы хуелиды - зависимости с 50-ю методами в интерфейсах, неудобные контракты... все это делает тесты сложнее. Не потому что тесты сложно а потому что тесты это клиентский код - просто все проблемы вылазят более явно.
источник

V

Vladimir Ponomarev in Software Design/Architecture/Zen
Спасибо большое за пояснения. Еще несколько вопросов касательно тестирования:
- В юнит-тестах мы проверяем как работает контракт данного класса/чего-то там, и при этом используем заглушки/стабы для имитации зависимостей этого класса. Стабы должны реализовывать соотв. контракты/интерфейсы. И нам нужно столько вариантов стабов чтобы покрыть все ветки логики внутри тестируемого класса. Правильно ли все это?

- Что, если некоторый метод тестируемого класса делает какой-то сайд-эффект и по сути не требуется что-то возвращать из этого метода? Как тестить в таком случае? Нормально ли мокать методы в стабах зависимостей и потом проверять что они были вызваны как надо? Или это признак криво спроектированного класса и нужно думать как это все переделать?

- Если мы делаем стабы контрактов зависимостей, это вроде как выглядит норм, но как быть в языках где нет поддержки контрактов/интерфейсов (например ES5/ES6), ведь если случайно (или не очень) поменять один из методов являющихся частью контракта у самого класса зависимости, то тесты могут оставаться зелеными, т.к. у нас стаб это нечто отдельное и нам нужно вручную искать где предыдущий вариант этого метода использовался и править все руками. Или есть что-то что может помочь с этим справиться?
источник

SP

Sergey Protko in Software Design/Architecture/Zen
- по сути да. Потому и говорю что с TDD флоу несколько отличается так как ты контракт зависимостей проектируешь под нужды тестируемого кода, а не пытаешься "привязать уже существующий контракт даже если он не совсем подходит". ISP из SOLID про это. И да, по сути зависимость прекондишен какой-то задает. И тебе надо описать ситуации на которые завязана логика.

Тут можно "схитрить". я обычно делаю так. Например есть некая зависимость которая получает айдишку и должна вернуть результат. Я могу в целом подменить эту зависимость на простую мэпу где ключ - айдишка под нужный прекондишен и результат. В разных тест кейсах будут разные айдишки. Причем я могу для каждой айдишки задать константу например с понятным именем прекондишена. Это хорошо работает и с фэйками (одна реализация на все тест кейсы выходит) и с мок фреймворками (в сэтапе теста все настраиваю).

- моки: если метод ничего не возвращает и нам надо проверить только сайд эффект - для этого моки собственно и нужны (и spy еще есть такая штука). По хорошему такой сайд эффект должен быть изолирован... ну то есть достаточно редко нужны и стабы и моки в одном интерфейсе - не оч удобный интерейс выходит. Тут как бы вопрос восприятия есть ли для тебя разница записываем ли мы чет в массив и ассертим или просто ассертим что метод был вызван с нужными нам аргументами. Нужно ли нам валидировать аргументы или достаточно убедиться что взаимодействие произошло и т.д.

Если есть возможность обойтись без моков (без ассертов вызовов) - лучше так. Оч часто вижу как разработчики берут какой-нибудь settings.get(key) и ассертят что должно вызываться.  не надо так - лучше в стабе прописать ситуацию что будет если передать ключ о котором мы ничего не знаем. Стабы должны полностью имплементить контракт зависимостей. Потому удобно если зависимость с одним и тем же контрактом нужна в куче тестов делать фэйк/in-memory реализацию. Если следовать ISP из SOLID то таких будет мало.

В JS у тебя есть модули, соответственно есть так же публичные приватные части. Ты можешь подменять элементы модуля на те же стабы, моки, фэйки... Мне в целом нравится как это реализовано в Jest и я его юзаю там (+ мне оч нравятся там ассерты, оч удобный тул как по мне).  Контракты ж всеравно есть, суть в целом та же. Разница в восприятии (модуль/класс).
источник

SP

Sergey Protko in Software Design/Architecture/Zen
у Jest еще есть manual mocks которые позволяют делать "общие заглушки". Примерно то о чем я писал выше про общие фэйки которые много где надо юзать.
источник