Форум
Архитектура программного обеспечения
Тема
Как правильно задавать вопросы
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>>·>Ок, пусть. Не вижу, в чём важность этой терминологии. Я использую название "мок", потому что библиотека называется mockito и создаются эти штуки функцией mock или аннотацией @Mock. Если тебе комфортнее стаб, пусть. Хоть горшком назови, только в печку не ставь. P>>Моки изначально предназначались для тестов вида "вызываем вон то, вон так, в такой последовательности" ·>Может быть. Неясно какое это имеет значение сейчас, так исторические курьёзны. Даже если посмотреть на историю библиотек для тестов - за много лет много чего менялось и переделывалось. P>>>>Ну так в джаве и пишут - перемножают сущности и радуются. P>>·>Причём тут перемножают? Это диктуется требованиями. Если в json тебе нужен b64, а аналогичном месте protobuf тебе нужен Bytes, то хоть на bf пиши, у тебя будут комбинации. P>>У вас - охотно верю. ·>Потому что у нас не хелловорды, а не как у вас, да? P>>Я вам пример приводил, про время, вам он ожидаемо не понравился - язык не тот ·>Я не понял к чему ты скачешь с одного на другое. Обсуждали статью и MaitreD, потом crypto api, теперь вот ещё time api зачем-то... P>>>>Я портировал довольно много кода с джавы в тайпскрипт, и охренел от тамошних привычек. P>>·>Портировал это значит, как минимум, ты по ходу удалял гору легаси кода, совместимость с устаревшим, етс. P>>С чего бы портирование стало означать удаление легаси ? ·>С того. Когда код существует хотя бы десяток лет - там наслоения чего попало, когда что-то делалось и переделывалось, много накапливается мусора "по историческим причинам". P>>>>Не нужны никакие "9 комбинаций" - нужно отделить создание и представление. P>>·>Так в изначальном дизайне crypto так и было - создаём hmac нужного алгоритма, потом выводим в нужном представлении. Ты почему-то упаковал это в одну функцию и назвал успехом. P>>В данном случае мне не надо переживать за поломаные тесты, если понадобится другой алгоритм, другая либа, итд. P>>Вот понадобился не hmac а что другое - в файлике samples поменял десяток значений, и всё ·>Почему десяток? У тебя только десяток операций в api? P>>А ваша альтернатива этому - еще и тесты перебулшитить. ·>Один, скорее всего. Ибо одного теста достаточно чтобы зафиксировать логику вычисления hmac. В остальных тестах достаточно ассертить его наличие, но не конкретный формат. P>>·>У кого "у нас"? Если бы никому не требовались разные виды токенов в разном представлении, то в библиотеке crypto был бы "makeToken" с ровно одним парамом. P>>·>Такое ощущение, что ты говоришь о дизайне какой-то домашней странички, а не о сложной системе. P>>Ну да, этож только у вас сложные системы. ·>Ну да, сам же сказал, что у тебя всё помещается в один файлик. Или он гиговый? P>>>>Количество может быть уменьшено за счет подхода к дизайну. P>>·>Я не понял, разговор был о crypto, теперь на какой-то time-api переключился. Я за твоим полётом мысли не успеваю. P>>У вас любой из примеров вызывает какой то негатив ·>Какой негатив? Вроде говорили об одном, теперь чего-то новое. ·>Вообще неясно причём тут time api и причём тут моки и тестирование вообще. P>>>>А операция конверсии в прикладном коде будет вот такой [tt]DateTimeOffset.from({...date.toFields(), ...time.toFields, offset: serverOffset});[/tt] P>>·>Это только на js годится такое писать. Со статической типизацией такое не прокатит. P>>Успокойтесь - это все статически контролируется, только в вашу джаву такие фичи еще не завезли. ·>Спасибо, но сводить всё к массиву из 7 чиселок - это фигня полная и издевательство. Даже такое [tt]DateTimeOffset.from({...time.toFields, ...date.toFields(), offset: serverOffset});[/tt] - и всё поехало. И где наносекуды, интересно? ·>Конструкторы удобнее и надёжнее с нужными типами, [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>>>>А если вы решили понасоздавать N! комбинаций - удачи, внятного покрытия вам не видеть, как своих ушей, хоть с моками, хоть без них. P>>·>Я вроде рассказал, как упрощать тестирование комбинаций. P>>Вы уже показали - перебулшитить все тесты, когда можно ограничиться десятком строчек на весь проект. ·>Это твои фантазии. P>>>>Читайте себя внимательно - вы регулярно утверждаете, что именно у меня проблемы с моками, что именно у меня квалификация под сомнением. P>>·>Так ты сам откровенно пишешь: "за 20 лет индустрия так и не осилила". Я сталкивался с другой индустрией, в которой с моками (или стабами?) проблем таких нет. P>>Ну да - для вас перебулшитить тесты проблемой не является :facepalm: Еще и настаиваете, что так и надо. ·>Я настаиваю, что так не надо. P>>>>Именно - так не надо, но именно так пишут и это типичный пример, к сожалению P>>·>Может в твоей индустрии. В java так не пишут, ну если только совсем вчерашние студенты, но PR такое не пройдёт. P>>Проходит же. Вот я и интересуюсь, кто настрочил горы непотребства :-) ·>Вчерашние студенты? P>>>>Интеграционные тесты это все выше уровня простых юнит тестов. Далеко не все интеграционные автоматически медленные. Условно, чистая функция вызывает десяток других чистых - опаньки, тест такой штуки будет интеграционным. Но нам это по барабану - они быстрые, можно обзапускаться хоть до посинения. P>>·>Ты куда-то мимо пошел. Не хочу вдаваться в подробности терминологии юнит-инт. Суть в том, что в твоём предложенном тесте появляется connectionString, значит "приходится плодить медленные тесты и тривиальные ошибки обнаруживать только после запуска всего приложения". P>>Эта разновидность тестов нужна и вам. ·>Нужны, но не для проверки каждой строчки кода, что параметры вызова не перепутаны. А только для тестирования интеграции. P>>>>Наоборот. Большое количество дешовых тестов, тысячи минимум, и десятки-сотни интеграционных, самых тяжелых тестов по одному на каждый сценарий приложения - десяток другой. P>>·>Какой тесто обнаружит ошибку в коде "repository.updateUser(newUser, oldUser)" и как? Вот это "выполним операцию и проверим, что состояние юзера соответствует ожиданиям"? Что должно быть поднято для прогона такого теста? P>>да вобщем то ничего, какая нибудь ин-мемори дб и инстанц контроллера или юз-кейса. ·>Ясно, закопайте. P>>·>Под интеграцией я понимал в данном случае твоё "curl -X POST". Это плохой тест, медленный, неуклюжий. Число таких тестов надо стараться минимизировать. P>>Такие тесты нужны в любом случае, моки-стабы от них не избавляют, это иллюзия. ·>Я знаю, что нужны, Я написал, что "[i]Число таких тестов надо стараться минимизировать[/i]". P>>>>В огороде бузина, а в киеве дядька. При чем здесь require ? framework as a detail и clean architecture это подходы к дизайну, архитектуре. P>>·>В том, что в твоём коде jest подменял код внутри глобального реестра require. P>>Я вам пример привел, как применяют моки. Обмокать можно что угодно, в т.ч. и в джаве-дотнете ·>Я не знаю кто так применяет, но так делать не надо. P>>>>Неверно - тестируется не код, а соответствие ожиданиям, требованиями. какой бы дизайн у вас ни был - все равно нужны тесты апи, сценариев итд. P>>·>Опять буквоедство какое-то. Что по-твоему тестируется на соответствие ожиданиям, требованиям? P>>Продукт, система, приложение, апи, компонент, модуль. Для теста именно кода у нас другие инструменты - код-ревью, линт, дизайн-ревью, статические анализаторы, итд. ·>Я сказал "Они отменяют необходимость написания тучи этих самых xxxComposition, нет кода — нечего тестировать". Ты прикопаться решил к слову код? Ок, пусть будет не код, а модуль-компонент. ·>"Моки отменяют необходимость написания тучи этих самых xxxComposition, нет такого компонента|модуля — нечего тестировать." Так яснее? P>>>>А вы тут сказки рассказыете, что это делать не надо P>>·>Суть в том, что тесты апи можно тестировать без реальной субд|кафки и т.п. И описывать ожидания, что updateUser сделан именно с (newUser, oldUser), а не наоборот. P>>Можно. И это делается без моков. Если мы заложимся на значение или состояние, то получим куда больше гарантий. ·>Без моков ты предложил только полный запуск всей аппликухи, в лучшем случае с тестовой субд. Kafka/amps/lbm/solace/tibco/etc, кстати, тоже тестовую будешь пускать? Или как? P>>В функции средний девелопер может понаделывать ошибок куда больше, чем перепутать old и new. ·>Я в этом и до среднего не дотягиваю, дохрена таких ошибок делаю, но вся эта фигня на раз ловится тестами, c моками (стабами), да. P>>>>Покажите как вы в репозиторий метод getAll передаете фильтры, сортировку итд P>>·>Не знаю, не припомню где у нас есть такое. Но наверное был бы какой-нибдуь value object, который передаёт необходимые настройки фильтров и сортировок. P>>Вот вы и встряли :-) Чем лучше изолируете, тем больше вам тестировать. Тут помогло бы использование какого dsl. В том же дотнете есть такое, и всё равно надо думать, что передать в репозиторий, быть в курсе, съест ли тамошний провайдер конкретную функцию или нет. ·>Пофиг. Я не знаю о чём ты говоришь и делаю wild guesses. P>>>>Именно - кто даст гарантию что с тем или иным конфигом, рантаймом, переменными окружения, тот самый метод контролера не начнет вдруг гарантировано валиться ? P>>·>Никто. P>>Именно! А потому нам все контроллеры нужно тестировать в апи тестах - тем самым мы исключаем добрый десяток классов проблем. ·>И эти тесты дадут тебе гарантию? P>>Что вас смущает? deep.eq проверит всё, что надо. query это не строка, объект с конкретной структурой, чтото навроде P>>[code] P>>{ P>> sql: 'select * from users where id=?', P>> params: [id], P>> transformations: { P>> in: [fn1], P>> out: [fn2] P>> } P>>} P>>[/code] ·>Жуть. Ну ладно. Т.е. тут мы тестируем репозиторий и ассертим текст sql :facepalm: ·>Как проверить, что текст запроса хотя бы синтаксически корректен? И что он при выполнении выдаст то, что ожидается? И как ты собрался тут подменять субд? Ты обещал, что теперь эту хрень можно отдать любой db и оно выдаст одинаковый результат? Даже если эта субд это oracle или cassandra? Да там синтаксис банально другой. P>>Сами трансформации тестируются отдельно, обычными юнитами, например [tt]expect(fn1(user)).to.eq(user.id);[/tt] ·>Так ведь надо трансформировать не некий user, а конкретно ResultSet возвращённый из "select *". Что колоночки в select местами не перепутаны, как минимум. ·>Ещё это всё "красиво" только на твоих хоумпейдж проектах. В реальном коде эти sql будут сотни строк с многоэтажными джойнами и подзапросами, и такие "тесты" станут даже немножечко вредить. P>>>>вот, вы начинате понимать, для чего нужны интеграционные :-) Здесь вам понадобится тест компонента с подклееной реальной бд. И без этого никак. P>>·>Т.е. та же ж, вид в профиль, но теперь большинство логики без реальной бд не протестировать. В случае с репо реальная бд нужна только для тестирования самого слоя взаимодействия с бд, а остальное может мокаться (стабиться?). Ты же предлагаешь всё приложение тестировать с реальной бд. P>>Вы все думаете в единицах старого дизайна, когда БЛ прибита гвоздями к бд. ·>Не к бд прибита. БЛ прибивается к репе. P>>>>Это типичный пример интеграция - вы соединяете выходы одного со входами другого. P>>·>Ну да. Но это не означает, что для этого необходимо тестировать только с реальной бд. P>>Нам нужна любая бд, что прогонять некоторые тесты, обычно небольшое количество. ·>Любая бд даёт любой результат. P>>>>Это в любом случае необходимо - у контролера всегда хрензнаетсколькилион зависимостей прямых и косвенных, и чтото да может пойти не так. P>>·>Для этого и объединяют толпу зависимостей в одну. Чтобы не N! было. P>>Объединяйте что угодно - а контролер все равно придется вызвать в АПИ тестах. ·>Не знаю что за апи тесты ты тут имеешь в виду, предполагаю, что это твой "curl". Если так, то достаточно позвать один метод для проверки интеграции всех компонент, а не для тестирования всей бизнес-логики апи. P>>>>А там где используют object, то отличий от js никакого нет P>>·>Ну обычно object стараются избегать использовать. P>>Шота я этого за 4 года не заметил :xz: ·>Может у тебя проекты написанные вайтишниками после курса ML, я не знаю. Но у тебя есть целый гитхаб, погляди насколько часто и для чего Object используют. P>>>>Иначе есть шанс что тот самый роут в нужный момент не сможет быть вызван, т.к. он просто задизаблен в конфиге P>>·>Не понял, ну раз задизаблен, значит и нельзя вызвать. Это является не ошибкой, а конфигурацией системы. Неясно что тут в принципе тестировать. P>>Юзеру так и скажете - мы не можем вернуть ваши деньги, потому что у нас в конфигурации возвраты отключены. ·>Для этого и есть L1 support - "проверьте, что ваш компьютер включен". P>>>>Вы там что, на каждый коммит всю систему переписываете? :wow: P>>·>Я описываю ситуацию - добавили новое общее поле в аудит - везде в этих твоих логах каждого теста - строчка аудита выглядит чуть по-другому. P>>Добавили, посмотрели дифом, вкомитали. Вам же не надо сразу всё обрабатывать. ·>А в дифе 10к строчек отличаются. И как это смотреть? Аудит же пишется для каждой операции, т.е. каждого теста, да ещё и не по разу. P>>>>Апи это именно про интеграцию - вызов контроллера в конкретном окружении, что есть в чистом виде интеграция, т.к. у контроллера всегда есть хрензнаетсколькилион зависимостей, прямых и косвенных. P>>·>Апи это про интерфейс системы. Интеграция тут причём? P>>Если апи возвращает то, что надо, это значит что у вас связка конфиг-di-sl-рантайм-переменные-итд склеено правильно. ·>И это ты предлагаешь гонять на каждый "updateUser(newUser, oldUser)"? Спасибо, не надо нам такого щастя. P>>>>Старый подход - контролер вызывает сервис БД который вызывает БЛ через репозиторий итд. Моками надо обрезать зависимости на БД у БЛ. P>>>>Т.е. БЛ это клиент к БД, по факту. P>>·>Моками (стабами?) обрезается БД и прочие внешние вещи от БЛ. Чтобы при тестировании БЛ можно было быстро тестировать логику кода, без всяких сетевых соединений и запуска всего приложения. P>>Можно. Это старый подход. ·>Ты говоришь как будто это что-то плохое. Это разумный подход. Делить не по тому, что сейчас у фаулеров в моде, а по конкретному осязаемому критерию, т.к. это напрямую выражается во времени запуска и требуемых ресурсов для тестирования. P>>·>Да пофиг. Эти слои можно жонглировать как сейчас модно. Это меняется каждый год. P>>Это новый подход, позволяет обходиться без моков-стабов итд и свести тестирование ключевых вещей к дешовым юнит-тестам ·>У тебя тривиальное updateUser(newUser, oldUser) не тестируется юнитами. Любая мелочёвка требует запуска всего, в лучшем случае с in-mem субд. P>>>>>>Кое что надо и в самом методе вызывать, без этого работать не будет. P>>>>·>Именно! И накой тогда аннотация нужна для этого? P>>>>Базовые гарантии. Некоторые из них можно выключить или доопределить конфигом итд. P>>·>Базовые гарантии чего? P>>Например, если вы аннотацией указываете что метод работает из под другого юзера, например Freemium, то базовая гарантия - вы будете получать Freemium юзера внутри этого метода. Ее можно модифицировать - отключить весь Freemium в конфиге приложения. Или навесить на Freemium юзера доп.свойства - свежегенеренное имя-емейл-баланс. ·>С такими же гарантиями можно и просто метод дёргать. Аннотации это только от плохого дизайна. P>>>>Разумеется, это интеграция - что аудит интегрирован с тем или иным стораджем. 1 тест. P>>·>"для [b]данных[/b] сценариев записываются [b]нужная[/b] инфа". Это где-то нужно валидировать, что для некой бизнес-операции в соответвтующих условиях записывается соответвтующий требованиям сообщение аудита. P>>В этом случае можно сделать аудит через тесты состояния. Прогоняем операцию, сравниваем что в аудите. Тесты вида "вызываем аудит с параметрам" - это тесты "как написано" ·>Не "вызываем аудит с параметрам", а "послано такое-то сообщение в аудит". P>>·>Как я понял скорее всего разница в том, что я обычно пишу на статике. Аннотации мешают тем, что их сложнее тестировать, контролировать типы. Приходится вместо простых вызовов методов поднимать очень много компонент и смотреть, что процессоры аннотаций сработали правильно. Т.е. вместо того, чтобы просто вызвать метод, мы пишем кучу слоёв какого-то мусора, чтобы вызывать ровно тот же метод. P>>Вот эти вещи нужно выталкивать во фремворк, что бы там протестировать раз на все времена, и не надо было каждый раз перепроверять "а не отвалился ли процессор аннотации" P>>Вы же не проверяете, что джава выполняет циклы правильно? Так и здесь ·>Фреймворк-ориентед программинг? Нет, спасибо.
Теги:
Введите теги разделенные пробелами. Обрамляйте в кавычки словосочетания с пробелами внутри, например:
"Visual Studio" .NET
Имя, пароль:
Загрузить
Нравится наш сайт?
Помогите его развитию!
Отключить смайлики
Получать ответы по e-mail
Проверить правописание
Параметры проверки …