Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[18.221.119.21] |
|
Страницы: (6) [1] 2 3 ... 5 6 все ( Перейти к последнему сообщению ) |
Сообщ.
#1
,
|
|
|
Всем привет.
Вот есть техника разработки ПО, именуемая TDD. Интересно стало много вообще кто ее использует? Очень часто встречаю ее в вакансиях, но везде где я был, про эту технику спрашивали либо очень слабо(какие то общие вопросы, типа что это вообще такое), либо не спрашивали вовсе, порой складывается впечатление, что им это нужно для галочки онли. Я как то пробовал писать по этой технике, но либо был не опытен конкретно в этой технике, либо не было времени, одни сплошные дедлайны, поэтому как то не пошло в свое время. Сейчас снова вернулся к этому, начал тут почитывать одну книжку. Наверное снова буду пробовать. Кто по этой методике работает - хотелось бы услышать как изменилась ваша жизнь, после использования этой техники? Стало меньше времени уходить на разработку? Или вас просто заставляют на работе писать по этой технике, но вы считаете ее оцтоем? Ну и вообще у кого какие мысли, высказывайте. Было бы интересно обсудить эту технику. Добавлено Ну и плюс еще статья с хабра в догонку(перевод - Автор оригинала: Eric Elliott), кому не лень почитать - https://habr.com/ru/company/ruvds/blog/450316/ Из этой статьи для меня оказалось в новинку что наличие Мок-объектов в UT говорит о том, что с кодом что то не так, и что DI - это признак жесткой связи между объектами В прочем автор поясняет почему, в принципе с такой точкой зрения - я даже согласен. Но для меня это стало открытием на самом деле. |
Сообщ.
#2
,
|
|
|
Цитата Wound @ Или вас просто заставляют на работе писать по этой технике, но вы считаете ее оцтоем? Это. Но это на прошлой работе. На текущей — нет TDD и так во многих случаях удобней. Цитата Wound @ Стало меньше времени уходить на разработку? ХЗ, бывает, что изменение требует значительно меньше кода, чем тестов, и приходится писать кучу однообразной мути, чтобы типа было покрыто тестами и т.п. Причём, ладно юнит-тесты, но функциональные были просто адом. Как по мне, значимость автоматического тестирования несколько преувеличена, а иногда оно приносит больше вреда, чем пользы, например, провоцирует писать quick&dirty код (тесты ж всё равно отловят ошибки, а на их написание и так уходит куча времени, чтоб ещё его тратить на качественный код/архитектуру, а синюю фазу рефакторинга на практике часто игнорируют). Конечно, это сильно зависит от сферы применения (всякое «mission-critical» ПО всё же лучше хорошо тестировать) и от «уровня» сервиса (например, фронтенд менее критичен к ошибкам, чем какие-нибудь РСУБД/ОС и прочая инфраструктура, которую использует сервис). Цитата Wound @ Из этой статьи для меня оказалось в новинку что наличие Мок-объектов в UT говорит о том, что с кодом что то не так Я после работы в TDD-ориентированной компании пришёл к выводу, что моки вообще больше зло, чем добро, и не нужны. Стабы лучше. ) Добавлено Ещё раздражает мантра «тесты — это спецификация». Возникает вопрос: а почему бы не писать код декларативно, чтобы он выглядел как спецификация и не требовал тестов? Не, опять же, бывают случаи, когда какой-нибудь числодробильный код не декларативен ради оптимизации времени выполнения и/или памяти, такие функции разумно покрыть тестами, да, тем более, что обычно это достаточно независимые функции и мокать/стабать/вообще-создавать-сколько-нибудь-сложное-окружение там не нужно. |
Сообщ.
#3
,
|
|
|
Цитата Wound @ Кто по этой методике работает - хотелось бы услышать как изменилась ваша жизнь, после использования этой техники? Хотелось бы работать, но полноценно нигде, где я работал, это внедрено не было. Цитата Ну и вообще у кого какие мысли, высказывайте. Было бы интересно обсудить эту технику. Пока мысли такие, что это хорошая техника, но нужно с ней обязательно "пожить" какое-то продолжительное время, чтобы полноценно освоить. Когда я таки начну полноценно делать свои проектики, тогда точно буду юзать TDD. Дело за малым Цитата Из этой статьи для меня оказалось в новинку что наличие Мок-объектов в UT говорит о том, что с кодом что то не так Статью я не читал еще. Но думаю, что ты усилил утверждение. Обычно говорят о том, что моки могут свидетельствовать о том, что с кодом что-то не так. Соовтетственно, обилие моков - повод задуматься. Добавлено Цитата korvin @ ХЗ, бывает, что изменение требует значительно меньше кода, чем тестов, и приходится писать кучу однообразной мути, чтобы типа было покрыто тестами и т.п. "типа покрыто" уже звучит как-то странно... Я так понимаю, что когда говорят об уменьшении времени, имеется в виду не врямя на разработку конкретной фичи, а скорее время на поддержку кода и пр. Сколько времени отладки и поиска ошибок экономит TDD. Ну и часто можно услышать, что он еще приводит к существенному сокращению критичных багов на проде. Добавлено Цитата korvin @ Ещё раздражает мантра «тесты — это спецификация».Вс Все относительно же. В том смысл, что такое отношение к тестам лучше, чем "обычное", когда "напишем потом, сейчас функциональность важнее". Цитата Возникает вопрос: а почему бы не писать код декларативно, чтобы он выглядел как спецификация и не требовал тестов? Даже если сам код декларативный, это не означает, что он правильный. Тесты нужны в любом случае для проверки. Скажем, поменяли что-то в коде и "случайно" нарушили контракт, какая разница декларативно код написан или нет? Ну или я тебя не так понял. |
Сообщ.
#4
,
|
|
|
Цитата D_KEY @ Сколько времени отладки и поиска ошибок экономит TDD. Практически нисколько. Цитата D_KEY @ Ну и часто можно услышать, что он еще приводит к существенному сокращению критичных багов на проде. Каждый кулик… Оно отлавливает лишь самые простые, которых бы не было, если бы использовались нормальные языки (а не JS) и писался бы нормальный код. А нетривиальные баги всё равно проскакивают. Цитата D_KEY @ В том смысл, что такое отношение к тестам лучше, чем "обычное", когда "напишем потом, сейчас функциональность важнее". Та ничем не лучше. Цитата D_KEY @ Даже если сам код декларативный, это не означает, что он правильный. Тесты нужны в любом случае для проверки. Ну ахренеть теперь. А если тест есть — это не значит, что он (тест) правильный. А если в тесте нет какого-то кейса? Цитата D_KEY @ Скажем, поменяли что-то в коде и "случайно" нарушили контракт, какая разница декларативно код написан или нет? Поменяли что-то в тесте и "случайно" нарушили требования, какая разница, есть тест или его нет? Цитата D_KEY @ Ну или я тебя не так понял. Не удивлюсь, если так. =) |
Сообщ.
#5
,
|
|
|
Цитата korvin @ Цитата D_KEY @ Ну или я тебя не так понял. Не удивлюсь, если так. =) А ты можешь кодом показать? Добавлено Цитата korvin @ Оно отлавливает лишь самые простые, которых бы не было, если бы использовались нормальные языки (а не JS) и писался бы нормальный код. Ну в идеальном мире всяко было бы лучше, да. Начать писать юниты те же - достаточно легко. Примеить TDD - чуть сложнее. Перейти на "нормальные языки" - крайне трудно. Писать нормальный код - невозможно Добавлено Цитата korvin @ Практически нисколько. ... Каждый кулик… ... Та ничем не лучше. Грустно, если так. Добавлено Цитата korvin @ А нетривиальные баги всё равно проскакивают Ну это понятно. Вопрос еще в том, насколько проще это поймать, воспроизвести, зафиксировать в новом тесте и вылить на прод. Обычно адепты говорят, что быстрее. Цитата Ну ахренеть теперь. А если тест есть — это не значит, что он (тест) правильный. А если в тесте нет какого-то кейса? Значит нужно его добавить как только обнаружили что-то. Цитата Поменяли что-то в тесте и "случайно" нарушили требования, какая разница, есть тест или его нет? Вероятность-то разная. В общем, если покажешь код, который не нуждается в тестирвании, будет неплохо. Добавлено Цитата korvin @ Как по мне, значимость автоматического тестирования несколько преувеличена Автоматическое тестирование уменьшает ручное. С современными требованиями по скорости поставки иначе никак. |
Сообщ.
#6
,
|
|
|
Цитата D_KEY @ А ты можешь кодом показать? Что показать? Цитата D_KEY @ Ну в идеальном мире всяко было бы лучше, да. Начать писать юниты те же - достаточно легко. Примеить TDD - чуть сложнее. Перейти на "нормальные языки" - крайне трудно. Писать нормальный код - невозможно В идеальном мире меритократии? Оно достаточно легко и чуть сложнее пока кодовая база небольшая, а потом объём тестов и говнокода становится настолько большим, что усилия на сопровождение этого всего начинают перевешивать пользу от него. Цитата D_KEY @ Обычно адепты говорят, что быстрее. Я ж говорю, каждый кулик… Цитата D_KEY @ Значит нужно его добавить как только обнаружили что-то. И вправду, как я об этом не подумал. А почему бы сразу в коде не поправить? Цитата D_KEY @ Вероятность-то разная Не особо. А «flaky tests» — слышал такое? А поломки совершенно, на первый взгляд, не связанных тестов из-за изменений в других тестах не встречал? Цитата D_KEY @ В общем, если покажешь код, который не нуждается в тестирвании, будет неплохо. filter odd |> map (* 2) |> reduce (+) Цитата D_KEY @ Автоматическое тестирование уменьшает ручное. С современными требованиями по скорости поставки иначе никак. Я ничего не говорил про ручное. Не, я ж не против наличия автотестов, но пусть их и пишут тестировщики/бизнес-аналитики/постановщики-задач, но TDD-то не про это. |
Сообщ.
#7
,
|
|
|
Цитата korvin @ Цитата D_KEY @ А ты можешь кодом показать? Что показать? Декларативный код, которому не нужны тесты. Цитата В идеальном мире меритократии? Ага, главное не забывать, что он недостежим Поэтому важны тенденции, а не абсолютные показатели. Цитата Оно достаточно легко и чуть сложнее пока кодовая база небольшая, а потом объём тестов и говнокода становится настолько большим, что усилия на сопровождение этого всего начинают перевешивать пользу от него. Не свидетельствует ли это о хреновой декомпозиции? Цитата Цитата D_KEY @ Значит нужно его добавить как только обнаружили что-то. И вправду, как я об этом не подумал. А почему бы сразу в коде не поправить? Так ты правишь и там и там, просто наличие теста позволит тебе в следующий раз, когда сломаешь, заметить это на более ранней стадии. Цитата А поломки совершенно, на первый взгляд, не связанных тестов из-за изменений в других тестах не встречал? Встречал. И это всегда были или хреновые тесты или хреновая подсистема или хреновая декомпозиция и кривые связи. То есть опять же некий признак, что явно идет не так, как хотелось бы Цитата Цитата D_KEY @ В общем, если покажешь код, который не нуждается в тестирвании, будет неплохо. filter odd |> map (* 2) |> reduce (+) Ну и почему на это не стоит написать тест? Ты ведь можешь в случае правок учесть не все места, где он используется. А тест проверит, что все контракты соблюдены. Цитата Не, я ж не против наличия автотестов, но пусть их и пишут тестировщики/бизнес-аналитики/постановщики-задач, но TDD-то не про это. На моем опыте всегда было лучше, когда разрабы продукта писали сами unit-тесты и активно участвовали в разработке автотестов на других уровнях. Но не буду утверждать, что это всегда так. Добавлено Цитата D_KEY @ Так ты правишь и там и там, просто наличие теста позволит тебе в следующий раз, когда сломаешь, заметить это на более ранней стадии. И это не сферический пример в вакууме. У меня сейчас автотесты "опаздывают" чуть по разработке продукта (догоняем, но пока не догнали). Так это уже приводило несколько раз к тому, что одни и те же вещи уже несколько раз отламывали в продукте |
Сообщ.
#8
,
|
|
|
Цитата D_KEY @ Не свидетельствует ли это о хреновой декомпозиции? Нет, с чего бы? Цитата D_KEY @ Так ты правишь и там и там, просто наличие теста позволит тебе в следующий раз, когда сломаешь, заметить это на более ранней стадии. На какой более ранней? Цитата D_KEY @ Встречал. И это всегда были или хреновые тесты или хреновая подсистема или хреновая декомпозиция и кривые связи. Ага, т.е. к хреновому коду ещё и добавляем хреновые тесты. Больше хрени богу хрени. Цитата D_KEY @ То есть опять же некий признак, что явно идет не так, как хотелось бы Ага: — У нас что-то не так — Давайте использовать TDD — Теперь у нас что-то не так x10 Напоминает картинку отсюда. Цитата D_KEY @ Ну и почему на это не стоит написать тест? Потому что этот код полностью корректен. Цитата D_KEY @ Ты ведь можешь в случае правок учесть не все места, где он используется. А какое мне дело до того, где он используется? Это независимый юнит, если по каким-то требованиям у него меняется определение, то либо новые требования / новое определение корректны для всех, либо кому-то придётся использовать старую версию или не использовать расшаренный юнит, а писать свою реализацию. Как тут поможет юнит-тест этого кода? Цитата D_KEY @ На моем опыте всегда было лучше, когда разрабы продукта писали сами unit-тесты и активно участвовали в разработке автотестов на других уровнях. На моём опыте — это дичайшая дичь. Цитата D_KEY @ У меня сейчас автотесты "опаздывают" чуть по разработке продукта Так это не TDD. Добавлено Цитата D_KEY @ Так это уже приводило несколько раз к тому, что одни и те же вещи уже несколько раз отламывали в продукте Так это потому что «хреновая подсистема или хреновая декомпозиция и кривые связи». |
Сообщ.
#9
,
|
|
|
Цитата korvin @ Цитата D_KEY @ Не свидетельствует ли это о хреновой декомпозиции? Нет, с чего бы? Ну потому что при нормальной декомпозиции размер системы не должен настолько сильно сказываться. Цитата Цитата D_KEY @ Так ты правишь и там и там, просто наличие теста позволит тебе в следующий раз, когда сломаешь, заметить это на более ранней стадии. На какой более ранней? На самой ранней из возможных. В идеале, это в юнит-тест добавить. Если не получается, то дальше. В любом случае, это будет отловлено в процессе CI. Цитата Цитата D_KEY @ Встречал. И это всегда были или хреновые тесты или хреновая подсистема или хреновая декомпозиция и кривые связи. Ага, т.е. к хреновому коду ещё и добавляем хреновые тесты. Больше хрени богу хрени. Я к тому, что на первый взгляд мне кажется, что TDD показывает проблемы системы. И это хорошо. А если его применять сначала, то кажется, что многих проблем можно будет избежать. Но пока не поработаю плотно с этим хотя бы полгодика, не стану ничего утверждать. Цитата Цитата D_KEY @ То есть опять же некий признак, что явно идет не так, как хотелось бы Ага: — У нас что-то не так — Давайте использовать TDD — Теперь у нас что-то не так x10 Не совсем так. Начали использовать TDD, что помогло нам заметить проблемы. Устранили проблемы, стало лучше со многим. Цитата Цитата D_KEY @ Ну и почему на это не стоит написать тест? Потому что этот код полностью корректен. Корректность кода определяется не самим кодом, а тем, удовлетворяет ли он контрактам, которые от него хотят извне. Цитата Цитата D_KEY @ Ты ведь можешь в случае правок учесть не все места, где он используется. А какое мне дело до того, где он используется? Это независимый юнит, если по каким-то требованиям у него меняется определение, то либо новые требования / новое определение корректны для всех, либо кому-то придётся использовать старую версию или не использовать расшаренный юнит, а писать свою реализацию. Как тут поможет юнит-тест этого кода? В юнит-тесте должны проверяться контракты юнита, которые декларируются наружу. Соответственно, поправили код, если тесты упали, значит нужно или сохранить совместимость со старыми контрактами или найти и исправить все места, где этот код используется в соответствии с новым контрактом. Цитата Цитата D_KEY @ На моем опыте всегда было лучше, когда разрабы продукта писали сами unit-тесты и активно участвовали в разработке автотестов на других уровнях. На моём опыте — это дичайшая дичь. Интересно. Цитата Цитата D_KEY @ У меня сейчас автотесты "опаздывают" чуть по разработке продукта Так это не TDD. Я знаю. Мне кажется, что если бы он применялся с самого начала, было бы лучше. Цитата Так это потому что «хреновая подсистема или хреновая декомпозиция и кривые связи». Да! И я думаю, что многих из этих проблем не было бы при использовании TDD со старта. |
Сообщ.
#10
,
|
|
|
Цитата D_KEY @ Ну потому что при нормальной декомпозиции размер системы не должен настолько сильно сказываться. Как это не должен, когда должен: к юнит тестам добавляются интеграционные тесты, потом функциональные и системные. Цитата D_KEY @ На самой ранней из возможных. Самая ранняя из возможных — это хинты IDE от компилятора и анализатора. Цитата D_KEY @ Я к тому, что на первый взгляд мне кажется, что TDD показывает проблемы системы. Нет, не показывает. Что он показывает, так проблемы анализа и постановки задач и вместо нормального решения затыкает костылём (собой). Цитата D_KEY @ А если его применять сначала, то… …никогда не дойдёшь до реализации. Либо вместо тебя дойдут конкуренты по методу херак-херак и в продакшн, но это уже другая история. Цитата D_KEY @ Начали использовать TDD, что помогло нам заметить проблемы. Не помогло. Добавило новых. Цитата D_KEY @ Корректность кода определяется не самим кодом, а тем, удовлетворяет ли он контрактам, которые от него хотят извне. Контракт этого кода: сумма удвоенных нечётных целых чисел из списка. Именно это в нём и написано. Дальше что? Цитата D_KEY @ Соответственно, поправили код Зачем вы поправили код? Цитата D_KEY @ найти и исправить все места, где этот код используется в соответствии с новым контрактом. Это ещё с какого хера? Если у этих мест появились новые требования (новый контракт), пусть сами его использование и чинят. Моя задача, как реализатора контракта — реализовать его. Цитата D_KEY @ И я думаю, что многих из этих проблем не было бы при использовании TDD со старта. Что ж, удачи тебе. ) |
Сообщ.
#11
,
|
|
|
Я как то при написании личного говнокода пробовал сначала написать тесты. Было неудобно то, что я до написания плохо представлял себе, какой конкретно интерфейс я хочу получить в проектируемом классе, и в результате, когда он менялся, приходилось переписывать тесты, потом нужно было красить их в зелёный, потом опять смена интерфейса с переписыванием тестов и так несколько раз. Зато потом, когда переводил поделие на линукс, тесты помогли, и прога заработала сразу как только были пройдены тесты основной либы.
На работе у нас тесты есть, но на них всегда не хватает времени, так что ни о каком TDD не идёт и речи. На одной из прошлых работ в своей зоне ответственности организовал тестирование - написал какие-то тесты, а потом, когда находились баги, первым делом вносил их в тест. Даже баги многопоточки получалось тестами покрывать, правильно расставляя в коде sleep-ы. TDD, вероятно, там бы сработало, но было лень ему следовать |
Сообщ.
#12
,
|
|
|
Цитата D_KEY @ Статью я не читал еще. Но думаю, что ты усилил утверждение. Обычно говорят о том, что моки могут свидетельствовать о том, что с кодом что-то не так. Соовтетственно, обилие моков - повод задуматься. Вот тут об этом пишут: https://medium.com/javascript-scene/mocking...ll-944a70c90a6a Основная идея в том, что если у тебя есть Моки, значит у тебя тесная связь, и твоя функция/система зависит от чего то извне, без чего не может быть протестирована, а это типа херово. Надо писать код в функциональной парадигме, чтоб этого избегать, чистые функции(без сайд эффектов), всякие там монады(then().then().then...) и т.п. Типа моки нужно применять в интеграционных тестах, и весь функционал, которые не покрывают UT - подразумевается что он должен работать с IO, соккеты/файлы/чета там еще, поэтому это тистируется интеграционными тестами. Ну это как я понял из статьи выше. Добавлено Вот например вот тут он описывает что представляет из себя тесную связь, а что слабую: Цитата Tight coupling: Class inheritance (coupling is multiplied by each layer of inheritance and each descendant class) Global variables Other mutable global state (browser DOM, shared storage, network, etc…) Module imports with side-effects Implicit dependencies from compositions, e.g., const enhancedWidgetFactory = compose(eventEmitter, widgetFactory, enhancements); where widgetFactory depends on eventEmitter Dependency injection containers Dependency injection parameters Control parameters (an outside unit is controlling the subject unit by telling it what to do) Mutable parameters Loose coupling: Module imports without side-effects (in black box testing, not all imports need isolating) Message passing/pubsub Immutable parameters (can still cause shared dependencies on state shape) DI - тесная связь. Вот для меня это открытием стало, потому что до этого я думал что это слабая связь, да и везде об этом пишут. |
Сообщ.
#13
,
|
|
|
Цитата Wound @ Кто по этой методике работает - хотелось бы услышать как изменилась ваша жизнь, после использования этой техники? Стало меньше времени уходить на разработку? Я стараюсь сначала писать тест, а потом фиксить баг. Это не всегда получается в силу разных причин, но я стараюсь Требований писать тесты у нас нет, более того, шеф не доверяет юнит-тестам и поэтому на каждый таск делается ручной тест (им он доверяет) Времени уходит больше, т.к. на написание теста тоже нужно время. А из-за того, что у нас код не всегда можно протестировать, приходится иногда что-то менять в коде, чтобы сделать его тестируемым. В принципе мне нравится как сама идея TDD, так и результат. При этом я допускаю, отход от паттерна "сперва тест". Цитата Wound @ Из этой статьи для меня оказалось в новинку что наличие Мок-объектов в UT говорит о том, что с кодом что то не так, и что DI - это признак жесткой связи между объектами В прочем автор поясняет почему, в принципе с такой точкой зрения - я даже согласен. Не знаю, наверное я не понял всей мысли, но эта мысль кажется мне странной Я уж не говорю о том, что Мок-объекты заменяют итерфейсы, а не объекты (D из SOLID). |
Сообщ.
#14
,
|
|
|
Цитата Fester @ Не знаю, наверное я не понял всей мысли, но эта мысль кажется мне странной Я уж не говорю о том, что Мок-объекты заменяют итерфейсы, а не объекты (D из SOLID). Ну вот автор и приводит пример. Типа можно ли протестировать модуль/функцию без имитации зависимости? Если нельзя - то это эта функция/модуль - тесно связана с имитируемыми зависимостями. Соотвественно получается что Моки и DI - являются тесной зависимостью. Чем больше зависимостей - тем больше вероятность получить ошибку. Вот тут он это описывает: Цитата Ironically, most of the sources of coupling are mechanisms originally designed to reduce coupling. That makes sense, because in order to recompose our smaller problem solutions into a complete application, they need to integrate and communicate somehow. There are good ways, and bad ways. The sources that cause tight coupling should be avoided whenever it’s practical to do so. The loose coupling options are generally desirable in a healthy application. You might be confused that I classified dependency injection containers and dependency injection parameters in the “tight coupling” group, when so many books and blog post categorize them as “loose coupling”. Coupling is not binary. It’s a gradient scale. That means that any grouping is going to be somewhat subjective and arbitrary. I draw the line with a simple, objective litmus test: Can the unit be tested without mocking dependencies? If it can’t, it’s tightly coupled to the mocked dependencies. The more dependencies your unit has, the more likely it is that there may be problematic coupling. Now that we understand how coupling happens, what can we do about it? |
Сообщ.
#15
,
|
|
|
Мне кажется, что автор этого текста сам себя перемудрил
Взаимодействие происходит по какому-либо (заранее известному) контракту, который описывается неким интерфеском. Юнит, соответственно, не взаимодействует ни с какими внешними объектами, он взаимодествует с контрактами. Более того, юнит должен исходить из того, что контракты работают так, как описано. А список "слабых связей" жесть: >> Module imports without side-effects (in black box testing, not all imports need isolating) Не совсем понимаю, что это такое >> Message passing/pubsub А потом тестировать switch, который будет разгребать эти сообщения. >> Immutable parameters (can still cause shared dependencies on state shape) Ага и по 100 параметров в каждой функции. Ну нахрен. |