Здравствуйте, Pauel, Вы писали:
P>·>Разжевываю: P>·>"тесты как написано", тк "они ничего не тестируют" — позор. Не важно с моками они или нет. P>·>Использование моков или нет — "детали реализации". P>"деталь реализации" означает что разница в свойствах несущественна и инструменты взаимозаменяемы, т.к. эквивалентны
Да. Верно. Вместо "дёрнуть метод" — "вернуть данные, которые будут переданы методу".
P>Моки и сравнения вовзращаемого значения не эквивалентны. Это следует хотя бы из того факта, что их приходится использовать совместно. P>То есть, это инструменты которые решают разные классы задач — вместо "assert x = y" тестируем "унутре вызвали вон тот метод с такими параметрами"
"verify(mock).x(y)"
P>Собственно, уже 20 лет как известно, что особенностью тестов на моках является их хрупкость, т.к. привязываемся буквально к "как написано"
Это твои заморочки.
P>·>Ещё раз повторюсь. Моки — инструмент. Если ты молотком пользоваться не умеешь и постоянно попадаешь по пальцам, то правильным решением будет научиться пользоваться молотком, а не продолжать закручивать гвозди отвёрткой. P>Есть два подхода к покрытию — на моках, и классический. У каждого есть и достоинства, и недостатки. P>А вы вместо обсуждения конкретных свойств каждого подхода пытаетесь переходить на личности и обсуждать мою квалификацию.
Я не понимаю какие проблемы у тебя с моками. А ты хранишь это в секрете. Только общие слова-отмазы "всем давно известно".
P>>>Не вся — моки могут добавлять то чего в природе нет, не водится, или выворачивать наизнанку. Соответствие моков реальному поведению системы всегда остаётся на совести разработчика, а следовательно человеческий фактор в его максимальном проявлении. P>·>В параметры тоже можно передавать то чего в природе нет. И что? P>Именно. Для классических тестов вы просто берете и покрываете входы по таблице истинности, покрывая именно ожидания пользователя. P>В моках у вас такого ориентира, как ожидания пользователя, нет и быть не может. P>Отсюда понятно, почему так трудно научить людей правильно пользоваться моками.
Единственное что не так с моками, это то, что это по сути подразумевается дизайн с side effects и non-pure функции. Это может быть плохо с т.з. теории и прочей чистой функциональщины, но на практике подавляющее количество кода всё равно с side effects. Может у тебя другой опыт и у тебя большинство проектов на хаскелле с монадами... но я почему-то сомневаюсь.
И ты тут телегу впереди лошади поставил. Ну да, у нас есть дизайн с side effects — что ж, либо давайте всё переписывать на хаскель, либо просто заюзаем моки для тестирования. У тебя есть третий вариант?
P>>>Зависимости. Моки отрезают зависимости во время тестирования. Что характерно, моки далеко это не единственный инструмент решения этой поблемы, и далеко не самый эффективный. P>·>Ты так и не показал как ты предлагаешь решать эту проблему, только заявил, что решается одной строчкой, но не показал как. Проигнорировал вопрос дважды: Напиши однострочный интеграционный тест для tryAcceptComposition. P>Однострочный интеграционный код для tryAcceptCompositio это просто вызов самого контроллера верхнего уровня.
Проигнорировал вопрос трижды: Напиши однострочный интеграционный тест для tryAcceptComposition. Код в студию!
P>>>Удвоение количества — это как раз про моки. При одинаковом покрытии кейсов мокам нужно больше кода. P>·>Я говорю конкретно о статье. Там кол-во кода удвоилось. Тестовое покрытие упало в несколько раз, зато Без Моков™. P>Потому что статья такая.
У тебя есть что-то лучше?
P>>>Так вы хотели, что бы вам в трех словах все тайны мироздания раскрыли? Все статьи такие, что там можно найти частный случай и заткнуть всё сразу. P>·>Я хотел, чтобы мне разъяснили нераскрытый вопрос в статье. P>Так уже. Это ж вы почемуто считаете что моки делают иерархию плоской, и аргументов не приводите.
Где я так считаю? Моки ничего сами не делают. Это инструмент тестирования.
P>·>Ясен пень, можно хоть на brainfuck писать, без этого вашего ООП. Но чем модель ближе — тем лучше. ООП как раз направлено на моделирование бизнес-требований как можно более похожим образом — именованная сущность там — именованная сущность здесь. Набор переменных это круто, конечно, но обычно только как практическое обоснование для жоп-секьюрити. P>Это принцип direct mapping, к ооп он имеет опосредованное отношение. Как вы будете сами сущности моделировать — дело десятое. Городить классы сущностей — нужно обоснование
Ок. Могу согласится, что это дело вкуса. Не так важно класс это или лямбда. Суть моего вопроса по статье — как же писать тесты, чтобы не оставалось непокрытого кода.
P>>>Проблема с самой статье P>>>1. в ооп стоит делать так, как автор показывает для фп варианта — больше контроля, меньше моков, больше юнит-тестов P>·>И кода стало больше, и бОльшая часть нетривиального кода не протестирована. P>Какой именно код не протестирован?
функция tryAcceptComposition. Ты обещал привести однострочный тест, но до сих пор не смог.
P>>>Это правило для работы с глубокоми иерахиями чего угодно — глубокую запутанную превращаем в плоскую одноуровневую. методы становятся длиннее, но зависимостями управлять легче тк иерархия неглубокая. P>·>Ну так внедрение зависимостей DI+CI это и есть плоская иерархия. В конструкторе все зависимости, методы — целевая бизнес-логика. В статье это и было показано, что такой подход эквивалентен частичному применению функций — код под капотом идентичный получается. P>Вам для моков нужно реализовывать в т.ч. неявные зависимости. Если вы делаете моками плоску структуру, получаются тесты "проверим что вызвали вон тот метод" т.е. "как написано"
Это называется whitebox тестирование. Причём тут моки?
P>А если мокаете клиент БД или саму бд, то вам надо под тест сконструировать пол-приложения.
Не очень понял что именно ты имеешь в виду. Вот мы тут вроде статью обсуждаем, там есть код, вот покажи на том коде что не так и как сделать так.
P>·>Ещё раз повторюсь — мок это лишь способ передачи данных внуть метода. В твоём случае ровно то же придётся делать, но передавать через параметры, а не через мок, вот и вся разница. P>Мок это тесты конкретного протокола взаимодействия, посредством контроля вызова методов. Отсюда ясно, что внятного оринтира нет — только то, как написано P>С обычными тестами вы закладываетесь на ожидания пользователя, и это достаточно осязаемый результат
А конкретно? С примерами кода. Как эти ожидания выражаются? Почему "вернуть X" — ты называешь "ожидание пользователя", а "вызвать x()" — "протокол взаимодействия"? И что всё эти термины значат? В чём принципиальная разница?
P>·>Слова Responsibility и Actor — это из словаря FRD. Т.е. именно эта терминология используется бизнесом для общения с девами. P>Успокойтесь. Добавлять классы на основании разговора на митинге — дело так себе. Актор может вообще оказаться целой подсистемой, а может и наколеночным воркером, или даже лямда-функцией
Ок. Каким образом ты делаешь соответствие термина в FRD с куском кода?
P>·>Аннотации именно так и работают. P>Вероятно, это вы их так пишете. У меня с аннотациями никаких глобальных переменных нет, и неявного внедрения зависимостей тоже нет. P>У вас видение из 90х или 00х, когда аннотациями лепили абы что.
А что сейчас? Сделай show&tell, или хотя бы ссылку на.
P>>>·>Ужас. annotation-driven development. Прям Spring, AOP, ejb, 00-е, application container, framework, middleware. Закопай обратно. P>>>Это то куда идут по большому счету все платформы. P>·>Когда отдают на аутсорс в индию, да. Именно такое рассуждение я как-то слышал "у нас требование покрытия тестами >90%. Аннотации в покрытии не участвуют. Давайте программировать на аннотациях". P>Я ж говорю — у вас 90е в голове бумкают. P>Ровно наоборот — аннотации в покрытии учавствуют, просто обязаны.
Покажи мне coverage report, где непокрытые аннотации красненьким подсвечены.
P>Прикрутили метаданные — есть тест на это. Используются ли эти метаданные — тоже есть тест.
Покажи как выглядит тест на то, что аннотация повешена корректно.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай