Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.142.210.100] |
|
Страницы: (6) « Первая ... 4 5 [6] все ( Перейти к последнему сообщению ) |
Сообщ.
#76
,
|
|
|
Нет. Цитата Fester @ Я уж как-нибудь обойдуть одним объектом, который полностью описывает "пользователя" и не буду убиваться из-за некоторой избыточности Любитель сильной связности. Понятно. Только в говнокоде. Просто убогие недоязычки не позволяют легко и просто описывать типы. Впрочем, на сегодняшний день из таких только Java осталась, да Pascal. На Джаве ты не пишешь, значит на Паскале? Цитата Fester @ В данном тесте - последний параметр - это заглушка и, соответственно Request - это мок-объект. Нет. Request даже не объект. |
Сообщ.
#77
,
|
|
|
Вопрос к практикам. Вот начинаем мы какую-то новую штуку кодить по TDD. Мы начинаем же с самых высокоуровневых задач? Т.е. сначала пишем тест на высокоуровневую задачу, верно? Потом, при развитии, проверяемая такими тестами функциональность в любом случае будет раскидана по нескольким юнитам. Так вот вопрос, эти более ранние тесты становятся интеграционными? Ведь у каждого юнита появится свой тест.
|
Сообщ.
#78
,
|
|
|
Цитата D_KEY @ Так вот вопрос, эти более ранние тесты становятся интеграционными? Ведь у каждого юнита появится свой тест. Не обязательно, зависит от архитектуры. У тебя же высокоуровневая задача является некоторой композицией низкоуровневых, вот смотри, в моём примере, я переделал высокоуровневый сервис (относительно Accounts, Transactions, Compliance, Notifier) Transfer, чтобы он не включал зависимости внутрь себя, т.е. вместо Transfer + Accounts + Transactions ... получилось Composer + Transfer + Accounts + Transactions ... где Transfer хоть и реализует высокоуровневую логику посредством остальных компонентов, но расположен на том же (структурном?) уровне фактически. Composer в свою очередь может быть абстрактным и тривиальным и иметь свои юнит-тесты. Естественно, можно сделать и интеграционные тесты (они ж не взаимозаменяемы с юнит-тестами), а на самом-самом верхнем уровне ещё добавить функциональные/end-to-end/системные тесты. Добавлено Ну, собственно, если у тебя правильная инверсия зависимостей, то высокоуровневый модуль полностью независим от низкоуровневых и ты можешь писать нормальные юнит-тесты для него ) |
Сообщ.
#79
,
|
|
|
Цитата korvin @ Ну, собственно, если у тебя правильная инверсия зависимостей, то высокоуровневый модуль полностью независим от низкоуровневых и ты можешь писать нормальные юнит-тесты для него ) Это да. Но вопрос изначальных тестов. Они же исходят из высокоуровневых задач и будут проверять работу целиком. Соответственно, они должны будут или перейти на уровень интеграционных или, став юнит-тестами для самих высокоуровневых юнитов, перестанут проверять высокоуровневые задачи. |
Сообщ.
#80
,
|
|
|
Цитата D_KEY @ Но вопрос изначальных тестов. Они же исходят из высокоуровневых задач и будут проверять работу целиком Э, ты путаешь тёплое с мягким, тип проверки зависит от типа теста и не зависит от уровня тестируемого компонента в системе. Работу целиком проверяют end-to-end и системные тесты. Как только ты принял решение выделить из высокоуровневого модуля под-модуль, сначала ты должен поменять тесты соответствующим образом, в этом же суть TDD: любое изменение начинается с тестов, т.е. сначала нужно убедиться, меняется ли архитектура/требование, потом отразить изменения в тестах, если нужно и только потом — в реализации. Тут всё зависит от того, выносишь ты субкомпонент как внешнюю зависимость или оставляешь его деталью внутренней реализации суперкомпонента: – если ты делаешь инверсию зависимости для этого субкомпонента, то твой изначальный тест суперкомпонента нужно разбить на два: 1) юнит-тест, который будет мокать/стабать интерфейс зависимости и проверять корректность входа/выхода суперкомпонента 2) интеграционный, который также будет мокать/стабать интерфейс зависимости, но проверять само взаимодействие, т.е. например, убеждаться, что суперкомпонент при каком-то входе вызывает метод интерфейса зависимости, нужное количество раз с правильными параметрами - если ты не делаешь инвресию зависимости, просто выносишь часть кода суперкомпонента в субкомпонент и используешь последний как некую библиотеку, то объект субкомпонента будет инстанциироваться внутри суперкомпонента (если это не так и ты передаёшь экземпляр субкопонента в публичный конструктор супера, то это уже внешняя зависимость и тебе лучше сделать полноценную инверсию и перейти к первому случаю) и ни мокать, ни стабать ты его не можешь и не должен, он всё также остаётся деталью внутренней реализации и изначальный тест у тебя не меняется. |
Сообщ.
#81
,
|
|
|
Цитата korvin @ если ты делаешь инверсию зависимости для этого субкомпонента, то твой изначальный тест суперкомпонента нужно разбить на два: 1) юнит-тест, который будет мокать/стабать интерфейс зависимости и проверять корректность входа/выхода суперкомпонента 2) интеграционный, который также будет мокать/стабать интерфейс зависимости, но проверять само взаимодействие, т.е. например, убеждаться, что суперкомпонент при каком-то входе вызывает метод интерфейса зависимости, нужное количество раз с правильными параметрами Во, кажется это ответ на мой вопрос Осталось понять, как правильно писать интеграционные тесты в C++ А то я так понимаю теперь, что у меня всегда были юнит-тесты, которые пишут разрабы, и системные, которые пишут qa. |
Сообщ.
#82
,
|
|
|
Кстати, возможно, в интеграционном тесте лучше не мокать субкомпонент, или добавить к мокнуты ещё тесты с использованием реального инстанса субкомпонента, иначе некоторые изменения не отловятся тестами
|
Сообщ.
#83
,
|
|
|
Вот погоди, нейронки выйдут из эмбрионального состояния, и всякоразные Плюсы с Питонами уйдут в нишу автокода.
Добавлено Не мути воду. Ты не такую задачу поставил. В том виде. как ты её поставил: Цитата Fester @ подход Wound не просто правилен, он единственно праведно верный. Ты же сейчас путём волшебных ментальных манипуляций придумал новую задачу: придумать реализующую исходную задачу архитектуру, которую было бы удобно тестить. Ну вот представим, что у тебя есть 2 компоненты: калькулятор и логгер. Все действия калькулятора должны быть запротоколированы. Как должен выглядить идеальный юнит-тест суммы? Добавлено P.S. Прочитал пока только половину темы. |
Сообщ.
#84
,
|
|
|
Цитата Qraizer @ подход Wound не просто правилен, он единственно праведно верный. Это чистой воды Aspect, вряд ли он это мог предложить, так что подходов уже как минимум два а подход назывется no coupling или по народному private responsibility или has a, предложил его кажется кто то из Борланда году в 1993-1994, ох как Я люблю так много умных слов Добавлено Цитата D_KEY @ Осталось понять, как правильно писать интеграционные тесты в C++ Включать здравый смысл, и перестать разводить не нужные теории |
Сообщ.
#85
,
|
|
|
Цитата Qraizer @ И долго еще осталось погождать? Вот погоди, нейронки выйдут из эмбрионального состояния, и всякоразные Плюсы с Питонами уйдут в нишу автокода. |
Сообщ.
#86
,
|
|
|
Цитата applegame @ И ещё особенней, если очень крупный. Оракл вон наособничался, когда читал, волосы даже в интимных местах шевелились. Ну да. Я не против автоматического тестирования вообще, я скорее разочарован в TDD, никак не помогает в конечном итоге, скорее мешает. Особенно если проект не очень крупный. Добавлено Цитата Wound @ Всё просто: тестировать надо всё, что написано в спецификациях. Ничего там не заявленного, тестировать не надо. Вот есть скажем требование что размер формы должен быть 100x200, вполне себе нормальный сценарий, который тоже можно протестировать. Или скажем "в случае неудачного соединения N-раз должно выскакивать окно - "Подключение невозможно, проверьте параметры сети", которое должно располагаться по центру экрана". Вполне себе нормальный сценарий, который тоже можно протестировать. Ага? Добавлено Цитата D_KEY @ Хороший вопрос. Готовый функционал лучше всего покрывается тестами снизу вверх. Пишешь юниты на каждый чих, интеграцией проверяешь их ...э-э-э, интеграцию. Разработка обычно идёт так же, а вот проектирование в обратном направлении. Я лично слабо себе представляю создание тестов без проверки их на реализованном поведении, т.к. при наличии фейла и следовательно для выявления его причины легче разобраться в чёткой логике, описанной формальным языком с формальной грамматикой, чем в его формальном описании на нечётком человеческом с множеством потенциальных неточностей, неоднозначностей и недосказанностей и местами противоречий, что не были замечены на извиняюсь спринтах. Вот начинаем мы какую-то новую штуку кодить по TDD. Мы начинаем же с самых высокоуровневых задач? Т.е. сначала пишем тест на высокоуровневую задачу, верно? Потом, при развитии, проверяемая такими тестами функциональность в любом случае будет раскидана по нескольким юнитам. Так вот вопрос, эти более ранние тесты становятся интеграционными? Ведь у каждого юнита появится свой тест. Добавлено Цитата applegame @ Я чего ты ждёшь-то собсвтенно? Итогов по их спору, что ли?И долго еще осталось погождать? По Wound-у требуется один юнит на интерфейс калькулятора, ещё один на интерфейс логгера и отдельный интегрант на их композицию. Этого достаточно на все случаи жизни. Вообще все. Пока не изменятся спецификации интерфейсов, конечно. Сколько ты не будешь мутить их комбинаций, эти три теста всегда будут к ним применимы, и всегда будут адекватны. Любая отдельная реализация обязана будет проходить эти тесты, без вариантов. Откуда у Fester там взялся зоопарк, я не имею ни малейшего понятия. Понятно, что отдельные реализации каждого из этих интерфейсов могут захотеть по-разному его расширить, и тогда на каждое такое расширение потребуется отдельный юнит, дополняющий, но не заменяющий, обобщённый юнит этого интерфейса. В итоге имеем: один общий юнит на каждый интерфейс, опциональный дополняющий его один частный юнит на каждую его реализацию и один интегрант на их композицию. Всё. Проблема лишь в том, что реализации пасскритериев (именно реализации пасскритериев, а не собственно пасскритерии) для каждой частной реализации общего интерфейса могут отличаться в связи с тесной связью с этой самой реализацией, что затруднит создание обобщённых юнитов. Но это же не проблема, ведь, так? Мы тут прогаммеры или куда? |
Сообщ.
#87
,
|
|
|
Цитата Qraizer @ Я лично слабо себе представляю создание тестов без проверки их на реализованном поведении, т.к. при наличии фейла и следовательно для выявления его причины легче разобраться в чёткой логике, описанной формальным языком с формальной грамматикой, чем в его формальном описании на нечётком человеческом с множеством потенциальных неточностей, неоднозначностей и недосказанностей и местами противоречий, что не были замечены на извиняюсь спринтах. Я попробовал TDD на своем маленьком проекте, пока все очень хорошо пошло. Но я так только несколько часов покодил пару недель назад, забросил пока Надеюсь, что вернусь на неделе к этому, посмотрим, как оно дальше пойдет. Цитата при наличии фейла и следовательно для выявления его причины легче разобраться в чёткой логике, описанной формальным языком с формальной грамматикой, чем в его формальном описании на нечётком человеческом с множеством потенциальных неточностей, неоднозначностей и недосказанностей и местами противоречий, что не были замечены на извиняюсь спринтах. Мы, кстати, на работе сейчас пробуем BDD подход, к user story сразу пишем BDD-сценарии, которые потом используем в автотестах для стори. Вроде хорошо пошло. Это так же помогает и в процессе PBR (на грумингах и не только). Попробуем несколько спринтов, потом решим, будет ли с этим жить. |
Сообщ.
#88
,
|
|
|
Цитата Qraizer @ Я жду когдаЯ чего ты ждёшь-то собсвтенно? Цитата Qraizer @ Ты же сказал "погоди", вот я и спрашиваю долго ли еще погоджать? нейронки выйдут из эмбрионального состояния, и всякоразные Плюсы с Питонами уйдут в нишу автокода. |