Автоматизация тестирования
А старые интерфейсы просто захламляли код.
А, ещё глянул, сколько же реализаций этих интерфейсов в проекте. В подавляющем большинстве случаев, да практически во всех - адын штука. Наличие этой тучи интерфейсов просто заставляет меня вместо f12 жать ctrl+f12 (я про Сишарп и Студию), чтобы сразу перейти к реализации. А ещё челы не освоили наследование комментов интерфейса реализацией, и писали в комментах к классам "смотри комменты интерфейса".
Более или менее эффективно это может работать только с помощью собственного расширения для тестового фреймворка + работающая со снэпшотами БД (оракл или MS) + самописный UnitOfWork, который надо использовать как в расширении тестового фреймворка, так и в продуктивном коде. И даже в этом случае, производительность таких тестов будет желать лучшего. Я уж не говорю о том, что будут не юнит-тесты :D
Просто юзаешь Entity Framework и всё. Там и юнит оф ворк, и прочее - всё встроено.
Во-вторых, приведенный код нестестируем не столько из-за БД, сколько из-за new и из-за того, что UserService - реальный объект, а значит нельза мокнуть функцию GetUser. Которая, в свою очередь, тоже возвращает реальный объект, а значит нельзя проверить была ли вызвана функция Login :)
Короче говоря, использование классов сделали эту функцию нетестируемой юнит-тестами :) Это не значит, что функцию нельзя протестировать, но труда для создания теста надо будет вложить в десятки раз больше. Так что лучше было бы сразу писать на абстракциях :D
По-моему, лучше тестировать на вещах, максимально приближенных к реальным, а не всяких моках. А что может быть ближе к реальному, чем копия реального? Копирнуть реальное - дело пары кликов, грубо говоря. А вот создать максимально приближенные к реальному подделки - тот ещё геморрой.
При этом, даже если делать все по правилам нет гарантии получения отличного кода.
Вот в этом-то и проблема. Претензий у фен-шуистов дохрена, а гарантий - никаких. В чистом виде инфоцигане. Просто разные дяди Бобы получили сцену и широкую аудиторию, а вы нет. ))
Оно всегда превращается в большую кучу мусора
У меня есть несколько иной опыт Да, может быть сложно, да может быть поначалу непонятно,
но если проект постоянно делали "нормальные" прогеры, то нет опаски что либо менять. И со временем точно знаешь где и что менять.
Если же использовалась методика лишь бы как, то и понимание не приходит и менять что либо боишься.
Вот казалось бы совершенно безобидная операция - переименовать намеспасе. А фиг вам - после этого уже ничего не запускается.
подмены СУБД, GUI и прочих вещей
-----
Если написано нормально, то любая из замен делается в пределах уровня без особых проблем.
Я не про то, что она может делаться, а про то, что она делается. Так вот, обычно она не делается, а используется раз и навсегда написанная. А потом приходят новые технологии, и уже мало кто помнит, как там всё подменяется, и почти всё переписывается с нуля. А все усилия по изначальному созданию максимальной универсальности и заменяемости идут коту под хвост, добавляют лишнюю сложность проекту и вообще, похоже, существуют лишь для поднятия чувства собственной важности недавно открывшим для себя какого-нибудь дядю Боба.
Вот в этом-то и проблема
Проблема не в этом, а в том что сам процесс разработки достаточно сложный процесс и выполнив только одну операцию "правильно" нет гарантии на правильность конечного продукта.
Типа как товар из Китая, вроде всё и правильно, но в итоге часто недоволен.
По-моему, лучше тестировать на вещах, максимально приближенных к реальным, а не всяких моках. А что может быть ближе к реальному, чем копия реального? Копирнуть реальное - дело пары кликов, грубо говоря. А вот создать максимально приближенные к реальному подделки - тот ещё геморрой.
Тестировать надо определенную логику.
Если вернуться к примеру:
public void Foo (DbConnection db, UserProvider provider) { UserService srv = new UserService (db); User user = srv.GetUser (provider); if (user != null) { user.Login (); } }
Предположим, тебе надо протестировать, что при получении юзера вызывается функция Login.
Если тестировать на объектах, то тест может стать крассным из-за ошибки в GetUser, а значит написанный тест тестирует все, что угодно, но только не фунцкцию Foo :)
Чаще всего сталкиваешься именно с проектами, где разработчиков правила не интересовали.
Значит, ваши теории "делай хорошо и не делай плохо" не работают. Надо менять теории, приближая их к реальности, а не отрицать реальность, говоря, что она какая-то неправильная, а вот теория была зашибись.
По-моему, лучше тестировать на вещах, максимально приближенных к реальным, а не всяких моках. А что может быть ближе к реальному, чем копия реального? Копирнуть реальное - дело пары кликов, грубо говоря. А вот создать максимально приближенные к реальному подделки - тот ещё геморрой.Тестировать надо определенную логику.
Зачем смотреть весь костюм? Ведь можно оценить по частям. К пуговицам претензии есть?
Мокаем отдельные части, мокаем части побольше, мокаем ещё побольше... И вот уже весь проект замочен в чём-то жидком и вонючем, не имеющим отношения к реальному окружению и ошибкам, в нём возникающим.
public void Foo (DbConnection db, UserProvider provider) { UserService srv = new UserService (db); User user = srv.GetUser (provider); if (user != null) { user.Login (); } }Предположим, тебе надо протестировать, что при получении юзера вызывается функция Login.
Если тестировать на объектах, то тест может стать крассным из-за ошибки в GetUser, а значит написанный тест тестирует все, что угодно, но только не фунцкцию Foo :)
Правильный вызов логина на объекте юзер - прерогатива объекта юзер. Вот в юните для него пусть и тестируется. А так вы в любом месте вызова логина будете этот вызов тестировать? В пяти разных местах будет - в пяти местах будете тестировать, хотя вызов зависит лишь от объекта юзер, который находится в одном месте.
Разве юнит тесты не могут быть каскаднозависимыми? Т.е. не выполнились тесты на объектах в тестируемой функции, значит не выполнились тесты и на самой функции.
Если бы изолированные тесты с моками работали как в теории, то не нужны были бы интеграционные тесты, т.к. вы фактически тестируете интеграцию объекта user в функцию Foo. А раз у вас есть интеграционные тесты, значит вы не доверяете даже изолированным юнит тестам. Тогда смысл тестировать, если нижележащие объекты не проходят тесты? Вот когда начнут проходить, тогда и оттестируете. Нет никакого смысла в правильности функции Foo, если неправильны используемые ей объекты. А пока это получается самоуспокоение и лишняя работа - тестировать то, что потом всё равно будет перетестировано интеграцией. Может, вы хотите покрытие юнит тестами больше 100%? По-моему, это легко осуществить, продублировав все тесты по нескольку раз для разных мест.
Вообще, странно, что принципы программирования, а конкретно единственность ответственности, у вас легко нарушаются в тестировании, и вы ответственность одного объекта легко размазываете по всем другим местам, где этот объект используется.
У вас сплошной положительный опыт.Кто сказал, что сплошной? Чаще всего сталкиваешься именно с проектами, где разработчиков правила не интересовали.
Следил за одним проектом в сети. С момента начала работ ещё до релиза. Челы получили некоторое финансирование от спонсора и года два времени на разработку. Делать надо было много и с нуля. Фигачили на результат, а не на будущую многолетнюю поддержку. Выкатили прототип, который уже на тестах пользователей взлетел. Так прототип в релиз и ушёл. И лишь отдав долги инвесторам и заработав самим, стали переписывать всё и покрывать тестами. Но ударились в другую крайность - гонку за феншуйством. Гордились, что покрытие тестами почти 100%, расширяемость неимоверная, проект на века, все дела. А потом пришли эффективные менеджеры по выжиманию бабла отовсюду, и вековой
проект резко стал "ну протянем ещё несколько годиков". Полкоманды сменилось, пошли сокращения, челы почти забили на баги, а донатные хреновины сыпались одна за другой, продолжая убивать проект, но зато выжимая бабло из остатков пользователей. Но хозяева проекта бабла, конечно, подняли. Вот так и становятся семидевятизнаками - не по феншую.
Не стройте на века. Бесполезно и неблагодарно. Не сломается само, так сломают специально. Вообще разницы не вижу между чуваками, талдычащими про строгое придерживание кучи всяких солидов, интерфейсов и тестов, и тренерами личностного роста и успешного успеха. Та же хрень, только в профиль. Инфоциганам надо же что-то продавать - мечты об идеальном мире, программистские библии со своими десятью заповедями. А вы просто легко ведётесь на эту всю херню - ну чел же правильные вещи говорит! Мы пойдём за ним на край света!
лучше тестировать на вещах, максимально приближенных к реальным, а не всяких моках.
Заблуждение, которым я тоже иногда страдаю
Это будут уже не юнит тесты. Или вот например:
Нужно проверить отсылку почты при каких то условиях. Ваша реализация на реальных вещах?
А вот создать максимально приближенные к реальному подделки - тот ещё геморрой.
просто не нужно их создавать.