Форум
Архитектура программного обеспечения
Тема
Как правильно задавать вопросы
B
I
abc
U
X
3
X
3
H1
H2
H3
H4
H5
H6
Asm
C/C++
C#
Erlang
Haskell
IDL
Java
Lisp
MSIL
Nemerle
ObjC
OCaml
Pascal
Perl
PHP
Prolog
Python
Ruby
Rust
SQL
VB
Здравствуйте, ·, Вы писали: ·>Здравствуйте, Pauel, Вы писали: P>>>>Моки изначально предназначались для тестов вида "вызываем вон то, вон так, в такой последовательности" P>>·>Может быть. Неясно какое это имеет значение сейчас, так исторические курьёзны. Даже если посмотреть на историю библиотек для тестов - за много лет много чего менялось и переделывалось. P>>И сейчас это основной кейс для моков. ·>Я не знаю где это основной кейс. Можешь посмотреть туториалы по тому же mockito, там такого треша нет. P>>Вы и сами тащите "надо проверить old и new", и другого варианта не видите, как будто его нет. Можно же и дизайн поменять, что бы юнитами такое проверять. Но нет - вы топите за моки. ·>Есть, конечно, но другие варианты хуже. Больше писать кода и сложнее тестировать. P>>>>У вас - охотно верю. P>>·>Потому что у нас не хелловорды, а не как у вас, да? P>>Потому, что вы используете дизайн, который плодит лишнее. Я вам на примере дата-время показал, как можно иначе, но вам любой пример не в вашу пользу надо забраковать. ·>По факту пока что кода лишнего больше у тебя. Притом "вот фаулер написал моки - плохо, давайте накрутим слоёв в прод коде!". P>>>>Я вам пример приводил, про время, вам он ожидаемо не понравился - язык не тот P>>·>Я не понял к чему ты скачешь с одного на другое. Обсуждали статью и MaitreD, потом crypto api, теперь вот ещё time api зачем-то... P>>Со статьё давно всё ясно. crypto api и time это пример, которые показывают, за счет можно отказаться от моков, и что будет, если этого не делать. ·>Ни для crypto api, ни для time моки не нужны обычно не потому что "дизайн", а потому что они быстрые, детерминированные, с нулём внешних зависимостей. P>>>>В данном случае мне не надо переживать за поломаные тесты, если понадобится другой алгоритм, другая либа, итд. P>>>>Вот понадобился не hmac а что другое - в файлике samples поменял десяток значений, и всё P>>·>Почему десяток? У тебя только десяток операций в api? P>>Это у вас на моках упадут все тесты всех операций апи. О том и речь. А на обычных юнит-тестах вы подкидываете новый набор значений, и всё путём. ·>Почему десяток? У тебя только десяток операций в api? Откуда взялся десяток? P>>>>А ваша альтернатива этому - еще и тесты перебулшитить. P>>·>Один, скорее всего. Ибо одного теста достаточно чтобы зафиксировать логику вычисления hmac. В остальных тестах достаточно ассертить его наличие, но не конкретный формат. P>>"достаточно ассертить его наличие" - вот вам и привязка к "как написано" ·>Не понял. Наличие hmac - это ожидание, бизнес-требование. P>>Ага, тесты "как написано" :facepalm: Вам придется написать много больше, чем один тест - как минимум, пространство входов более-менее покрыть. Моками вы вспотеете это покрывать. ·>Я тебе показывал как надо моками покрывать. P>>>>Ну да, этож только у вас сложные системы. P>>·>Ну да, сам же сказал, что у тебя всё помещается в один файлик. Или он гиговый? P>>Вы там в телепатию заигрались? Что именно по вашему помещается в один файлик? Вся система, все тесты, вся система с тестами? P>>Вы чего то недопоняли, но вместо уточнения начинаете валять дурака? ·>А толку уточнять. Я задал вопрос чего десяток - ответа так и не последовало. P>>·>Какой негатив? Вроде говорили об одном, теперь чего-то новое. P>>·>Вообще неясно причём тут time api и причём тут моки и тестирование вообще. P>>time api это пример дизайна, как можно уйти от комбинаторного взрыва. ·>Это не "дизайн". Это если ЯП умеет в duck typing и сооружать типы на ходу. Впрочем, тут явно фича применена не по месту. P>>>>Успокойтесь - это все статически контролируется, только в вашу джаву такие фичи еще не завезли. P>>·>Спасибо, но сводить всё к массиву из 7 чиселок - это фигня полная и издевательство. Даже такое [tt]DateTimeOffset.from({...time.toFields, ...date.toFields(), offset: serverOffset});[/tt] - и всё поехало. И где наносекуды, интересно? P>>Где вы видите массив? Это объект, статически типизированый, наносекунды будут в time.toFields как fractionalSeconds. Вам телепатия еще не надоела? ·>Ужас. Закопайте. P>>·>Конструкторы удобнее и надёжнее с нужными типами, [url=https://docs.oracle.com/javase/8/docs/api/java/time/OffsetDateTime.html#of-java.time.LocalDate-java.time.LocalTime-java.time.ZoneOffset-]например[/url], [tt]OffsetDateTime.of(date, time, offset)[/tt], это хотя бы читабельно, и если что-то не так, не компиляется P>>Принципиальное отличе [tt]of[/tt] вместо [tt]from[/tt] :facepalm: ·>Принципиальное отличие что тут три разных типа Date, Time и Offset - и их никак не перепутать. P>>>>Вы уже показали - перебулшитить все тесты, когда можно ограничиться десятком строчек на весь проект. P>>·>Это твои фантазии. P>>Вы сами пишите, что тестировать надо "как написано", это следует из того, как вы предлагаете решать задачу с hmac. Таких же задач будет не одна на проект, а целая куча. Вот и будут тесты "проверить что делает" ·>Я предложил как решают задачу взаимодействия с неким абстрактным сложным API в тестах с моками (стабами?). То что это crypto - к сути дела не относится, я это сразу заявил в ответе на твой пример, перечитай. Так что это твои фантазии. P>>>>Ну да - для вас перебулшитить тесты проблемой не является :facepalm: Еще и настаиваете, что так и надо. P>>·>Я настаиваю, что так не надо. P>>Если не надо, то должен быть другой подход к тестированию. А вы выбираете тесты на моках "проверим что вызывается hmac с нужными параметрами" ·>У меня в примере не было "проверим что вызывается hmac с нужными параметрами". Это было у тебя, и я сказал, что так не надо. P>>>>Проходит же. Вот я и интересуюсь, кто настрочил горы непотребства :-) P>>·>Вчерашние студенты? P>>Да не похоже. ·>Ок, пусть сорокалетние+ джуниоры. P>>>>Эта разновидность тестов нужна и вам. P>>·>Нужны, но не для проверки каждой строчки кода, что параметры вызова не перепутаны. А только для тестирования интеграции. P>>АПИ и есть та самая интеграция. ·>Нет. P>>>>Продукт, система, приложение, апи, компонент, модуль. Для теста именно кода у нас другие инструменты - код-ревью, линт, дизайн-ревью, статические анализаторы, итд. P>>·>Я сказал "Они отменяют необходимость написания тучи этих самых xxxComposition, нет кода — нечего тестировать". Ты прикопаться решил к слову код? Ок, пусть будет не код, а модуль-компонент. P>>·>"Моки отменяют необходимость написания тучи этих самых xxxComposition, нет такого компонента|модуля — нечего тестировать." Так яснее? P>>Не отменяют. Когда вы укрупняете компонент, то тестировать его сложнее. Или ваше покрытие будет решетом, или вам придется понаписывать много моков вида "это вызывает то", которые сломаются даже при минорных изменения компоненты ·>Суть в том, что компонент содержит несколько частей функциональности и весь компонент покрывается со всей его функциональностью, с моками (стабами?) зависимостей. После этого достаточно одного интеграционного теста, что несколько компонент соединились вместе и взаимодействуют хотя бы по одной части функциональности. Условно говоря, если в классе 20 методов и все 20 протестированы сотней юнит-тестов, то для тестирования интеграции обычно достаточно одного и-теста. В качестве аналогии - когда ты вставляешь CPU в материнку - тебе достаточно по сути smoke test, а не прогонять те миллионы тестов, которые были сделаны на фабрике для каждого кристалла и конденсатора. ·>У тебя же будет дополнительных xxxComposition на каждый метод в прод-коде и это надо будет всё как-то тестииовать в полном сборе. P>>>>Можно. И это делается без моков. Если мы заложимся на значение или состояние, то получим куда больше гарантий. P>>·>Без моков ты предложил только полный запуск всей аппликухи, в лучшем случае с тестовой субд. Kafka/amps/lbm/solace/tibco/etc, кстати, тоже тестовую будешь пускать? Или как? P>>Вы додумываете. Это в вашем понадобился бы запуск всей апликухи. У меня же апликуха запускается только ради e2e тестов. P>>Кафка - это обычный эвент, как вариант, можно обойтись и простым юнитом, убедиться что функция возвращает объект-эвент. P>>Если у вас такой роскоши нет - добавьте мок ровно на нотификацию, а не на кафку. ·>Так вызов метода - это и есть по сути эвент. По крайней мере, изоморфное понятие. P>>>>В функции средний девелопер может понаделывать ошибок куда больше, чем перепутать old и new. P>>·>Я в этом и до среднего не дотягиваю, дохрена таких ошибок делаю, но вся эта фигня на раз ловится тестами, c моками (стабами), да. P>>Если вы написали тест на old и new, то конечно же словится. Только откуда следует, что это единственные проблемы? P>>Проблем может быть сколько угодно, именно конечный результат говорит что правильно а что нет ·>Не знаю как у тебя, но у меня большинство ошибок именно логике в реалзиации методов, когда я тупо ошибаюсь в +1 вместо -1, from/to и т.п. P>>>>Именно! А потому нам все контроллеры нужно тестировать в апи тестах - тем самым мы исключаем добрый десяток классов проблем. P>>·>И эти тесты дадут тебе гарантию? P>>Разумеется, мы ради этого и пишем тесты. Не только что бы убедиться, что работает здесь и сейчас, но что бы можно было перепроверить это в т.ч. на живом окружении. P>>После билда работает, после деплоя - нет, опаньки! ·>У меня такое редко бывает. Неделю мучаюсь, вылизываю corner cases, потом деплою и оно тупо работает. Ну или сразу грохается при запуске, т.к. новый парам забыл в конфиге определить и лечится за минуту. P>>Впрочем, в прошлом году вы рассказывали, что деплой трогать низя - он у вас хрупкий, не дай бог повалится от лишнего запроса. ·>Это ты фантазируешь. Не "повалится", а произойдёт реальная сделка. P>>·>Жуть. Ну ладно. Т.е. тут мы тестируем репозиторий и ассертим текст sql :facepalm: P>>Здесь мы тестируем построение запроса ·>Ассерт-то в чём? Что текст запроса 'select * from users where id=?'? У тебя в тесте именно текст забит или что? P>>·>Как проверить, что текст запроса хотя бы синтаксически корректен? P>>Для этого нам всё равно придется выполнить его на реальной бд. Расскажите, как вы решите задачу вашими моками. ·>Я уже рассказывал. Интеграционным тестом repo+db. Текстов запроса в тестах нет, и быть не должно. Как-то так: ·>[java] ·>var testSubject = new MyRepo("connectionString");// по возможности in-mem dbms, но может быть и реальная ·>var id = 42; ·>testSubject.save(new User(id, "Vasya"))); ·>var actual = testSubject.getUser(id); ·>assert actual.getName().equals("Vasya"); ·>[/java] >>> И что он при выполнении выдаст то, что ожидается? P>>А здесь как вы моками обойдетесь? ·>Тут и не надо. Здесь же интеграция с субд тестируется. Моки (стабы?) будут дальше - в бл, в контроллере, етс. >>> И как ты собрался тут подменять субд? Ты обещал, что теперь эту хрень можно отдать любой db и оно выдаст одинаковый результат? Даже если эта субд это oracle или cassandra? Да там синтаксис банально другой. P>>А разве я говорил, что бд можно менять любую на любую? Построение запросов мы можем тестировать для тех бд, которые поддерживаются нами. ·>У тебя был такой код: ·>[code] ·>const getUser = repository.getUser(id); ·>const oldUser = db.execute(getUser); ·>[/code] ·>Этот код [i]выглядит[/i] так, что getUser выдаваемый из репы не зависит от db (и как ты заявил обещано в clean) и repo покрывается тестами независимо. Но по сути всё то же самое. Просто зависимость стала неявной. "генерим любой результат, но только такой, который где-то как-то будет использоваться в db.execute и мы должны знать где и как". Иными словами, repo может генерить только такие результаты, которые можно использовать далее, пишем репу, но должны всё знать о db слое. И вот это никак не тестируется без запуска всего кода контроллера в котором живёт этот код. А чтобы запустить контроллер - надо обеспечить ему все зависимости, т.е. по сути запустить всё приложение. ·>В моём коде выше с [tt]MyRepo("connectionString")[/tt] - мы тестируем только интеграцию двух частей repo + dbms. И ничего больше в таких тестах поднимать не надо. P>>>>Сами трансформации тестируются отдельно, обычными юнитами, например [tt]expect(fn1(user)).to.eq(user.id);[/tt] P>>·>Так ведь надо трансформировать не некий user, а конкретно ResultSet возвращённый из "select *". Что колоночки в select местами не перепутаны, как минимум. P>>Что вас смущает? трансформация результата принимает ResultSet и возвращает вам нужный объект. ·>Так ведь надо не абы какой ResultSet, а именно тот, который реально возвращается из "select *". У тебя же эти по настоящему связанные сущности тестируются независимо. Что абсолютно бесполезно. P>>·>Ещё это всё "красиво" только на твоих хоумпейдж проектах. В реальном коде эти sql будут сотни строк с многоэтажными джойнами и подзапросами, и такие "тесты" станут даже немножечко вредить. P>>Расскажите, как вы это моками решите ·>Моки (стабы) - это для отпиливания зависимостей в тестах. Репу тестируем медленными и-тестами с более-менее реальной субд, а дальше моки (стабы) для быстрого тестирования всего остального. P>>>>Вы все думаете в единицах старого дизайна, когда БЛ прибита гвоздями к бд. P>>·>Не к бд прибита. БЛ прибивается к репе. P>>Это одно и то же, и в этом проблема. Я ж вам говорю, как можно иначе - но вы упорно видите только вариант из 90х-00х ·>Ты показал это "иначе", но там всё ещё хуже прибито. Вплоть до побуквенного сравнения текста sql. P>>В новом подходе не надо БЛ прибивать ни к какой репе, ни к бд, ни к стораджу, ни к кафе, ни к внешним сервисам ·>Ага-ага. P>>>>Шота я этого за 4 года не заметил :xz: P>>·>Может у тебя проекты написанные вайтишниками после курса ML, я не знаю. Но у тебя есть целый гитхаб, погляди насколько часто и для чего Object используют. P>>Я как раз с гитхаба и брал, если что. ·>Ссылку давай. P>>>>Юзеру так и скажете - мы не можем вернуть ваши деньги, потому что у нас в конфигурации возвраты отключены. P>>·>Для этого и есть L1 support - "проверьте, что ваш компьютер включен". P>>Я именно это сказал - L1 support так и скажет юзеру, "в конфиге отключено, значит неположено" P>>Что бы такого не случалось, в тестах должен быть сценарий, который включает возврат. И так для всех апи которые вы выставляете. ·>Не понял, если возврат отключен, то и тест должен тестировать, что возврат отключен. P>>>>Добавили, посмотрели дифом, вкомитали. Вам же не надо сразу всё обрабатывать. P>>·>А в дифе 10к строчек отличаются. И как это смотреть? Аудит же пишется для каждой операции, т.е. каждого теста, да ещё и не по разу. P>>А почему 10к а не 10к миллионов? ·>Примерное типичное кол-во сценариев реальной системе большего, чем хоумпейдж масштаба. P>>>>Если апи возвращает то, что надо, это значит что у вас связка конфиг-di-sl-рантайм-переменные-итд склеено правильно. P>>·>И это ты предлагаешь гонять на каждый "updateUser(newUser, oldUser)"? Спасибо, не надо нам такого щастя. P>>Да, я в курсе, у вас есть L1 суппорт, который скажет клиенту, что возвраты не положены. P>>Это не шутка - мне так L1 однажды залепил P>>Неделя бодания и перекинули проблему наверх, только когда я сослался на федеральный закон P>>Признавайтесь, ваша идея? ·>Только не пытайся доказать, что это у них "не работало", потому что тесты у них неправильные. Уж поверь, у них всё работало как надо (им). P>>>>Можно. Это старый подход. P>>·>Ты говоришь как будто это что-то плохое. Это разумный подход. Делить не по тому, что сейчас у фаулеров в моде, а по конкретному осязаемому критерию, т.к. это напрямую выражается во времени запуска и требуемых ресурсов для тестирования. P>>В данном случае вам нужно писать больше кода в тестах, и они будут хрупкими. Другого вы с моками не получите. Потому и убирают зависимости из БЛ целиком, что бы легче было покрывать тестами ·>Но ведь не "убирают", а переносят. Что добавляет и количество прод-кода и число тестов. P>>>>Это новый подход, позволяет обходиться без моков-стабов итд и свести тестирование ключевых вещей к дешовым юнит-тестам P>>·>У тебя тривиальное updateUser(newUser, oldUser) не тестируется юнитами. Любая мелочёвка требует запуска всего, в лучшем случае с in-mem субд. P>>Ага, сидим да годами ждём результаты одного теста. Вам самому не смешно? ·>Думаю ваш хоум-пейдж за час тестируется, в лучшем случае. P>>·>С такими же гарантиями можно и просто метод дёргать. Аннотации это только от плохого дизайна. P>>Ну вот подергали вы метод. А потом вас попросили отразить всё такое в сваггере каком, что бы другим было понятно. Гы-гы. Ищите строчки в коде. P>>А с аннотациями взял да и отрендерил манифест. ·>Гы-гы. У тебя же, ты сам говорил, что попало где попало - и в переменных окружения, и в конфигах и где угодно эти "аннотации" висят. Сваггер у вас каждые 5 минут новый, да? P>>>>Вы же не проверяете, что джава выполняет циклы правильно? Так и здесь P>>·>Фреймворк-ориентед программинг? Нет, спасибо. P>>Это ж классика - отделяем логику, которая меняется часто, от той, которая меняется редко. По этому пути индустрия идет последние 50 лет ·>Ты любишь сложность на пустом месте, притом в прод-коде, я уже понял. Но это плохо. Фреймворк это совсем другая весовая категория. Для того что ты пишешь достаточно extract method refactoring, а не новая архитектура с фреймворками.
Теги:
Введите теги разделенные пробелами. Обрамляйте в кавычки словосочетания с пробелами внутри, например:
"Visual Studio" .NET
Имя, пароль:
Загрузить
Нравится наш сайт?
Помогите его развитию!
Отключить смайлики
Получать ответы по e-mail
Проверить правописание
Параметры проверки …