Здравствуйте, ·, Вы писали:
P>>>>Сейчас это называется плохо протестировать — вместо простых и дешовых юнит-тестов вам надо обмазываться моками, и писать хрупкие тесты вида "вызвали функцию репозитория"
P>>>>То есть, это тесты "как написано", тавтологические
P>>·>Технически то же самое.
P>>Тесты "как написано", технически не дают никаких гарантий — вызвал другой метод репозитория, результат тот же, а тесты сломались. Вот вам и "то же самое"
·>Это уже детали реализации — что именно тестируют тесты. Если я хочу тестировать факт вызова определённого метода, то тест и должен сломаться. Что именно покрывает тест — это должен решать программист. Моки к этому отношения не имеют вообще никакого.
Забавный плюрализм в одной голове — в одном треде вы клеймите позором "тесты как написано", тк "они ничего не тестируют", а здесь это уже "детали реализации"
Как вас понимать, какая версия вашего мнения считается более актуальной?
P>>Например, научить новичка внятно пользоваться моками да правильно покрывать тесты используя такой подход довольно трудно, на это уходят годы. А потому рано или поздно будете ловить последствия в проде.
·>Это всё риторика. Любые тесты искажают действительность, просто по определению. Моки — тут вообще не при чём.
Любые и все по разному, в разной степени. Моки по своей сути сильнее всего этому подвержены. Пол-приложения не работает при зеленых тестах — обычное дело с моками.
P>>Вы сейчас играете в слова. В одном случае вы получаете проблемы из за моков, а в другом случае просто тестируете ключевую функцию юнит-тестами без моков.
·>Моки это всего лишь механизм передачи данных от одного участка кода другому. Пюрешки могут использовать только передачу параметров и возвращаемое значение. Моки — дополнительно позволяют передавать инфу через вызовы методов. Вот и вся разница.
Не вся — моки могут добавлять то чего в природе нет, не водится, или выворачивать наизнанку. Соответствие моков реальному поведению системы всегда остаётся на совести разработчика, а следовательно человеческий фактор в его максимальном проявлении.
P>>Обмазываетесь моками — значит время на разработку тестов больше, тк тесты хрупкие.
·>Моки лишь дополнительный инструмент. Можно им всё сломать, а можно сделать красиво.
У вас моки стали какой то панацеей. Вас послушать так у моков одни преимущества, без каких либо недостатков.
P>>Моки это инструмент решения проблем, а не способ выражения намерений. А раз так, то нужно сперва решить проблему, тогда и отпадет необходимость применять этот инструмент.
·>Решения каких проблем?
Зависимости. Моки отрезают зависимости во время тестирования. Что характерно, моки далеко это не единственный инструмент решения этой поблемы, и далеко не самый эффективный.
А у вас он стал панацеей
P>>Эти вещи связаны исключительно конкретным пайплайном. А вот логически это разные вещи. Тестировать сам пайплайн удобнее интеграционными тестам — прогнал один, значит пайпалайн работает. А вот отдельные части пайплайна — дешовыми юнит-тестами, их можно настрочить тыщи, хоть генерируй по спеке, время на запуск все равно 0 секунд.
·>Я о чём и говорю. Шило на мыло меняешь, правда ценой удвоения количества кода.
Если есть выбор, моком или простым юнит-тестом, то юнит-тест всегда эффективнее. Удвоение количества — это как раз про моки. При одинаковом покрытии кейсов мокам нужно больше кода.
P>>А вот если вы обмазываетесь моками, то пишете тесты "как написано" и другого варианта у вас нет.
·>Варианта чего? Вынести пюрешку можно банальным extract method refactoring и покрыть отдельно — если это имеет хоть какую-то практическую пользу. Мой поинт в том, что в статье практической пользы делать закат вручную мне не удалось увидеть.
Так вы хотели, что бы вам в трех словах все тайны мироздания раскрыли? Все статьи такие, что там можно найти частный случай и заткнуть всё сразу.
P>>Именно! А вы предлагаете грязный ооп использовать на уровне методов технической реализации. Потому вам и нужны моки. ООП это парадигма для управления сложностью взаимодействия. ФП — для управления сложностью вычислений. Отсюда ясно, что нам надо и то, и другое — склеить взаимодействие с вычислениями. Создание — тупо вычисления, а вы сюда втискиваете зависимость на БД и вещаете что это хорошо.
·>Я предлагаю использовать ооп. На минутку — что требует бизнес? Реализацию сущности MaitreD.
Нет, не требует. Бизнесу до ваших сущностей никакого дела нет. А потому разработчик имеет право выбирать, нужна ли ему такая сущность, и как он её будет моделировать — объектами, классами, актерами итд итд итд Хоть набором переменных, абы это имело практическое обоснование
·>В статье на замену предложено вычленить локальное нутро реализации метода, вынести наружу, чтобы получилось вот это: int -> (DateTimeOffset -> Reservation list) -> (Reservation -> int) -> Reservation — это вообще чо??!.
Это описание конкретного пайплайна. В ооп подходе у вас будет примерно такая же штукенция. Покрасивее будет, т.к. именованая. Но принципиально всё сохранится. В том и то и бенефит.
Проблема с самой статье
1. в ооп стоит делать так, как автор показывает для фп варианта — больше контроля, меньше моков, больше юнит-тестов
2. если в фп задаться целью сделать как автор для ооп вариана — можно просто убиться
Это правило для работы с глубокоми иерахиями чего угодно — глубокую запутанную превращаем в плоскую одноуровневую. методы становятся длиннее, но зависимостями управлять легче тк иерархия неглубокая.
>>> Но замели сложность в ещё один tryAcceptComposition на 3 строки (притом довольно хитрый! со всякими магическими заклинаниями liftIO, $, return, flip, .), для которого теперь требуется писать ещё и интеграционный тест. Удвоили кол-во кода, усложнили тестирование... а в чём выгода — я ну никак понять не могу.
P>> Вы по прежнему думаете, что моки избавляют от интеграционных тестов. Ровно наоборот — сверх обычных юнитов вам надо понаписывать моки на все кейсы, и всё равно придется писать интеграционные тесты.
·>Зачем писать моки на все кейсы? Моки делаются не для кейсов, а для зависимостей. Тут одна зависимость — репозиторий — значит один мок. Неважно сколько кейсов.
Ваш мок должен поддерживать все эти кейсы, что очевидно. Думаете мок сам догадается, какие кейсы ему поддерживать?
·>Юнит-тестов нужно только два — успешная и неуспешная резервация. Интеграционный тест только один — что MaitreD успешно интегрируется со всеми своими зависимостями.
Юнит-тестов нужно гораздо больше — в зависимости от того, сколько у нас параметров, состояний итд.
P>>На основе коротких функций мы можем менять компоновку уже по ходу пьесы подстраиваясь под изменения треботваний, а не бетонировать код на все времена.
·>"зарезервировать столик" — это Responsibility выполняемое Actor-ом MaitreD. Это понятно бизнесу.
Бизнесу до этого никакого дела нет. MaitreD это абстракция уровня реализации.
·>Это не аудит, это просто лог для дебага. Аудит это требуемый аудиторами record-keeping процесс определённого формата с определёнными требованиями с целью контролировать business conduct — по тому как происходят различные бизнес-операции с т.з. legal compliance. С т.з. реального мира — тот дядька у входа в ресторан, например, обязан секретно уведомлять полицию если к нему пришёл клиент с признаками наркотического отравления.
·>Ты не отвлекайся. Код в статье рассматривай. Расскажи куда там воткнуть это всё в tryAcceptComposition или куда там получится. Я хочу рассмотреть пример когда у метода будет больше одной зависимости. А ты мне предлагаешь зависимости внедрять неявно через аннотации и глобальные переменные.
Это ваши фантазии. Я ничего не предлагаю внедрать неявно, тем более с глобальными переменными. Это вы с голосами в голове спорите.
P>>@useAudit(Schema.arrange, Schema.arranged)
P>>@useEvent(Schema.arranged)
P>>@validate(Schema.arrange)
P>>@presenter(Schema.arranged)
·>Ужас. annotation-driven development. Прям Spring, AOP, ejb, 00-е, application container, framework, middleware. Закопай обратно.
Это то куда идут по большому счету все платформы.