(пули свистели над головой!) LCR>Ты прав, и это не противоречит моим словам — в длительной перспективе тесты необходимы. Я же говорил о
... о срочных проектах.
Здравствуйте, GlebZ, Вы писали:
GZ>Когда-то я два дня потратил на поиск ошибки в релизе. Оказалось, одна нужная функция выполнялась в рамках ASSERT. После этого поклялся более акуратно относиться к ASSERT и стараться не выполнять функции в оных. ASSERT создает разницу функционирования debug и release версии. Это не есть good.
Этой ошибке сто лет в обед. Просто нужно пользоваться VERIFY
... << RSDN@Home 1.2.0 alpha rev. 655>>
It is always bad to give advices, but you will be never forgiven for a good one.
Oscar Wilde
Здравствуйте, ekamaloff, Вы писали:
E>Этой ошибке сто лет в обед. Просто нужно пользоваться VERIFY
Ага. И поставлять всю байду с тестированием клиенту?
Здравствуйте, GlebZ, Вы писали:
GZ>Здравствуйте, ekamaloff, Вы писали:
E>>Этой ошибке сто лет в обед. Просто нужно пользоваться VERIFY GZ>Ага. И поставлять всю байду с тестированием клиенту?
Какую байду с тестированием? VERIFY из релиза выкидывается, а вычисление подскобочного выражения остается
... << RSDN@Home 1.2.0 alpha rev. 655>>
It is always bad to give advices, but you will be never forgiven for a good one.
Oscar Wilde
Здравствуйте, GlebZ, Вы писали:
GZ>Здравствуйте, minorlogic, Вы писали:
M>>Поясните плиз , что имелось ввиду ? GZ>Когда-то я два дня потратил на поиск ошибки в релизе. Оказалось, одна нужная функция выполнялась в рамках ASSERT. После этого поклялся более акуратно относиться к ASSERT и стараться не выполнять функции в оных. ASSERT создает разницу функционирования debug и release версии. Это не есть good.
Ну можно и не такое написать ... ASSERT то сам не виноват ? правда ?
"ASSERT создает разницу функционирования debug и release версии. Это не есть good" — это и есть самое главное преимущество в ASSERT. В отладочной сборке он проверяет условия , но в релизной не тратит на это ресурсов.
То есть , любой инструмент надо УМЕТЬ использовать
Здравствуйте, minorlogic, Вы писали:
M>В итоге получается ТОТ же самый юнит тест , но уже ВНЕДРЕННЫЙ в код , со всеми вытекающими преимуществами.
Только при том условии, что будет еще человек, который запустит код и пройдет по всем нужным ветвям развится в программе. А если он забудет некую ветвь правильно протыкать или введет не те данные, в некотором месте, то ассерты ничего не выявят просто потому, что до них не дойдет выполнение программы. Еще более важно — сколько времени человек затратит на это самое воспроизведение азных сиуаций.
В случае юнит-тестов нажимается одна(!) кнопка и все тесты побежали на выполнение. При этом можно быть уверенным, что по всем входным данным, заложенные в этих тестах — проверки выполенны.
З.Ы. никто не мешает ставить в код ассеры и инварианты, просто это все же совсем другая вещь, нежели юнит-тесты.
Здравствуйте, vvaizh, Вы писали:
V>На самом деле проблема самих unit-тестов в том, что они тестируют совсем не то что тестирует заказчик.. V>заказчик тестирует полное приложение, а unit тесты тут как раз лажают.. V>нужны именно функциональные тесты.. минимум..
На самом деле у них просто другая область применения. Юнит-тесты — это помощь программисту, для более быстрого обнаружения и локализации ошибок.
А функциональные тесты тоже нужны — дл ятестирования системы в целом, это да.
Здравствуйте, Lazy Cjow Rhrr, Вы писали:
LCR>GlebZ,
LCR>>>1. Писать ЮТ — рутина. GZ>>По разному. Если у тебя на выходе xml полученный с эталонной базы данных, и ты его должен проверить по нескольким параметрам, то тут уже меньше рутины и больше творчества. По таким тестам и рефакторинг проводится. К тому же у тестов есть дополнительный бонус: он показывает/уточняет разработчику — что же должна делать его функциональность в данном конкретном месте.
LCR>Тебе не трудно будет привести примерчик, что за параметры и что за xml. Хотя бы с высоты птичьего полёта?
необязательно xml
достаточно просто уметь получить результат запроса к базе данных в виде текста
например так:
Cyberax,
>> C>Не знаю, по моему опыту юниттестирования — они как раз помогают писать >> быстрее. >> В /длительной/ перспективе — охотно верю, даже вижу подтверждение этому >> собственными глазами. Но когда каждый день на счету — трата времени, ибо >> есть более приоритетные задачи. C>Это скорее задача менеджмента проекта.
Задача нашего менеджмента — влезть в уже закрывающуюся дверь лифта, который доставит их к заказчику. Я писал об этом в исходном сообщении.
>>> > *2. Написание ЮТ отнимает значительное время и требует внимания.* >>> > Этот факт в основном действует как красная тряпка, отвлекая от важных >>> > дел. >> C>А отладка кода занимает еще больше. >> Упс, обоснуй, пожалуйста: Почему наличие юнит-тестов значительно >> уменьшает время на отладку? C>Большинство багов, на которые тратится много времени, возникают когда C>изменение в одном модуле ломают что-то в другом. Без unit-тестов это C>обнаружится только когда функциональность другого модуля все-таки вызовут.
Её и так вызывают. Явно. Мышкой. Запуск ради этого и делается.
C>Unit-тесты тут замечательно помогают — ты очень точно можешь отловить C>момент когда что-то сломалось. Соответственно, ты еще помнишь что только C>что изменял и обычно легко можешь найти багу.
C>Ну и уже написанные unit-тесты при изменении существующего кода C>(добавлении оптимизации, например) позволяют проверить большое C>количество частных случаев.
C>По опыту, время на отладку заметно уменьшается. Я даже для эксперимента C>решил использовать ViM вместо Студии, так как отладчик стал менее важен. C>Проект, кстати, на С++ (это про статическую типизацию).
Уфф. Мне до сих пор неочевидно, что создание юнит-тестов + отладка для срочных проектов будет занимать меньше времени, чем просто отладка. Либо ты чего-то не договариваешь, либо что-то не так
Как должен выглядеть процесс разработки? TDD? XP?
>> C>Вот это как раз достаточно легко побеждается — надо просто помнить, что >> C>нам нужно тестировать не приложение, а код. То есть вместо значений из >> C>конфига ему можно подсунуть захардкоденные строки. >> И умереть при формировании этих захардкоденных строк... C>Ну зачем же так, надо просто написать тулзу, которая делает слепок C>текущей конфигурации. C>Есть куча инструментов: C>http://mockcreator.sourceforge.net/ C>http://www.mockobjects.com/ C>и т.п. >> Тогда юнит-тестирование >> превращается просто в ад: создать мок-объекты к очень даже не тоненьким >> фреймворками, а потом создать юнит-тесты. В данной ситуации это неприемлемо. C>Для фреймворков есть еще такой метод — создаешь ситуацию для test-case'а C>руками (допустим, сделав некоторые действия в IDE), и все еще во время C>работы приложения вызываешь тестовую функцию. С помощью специального C>mockcreator'а отслеживается какие данные используются тестовой функцией C>и делается их статический слепок.
Ммм. Всё это очень трудоёмко и нужно разбираться с ними. Хотя спасибо за информацию.
Lazy Cjow Rhrr wrote: > Какого х**? Почему он лезет в inet и качает кучу всего, когда оно уже > есть в локальном каталоге. Начинаются раскопки...
Написано же в доке — работает с репозиториями зависимостей Дальше
раскопки сразу должны показать на дефолтный репозиторий ibiblio.
Здравствуйте, fmiracle, Вы писали:
F>Здравствуйте, vvaizh, Вы писали:
V>>На самом деле проблема самих unit-тестов в том, что они тестируют совсем не то что тестирует заказчик.. V>>заказчик тестирует полное приложение, а unit тесты тут как раз лажают.. V>>нужны именно функциональные тесты.. минимум..
F>На самом деле у них просто другая область применения. Юнит-тесты — это помощь программисту, для более быстрого обнаружения и локализации ошибок.
F>А функциональные тесты тоже нужны — дл ятестирования системы в целом, это да.
проблема в том, что нет единого и стандартного средства позволяющего плавно переходить от одного к другому..
а ведь нужно как..
1. заказчик заказал определённый функционал
2. пользователь быстро его реализовал выкатив первую версию и минимальное количество тестов для
неё (чтобы просто показать что всё функционирует как задумано)
3. заказчик начал тестировать глубже, находить что то новое или просто требовать небольшие новые фишки
4. дописываются тесты на эти случаи/рефакторинги, при этом используются функ тесты предыдущих итераций,
при необходимости для вещей которые наиболее часто затрагиваются прописываются свои юнит-тесты, которые должны
в той же среде по идее бегать
это — если времени не хватает, нужна скорость разработки..
Lazy Cjow Rhrr wrote: > A> Отсюда и рождается болезненное восприятие изменения этого кода, > потому как неизвестно как себя поведёт этот код при банальных изменениях > в нём, а уж о сложных и говорить нечего, а тесты позволяют видеть как > ведёт себя код при изменениях. > Свежий код меняется достаточно легко — мы его только что написали и > помним все трещинки.
Как раз большая часть ошибок происходит из-за того, что свежий код
ломает другой код. Юнит-тесты как раз повзоляют это выловить и по
горячим следам тут же исправить.
fmiracle wrote: > З.Ы. никто не мешает ставить в код ассеры и инварианты, просто это все > же совсем другая вещь, нежели юнит-тесты.
Более того, verify и assert'ы замечательно дополняют юнит-тесты, так как
сработавший в unit-test'е assert сразу дает причину и место ошибки.
LCR>Короче, такая недружественная практика по отношению к программистам при этом вполне себя оправдывает: продукт в рекордные сроки поставляются клиентам, клиенты кивают головой увидев что нужно, конкуренты курят бамбук. И только программисты слегка оправившись от пережитого "ужоса" понимают, что "ужос" скоро будет опять (очередная порция хотелок), поэтому надо взять рефакторинг и хотя бы причесать код. Опыт показывает, что код, написанный на большой скорости просто ужасен (низкий уровень обобщения, невнятные соглашения, большая избыточность, сильное сцепление), поэтому рефакторить надо.
А вот как раз когда рефакторить надо ЮТ рулят просто неимоверно.
Ситуация из собственного опыта. 4 человека разрабатывают проект. И тут в один прекрасный момент заказчик вспомниает, что через 1,5 недели у него важнейшая выставка, к которой 10(условно) мегафич должны быть готовы. А по плану те же самые 10 мегафич должны быть готовы не ранее чем через 2 месяца. Попытки воззвать к здравому смыслу заказчика не увенчались успехом. И вот начинается "ужос" . 12-14 часовой рабочий день, код колбасится так, что чуть ли дым из клавиатуры не идет . Путем неимоверных усилий функционал таки готов к сроку. Выставка проходит более менее успешно. Естественно появились новые хотелки. Но надо ж сделать рефакториг... Все в команде в принципе с этим согласны. Но как же его сделать ? Проект за полторы недели расколбасного писания превратился в конструкцию весьма похожую на дом из знаменитой истории "Если бы программисты строили дома". При малейшем изменении приходится пробегать по всем веткам приложения, потому что вылететь может что угодно и где угодно. Попытка рефакторинга после таких авралов очень напоминает хождение по высоко натянутому канату с закрытыми глазами. А сроки сдачи те же. Время идет. Функционала нового не добавляется. Да и результатов от рефакторинга особо не видно. Потому что ехать на машине и шагать по канату с закрытыми глазами с одинаковой скоростью сложно. Следующий майлостоун был просрочен на 2 недели. После этого начали писать юнит тесты. Но это не скзака, поэтому рассказов о том что срзау все заработало и стало перкрасным благодаря юнит тестам не будет. Отнюдь. Были свои приколы когда Mock объекты не совсем корректно реализовывали функционал тех вещей, которые они эмулировали, было потрачено время на то чтобы понять как правильно писать юнит тесты, и где они нужны реально, а где их написание не приносит ощутимых доходов. Тем не менее, после внедрения ЮТ при мысле о рефакторинге на лицах команды нет выражения как при сильной зубной или головной боли. ЮТ не панацея, но в death march проектах, их применение оправдано, и дает реальные плоды.
LCR>Ладно, с условиями разобрались. Теперь перечислим факты о ЮТ, которые играют роль, но о которых не очень охотно говорят.
LCR>1. Писать ЮТ — рутина. LCR>На мой взгляд единственный элемент творчества здесь — это строковая константа.
Такие тесты как и было замечено пишутся практически на автомате. Плюс VS 2005 умеет генерировтаь обертки для юнит тестов. Но при ручном написании таких тестов доволно часто возникает соблазн написать именно такие слова
LCR> Вывод: никто кроме самого программиста нормальные тесты не сделает.
Воистину. Тесты пишет тот же человек, что и код.
LCR>Написание обобщённого кода вызывает ощутимый оверхед, такой, что проще забить на это дело и не парить моск. Для тех, кто сомневается: представьте например, два больших, почти идентичных класса LCR>Как избавиться от дублирования? (Это очень даже реальный пример, два увесистых классика имели всего 43 диффа, дублирование мозолило глаз, но альтернативы? — плодить 43 оператора if, или ещё минимум 3 не самых простеньких класса. Плиз!).
Альтернативы как известно всегда есть . Могу работать, а могу и не работать (с).
Да, бывают такие ситуации. И никуда от них не деться.
LCR>2. Написание ЮТ отнимает значительное время и требует внимания. LCR>Этот факт в основном действует как красная тряпка, отвлекая от важных дел. Отвлекать от важных дел он перестанет только когда оно само (написание ЮТ) будет важным делом.
Достаточно 2-3 раза пережить такие этапы как вышеописанный, и наступает понимание что написание ЮТ все-таки важное дело. Может менее важное чем архитектура, но тем не менее важное.
LCR> Тремя словами это будет так: "worse is better".
Адепты TDD утверждают, что разработка идеть в 3 этапа red, green, refactor.
на красном, мы имеем нес рабатывающий тест, на зеленом мы имеем срабатывающий тест, а на рефакторе мы убираем из кода все лишнее. Итого имеем Simplicity И (относительную)Correctness. Принцип worse is better не нарушается
LCR> Хотя очевидно, что это соотношение существует (на мой взгляд процент должен зависеть от типа проекта; чем проект дольше — тем меньше процент, а абсолютная величина больше), и доля тестов весьма ощутима.
+1 Абсолютно согласен
LCR>Плюс необходимость переключать внимание с ЮТ на код и обратно — это разбрасывать шары, а потом их снова скрупулёзно собирать... (неплохая аналогия тов. Спольски). Как минимум — некомфортно. Фактически — расход заметного времени именно на переключение (общеизвестная статистика — вхождение "в поток" съедает 15 минут, умножаем это время на количество прерываний=переключений...).
За всех говорить не буду, но у меня написание класса и юнит тестов находится в одном "потоке". Это не отвлекает, а наоборот, ты предстваляешь КАК будет использоваться то что ты пишешь, и когда тесты написаны, ты знаешь что в большинстве случаев твой код будет работать правильно. А это как минимум приятно. А вот когда вылетает непонятный иксепшен, из-за банального обращения к элементу массива с нумером -1, то это может очень здорово выбить из потока. Повторюсь, речь идет обо мне
LCR>3. Проверять код взаимодействующий с окружением скорее всего не имеет смысла.Такой код часто имеет следующую особенность: он работает только при грамотной конфигурации, наличия нужных джарок в нужных директориях, правильных переменных окружения и т.п. Примеров куча: деплоймент дескрипторы, plugin.xml, web.xml, struts-config.xml, yan.xml и так далее. Часто ошибки именно в неправильной конфигурации.
LCR>Так вот, чтобы протестировать код, нужно написать правильный конфиг, ну а дальше вы поняли... Рекурсия, как всегда, божественна.
В таких случаях используются Mock объекты. Что-то типа "Если все поднимется правильно, то на вызов метода X с параметрами Y окружение должно ответить Z". Но иногда оказывается что реально окружение отвечает AAAA. Тогда возникают проблемы
LCR>В данном случае уже работает выбор худшего из двух зол. Что хуже: ошибка в архитектуре или ошибка в работе метода? Я думаю, что как правило первое хуже.
+1 ЮТ не значить "забить на архитектуру".
LCR>Вдобавок, если юнит-тесты будут, то не будет (или будет в недостаточном количестве) чего-то другого. Как всегда, бесплатный сыр соблазнительно качается на пружинке...
Не будет длительной отладки ? (шутка). На самом деле ты прав. Во всем важен баланс. Способсвует ли отсуствие или наличие ЮТ соблюдению баланса каждый отвечает сам. Ситуации они разные бывают.
LCR>5. Статическая типизация в сочетании с IDE работает удовлетворительно и без тестов.
+1 Но статическая типизация в сочетании с ИДЕ и с юнит тестами работает лучше чем удовлетворительно.
LCR>В одном предложении: вопрос написания ЮТ — это вопрос расстановки приоритетов.
+1
LCR> И так как итоговый результат получается удовлетворительный, то юнит-тесты выпадают из рассмотрения.
ЕСЛИ итоговый результат получается удовлетворительный.
LCR>Возможно такие быстрые проекты нужно писать на других языках (ФЯ или тех же динамических) или другим способом (XP, TDD), но без обкатки это большой риск.
+1
LCR>Чем в данных условиях могут помочь юнит-тесты?
Лично мне очень помогают при рефакторинге. Который неизбежен.
LCR> умные сволочи вроде Эккеля, Фаулера и Бека что "если юнит-тестов нет, то программа не работает",
Скорее всего перегибают палкую для сферической программы в вакууме это скорее всего справедливо.
Итог.
Я виже пользу в юнит тестах исключительно когда нужен рефакторинг. Это помогает сразу же увидеть сломал ты что-то или нет. Особенно это полезно когда в команду приходит новый человек.
Cyberax,
>> Какого х**? Почему он лезет в inet и качает кучу всего, когда оно уже >> есть в локальном каталоге. Начинаются раскопки... C>Написано же в доке — работает с репозиториями зависимостей Дальше C>раскопки сразу должны показать на дефолтный репозиторий ibiblio.
Воот. Я должен буду заглянуть в доку и т.п.
В данном случае может быть всё просто и ноги найдутся через 5 минут. Но можешь ли ты утверждать это для любой библиотеки? Для любой ошибки или любого затруднения? Можешь ли ты утверждать, что переезд с любой библиотеки на другую аналогичную произойдёт легко и безболезненно?
Мы, наученные горьким опытом, стараемся держаться в русле и использовать пользующиеся вниманием и проверенные фреймворки/библиотеки. Много шагов в сторону означает увеличение риска. В частности, Spring выглядит многообещающе, и вроде развивается давно, но мы не используем его. Никто ещё не нашёл возможности и желания попробовать его "на зубок" в фоновом режиме...
Здравствуйте, Lazy Cjow Rhrr, Вы писали:
LCR>Вопрос на засыпку: кто и когда будет изучать "подходящий инструмент"? Когда этот "подходящий инструмент" будет обкатываться?
А кабы знать!
Это вообще вопрос, на который я пока не слышал вразумительного ответа: "Как изучать что-нибудь новое, когда работой завален по горло?"
Я знаю только один способ: изыскивать время (см. например Сделай это сейчас
) и терпеть. Еще хорошо, когда в команде есть подвинутый на изучении чего-нибудь нового человек (мне как-то повезло в с таким работать). Можно еще вспомнить Брукса с его организацией работы, когда в команде есть отвечающий за инструменты программист.
LCR>Как говорят на востоке: "Самая короткая дорога — та, которую знаешь".
А лучше всего знаешь ту дорогу, которую сам и проложил, поэтому велосипеды рулят!
LCR>(Или я не понял о каком тестировании и инструменте речь).
Здесь можно провести аналогию с языками высокого или низкого уровня. Для того, чтобы открыть файл, прочитать его построчно и выбрать что-то подходящее, на разных языках придется писать разный объем кода. На ассемблере очень много. На C++ гораздо поменьше. На Ruby еще меньше. А если есть возможность запустить grep, то вообще одну строку. Соответственно время решения этой задачи в зависимости от имеющегося в наличии инструмента будет отличаться на порядки.
Если в условиях цейтнота выясняется, что писать приходится слишком много, то очень возможно, что используемый инструмент слишком низкоуровневый для конкретной задачи. Имхо, такие вещи происходят сплошь и рядом, когда берется какой-нибудь универсальный инструмент, а затем на нем в лоб пытаются решать свою проблему. Хотя, очень возможно, задача решилось бы гораздо быстрее, если бы над универсальным инструментом была создана узкозаточенная надстройка. И именно на ее основе создавался бы прикладной код.
Опять буду не скромным и приведу примеры из собственного опыта. Года четыре назад, когда мы только начинали работать с SMPP-транспортом нам приходилось время от времени в очень сжатые сроки обеспечивать поддержку различных SMS-акций (голосования, викторины), да и различные демонстрации наших продуктов к какому-нибудь приезду высоких гостей-заказчиков так же. Имея голую реализацию SMPP-протокола поверх голого же TCP/IP делать это было не очень просто, поскольку кроме прикладной логики нужно было заниматься как деталями TCP/IP взаимодействия, так и деталями SMPP-протокола (в частности, отслеживать времена отсутствия активности и обмениваться периодическими пингами). Ситуация кардинально изменилась, когда над поддержкой SMPP-протокола был выстроен дополнительный логический слой, предоставляющий совсем другую функциональность. Прикладную логику стало возможно программировать с использованием высокоуровневых понятий receive/send, не заботясь о том, во что это выливается в SMPP и в TCP/IP. При этом, однако, была потеряна некоторая степень гибкости в управлении низкоуровневыми деталями протокола, но зато существенно возрасла скорость разработки прикладных решений.
Еще один пример. Я занимаюсь разработкой распределенных приложений на SObjectizer, в которых отдельные модули могут располагаться как в рамках одного процесса, так и в разных процессах. Если модули разносятся по разным процессам, то приходится эти процессы соединять между собой TCP/IP соединениями. При использовании голого SOP в SObjectizer это не представляет проблемы, однако является довольно трудоемкой. В частности, приходится решать две задачи: контроль каналов, через которые должен идти peer-to-peer обмен сообщениями между модулями (т.е. при разрыве и переустановлении TCP/IP соединения имена каналов меняются и их нужно запоминать) и организация этих каналов в процессе при старте. Первая задача разрешилась путем добавления специальной подсистемы над SOP (называемой message box api, чем-то напоминающем message oriented middleware) благодоря которой модулям больше не требуется знать про коммуникационные каналы вообще. Вторая разрешилась посредством создания специальной библиотеки, которая подключается к процессу и берет из конфигурационного файла список нужных подключений и создает для них нужное количество коммуникационных каналов с нужными параметрами. А приложения при таком подходе строятся из DLL-ек как из конструктора (хотя ты подобные вещи знаешь по EJB контейнерам).
Когда приложение собирается из DLL-ек как из конструктора возникает проблема правильного конфигурирования, ведь тогда сложность перемещается в правильность конфигурационных файлов (об этом ты так же говорил). И, если править эти файлы ручками, то можно потратить много времени на устранение последствий глупых ошибок. Но здесь над конфигами можно сделать еще одну собственную прослойку: генератор конфигурационных файлов заточенный под конкретный тип приложения. Например, Ruby-новый DSL, который знает, как преобразовать описания в набор конфигов.
В общем, есть очень тонкий момент, в который можно понять, что обычный способ использования какого-то инструмента оказывается слишком дорогостоящим. В этот момент можно что-то сделать (например, какой-то собственный велосипедик) чтобы упростить использование инструмента для какого-то типа задач. (Существует мнение, что RubyOnRails как раз стал популярным из-за того, что он как раз и является велосипедом для очень ограниченного класса Web-приложений, но зато очень удобным).
Вот как-то так.
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Lazy Cjow Rhrr wrote: > C>Это скорее задача менеджмента проекта. > Задача нашего менеджмента — влезть в уже закрывающуюся дверь лифта, > который доставит их к заказчику. Я писал об этом в исходном сообщении.
Даже в это ситуации трезвый подход и распланированное написание тестов
могут сократить время.
> C>Большинство багов, на которые тратится много времени, возникают когда > C>изменение в одном модуле ломают что-то в другом. Без unit-тестов это > C>обнаружится только когда функциональность другого модуля все-таки вызовут. > Её и так вызывают. Явно. Мышкой. Запуск ради этого и делается.
Э, нет.
К примеру, реальная ситуация из все того же проекта: я добавил функцию
IMPORT_MODULE и сделал так, что создание корневого модуля сделано как
импорт пустого модуля. Проверил, это нормально работает.
Запустил тесты — и сразу увидел ошибку. В stacktrace появилось новое звено:
somefile.jam:17 in module ('_ROOT_') scope
somefile.jam:17 in module ('_ROOT_') scope
another.jam:223 in module ('test') scope
...
Ошибка возникла из-за того, что раньше корневой модуль при выводе
stacktrace'а обрабатывался специальным образом.
Без тестов ты эту ошибку можешь заметить намного позже и ее отладка и
исправление может занять больше времени.
> C>По опыту, время на отладку заметно уменьшается. Я даже для эксперимента > C>решил использовать ViM вместо Студии, так как отладчик стал менее важен. > C>Проект, кстати, на С++ (это про статическую типизацию). > Уфф. Мне до сих пор неочевидно, что /создание юнит-тестов + отладка/ для > срочных проектов будет занимать меньше времени, чем /просто отладка/.
Если срочный проект поддается тестированию (не всегда так бывает), то
вполне возможно. В моей практике тесты значительно сокращают время отладки.
> Как должен выглядеть процесс разработки? TDD? XP?
Да хоть RUP. Можно просто рассматривать тесты как один из рабочих
инструментов.
> C>Для фреймворков есть еще такой метод — создаешь ситуацию для test-case'а > C>руками (допустим, сделав некоторые действия в IDE), и все еще во время > C>работы приложения вызываешь тестовую функцию. С помощью специального > C>mockcreator'а отслеживается какие данные используются тестовой функцией > C>и делается их статический слепок. > Ммм. Всё это очень трудоёмко и нужно разбираться с ними. Хотя спасибо за > информацию.
Угу, некоторые mockobject'овые тулзы так и работают.
Здравствуйте, minorlogic, Вы писали:
M>Ну можно и не такое написать ... ASSERT то сам не виноват ? правда ?
А тож.
M>"ASSERT создает разницу функционирования debug и release версии. Это не есть good" — это и есть самое главное преимущество в ASSERT. В отладочной сборке он проверяет условия , но в релизной не тратит на это ресурсов.
Проверяет условия — это конечно хорошо. Но это не юнит тестирование, поскольку в юнит тестировании:
1. Проверяется корректность результатов функции при определенных входных параметрах. И проверяет он явно, показывая что данная функция, с такими параметрами не может работать, а вот с такими на ура.
2. Все проверки вынесены за пределы релизного функционала, и никак не влияют на функционирования самой функции. Нужно захотеть, чтобы перевести систему в состояние, неравнозначное исходному. В случае ASSERT такое возможно неявно.
3. В случае ассерт — мы можем тестировать только те пути, что выполняет тестер. А тестеры обычно не выполняют не все пути исполнения. Хорошо если они хотя бы выполнят функциональные тесты согласно требованиям. Иногда и даже этого не делают. Либо делают до того, как в проект были внесены ошибки.
M>То есть , любой инструмент надо УМЕТЬ использовать
Но это не есть unit тестирование. Максимум что я использую в ассертах — проверка простых переменных в особых случаях.
Здравствуйте, ekamaloff, Вы писали:
E>Какую байду с тестированием? VERIFY из релиза выкидывается, а вычисление подскобочного выражения остается
К тебе приходит результат функции в виде структуры с 3 полями. Ты их хочешь проверить. Ты будешь поднимать VERIFY?