Я задаю этот вопрос относительно проблем, с которыми я столкнулся во время проектов TDD. Я заметил следующие проблемы при создании модульных тестов.
- Генерация и ведение фиктивных данных
Поддерживать большие фиктивные данные сложно и нереально. Еще сложнее, когда структура базы данных претерпевает изменения.
- Тестирование GUI
Даже с MVVM и способностью тестировать GUI, для воспроизведения сценария GUI требуется много кода.
- Тестирование бизнеса
У меня есть опыт, что TDD работает хорошо, если вы ограничиваете его простой бизнес-логикой. Однако сложную бизнес-логику сложно протестировать, поскольку число комбинаций тестов (тестовое пространство) очень велико.
- Противоречие в требованиях
На самом деле сложно учесть все требования при анализе и проектировании. Много раз требования одной записки приводят к противоречию, потому что проект сложен. Противоречие найдено поздно в стадии реализации. TDD требует, чтобы требования были на 100% правильными. В таких случаях можно ожидать, что конфликтующие требования будут учтены при создании тестов. Но проблема в том, что это не так в сложных сценариях.
Я прочитал этот вопрос: почему TDD работает?
Действительно ли TDD работает для сложных корпоративных проектов или практически ограничено типом проекта?
Ответы:
Ложь.
Модульное тестирование не требует «больших» фиктивных данных. Требуется достаточно ложных данных для проверки сценариев и ничего более.
Кроме того, по-настоящему ленивые программисты просят специалистов по предметам создавать простые таблицы различных тестовых случаев. Просто простая таблица.
Затем ленивый программист пишет простой скрипт для преобразования строк электронной таблицы в случаи модульного тестирования. Это довольно просто, правда.
Когда продукт развивается, электронные таблицы тестовых случаев обновляются и генерируются новые модульные тесты. Делай это все время. Это действительно работает.
Какая? «ВОПРОИЗВЕДЕНИЕ»?
Смысл TDD в том, чтобы спроектировать вещи для тестируемости (Test Drive Development). Если графический интерфейс настолько сложен, то он должен быть переработан, чтобы быть более простым и более тестируемым. Упрощение также означает более быструю, более легкую в обслуживании и более гибкую. Но в основном проще будет означать больше тестируемых.
Это может быть правдой.
Тем не менее, просьба к экспертам в данной области предоставить основные тестовые примеры в простой форме (например, в электронной таблице) действительно помогает.
Таблицы могут стать довольно большими. Но это нормально, так как я использовал простой скрипт на Python, чтобы превратить электронные таблицы в тестовые случаи.
А также. Мне пришлось написать несколько тестов вручную, потому что таблицы были неполными.
Тем не мение. Когда пользователи сообщали об «ошибках», я просто спрашивал, какой контрольный пример в электронной таблице был неправильным.
В этот момент эксперты в данной области либо исправят электронную таблицу, либо добавят примеры для объяснения того, что должно было произойти. Отчеты об ошибках - во многих случаях - могут быть четко определены как проблемы тестового примера. Действительно, исходя из моего опыта, определение ошибки как неработающего тестового примера значительно упрощает обсуждение.
Вместо того, чтобы слушать экспертов, пытающихся объяснить сверхсложный бизнес-процесс, эксперты должны привести конкретные примеры этого процесса.
Неиспользование TDD требует, чтобы требования были на 100% правильными. Некоторые утверждают, что TDD может терпеть неполные и изменяющиеся требования, когда подход без TDD не может работать с неполными требованиями.
Если вы не используете TDD, противоречие обнаруживается на поздней стадии реализации.
Если вы используете TDD, противоречие обнаруживается ранее, когда код проходит некоторые тесты и не проходит другие тесты. Действительно, TDD дает вам доказательство противоречия в начале процесса, задолго до реализации (и аргументы во время приемочного тестирования пользователя).
У вас есть код, который проходит одни тесты, а другие не проходит. Вы смотрите только на эти тесты, и вы обнаружите противоречие. Это работает очень, очень хорошо на практике, потому что теперь пользователям приходится спорить о противоречии и приводить последовательные, конкретные примеры желаемого поведения.
источник
да
Моим первым знакомством с TDD была работа над компонентами промежуточного программного обеспечения для мобильного телефона на базе Linux. Это в конечном итоге привело к тому, что миллионы строк исходного кода, в свою очередь, потребовали около 9 гигабайт исходного кода для различных компонентов с открытым исходным кодом.
Предполагалось, что все авторы компонентов предложат как API, так и набор модульных тестов, а также проведут их проверку в экспертной комиссии. Никто не ожидал совершенства в тестировании, но все общедоступные функции должны были иметь хотя бы один тест, и после того, как компонент был передан в систему контроля версий, все модульные тесты должны были всегда проходить (даже если они это делали, потому что компонент ложно сообщал все работало нормально).
Без сомнения, по крайней мере частично из-за TDD и настойчивого требования, что все модульные тесты всегда проходят, релиз 1.0 пришел рано, в рамках бюджета и с удивительной стабильностью.
После выпуска 1.0, поскольку корпоративные компании хотели иметь возможность быстро менять область действия из-за требований клиентов, они сказали нам прекратить заниматься TDD и отменили требование о прохождении модульных тестов. Было удивительно, как быстро качество пошло в унитаз, а затем график следовал за ним.
источник
removed the requirement that unit tests pass. It was astonishing how quickly quality went down the toilet, and then the schedule followed it.
- это все равно, что сказать своему гонщику Формулы 1, что ему запрещены «Пит-стопы», потому что это занимает слишком много времени…Я бы сказал, что чем сложнее проект, тем больше пользы вы получаете от TDD. Основными преимуществами являются побочные эффекты того, как TDD заставит вас писать код гораздо меньшими, гораздо более независимыми частями. Ключевые преимущества:
а) Вы получаете намного более раннюю проверку вашего проекта, потому что ваша петля обратной связи намного труднее из-за тестов с самого начала.
б) Вы можете изменить кусочки и посмотреть, как система отреагирует, потому что вы все время создавали стеганое тестовое покрытие.
в) Готовый код будет намного лучше в результате.
источник
Действительно ли TDD работает для сложных проектов?
Да. Не каждый проект, как мне говорят, хорошо работает с TDD, но большинство бизнес-приложений хороши, и я держу пари, что те, которые не работают хорошо, когда они написаны чисто TDD-способом, могут быть написаны ATDD без особых проблем.
Генерирование и поддержка фиктивных данных
Держите его небольшим и получите только то, что вам нужно, и это не страшная проблема, как кажется. Не поймите меня неправильно, это боль. Но это того стоит.
Тестирование графического интерфейса пользователя
Проверьте MVVM и убедитесь, что его можно протестировать без представления. Я нашел это не сложнее, чем тестирование любой другой части бизнес-логики. Тестирование представления в коде, которое я не делаю, однако все, что вы тестируете на этом этапе, - это логика связывания, которая, как мы надеемся, будет быстро обнаружена, когда вы выполните быстрый ручной тест.
Тестирование бизнеса
Не найдено проблем. Много маленьких тестов. Как я уже говорил выше, некоторые случаи (решатели головоломок Судоку, кажется, популярны), по-видимому, трудно сделать TDD.
TDD требует, чтобы требования были на 100% правильными.
Нет, это не так. Откуда вы взяли эту идею? Все Agile-практики признают, что требования меняются. Вам нужно знать, что вы делаете, прежде чем делать это, но это не то же самое, что требование к 100%. TDD является обычной практикой в Scrum, где требования (пользовательские истории), по определению, не выполнены на 100%.
источник
Во-первых, я полагаю, что ваша проблема больше связана с модульным тестированием в целом, чем с TDD, поскольку я не вижу ничего действительно относящегося к TDD (цикл «сначала тест + красный-зеленый-рефактор») в том, что вы говорите.
Что вы подразумеваете под фиктивными данными? Предполагается, что макет содержит только какие-либо данные, то есть никакие поля, кроме одного или двух, необходимых в тесте, и никаких зависимостей, кроме тестируемой системы. Настройка фиктивного ожидания или возвращаемого значения может быть выполнена в одну строку, так что ничего страшного.
Если вы имеете в виду, что база данных претерпевает изменения без внесения надлежащих изменений в объектную модель, хорошо тестовые модули именно здесь, чтобы предупредить вас об этом. В противном случае изменения в модели должны быть отражены в модульных тестах, но с указанием компиляции это легко сделать.
Вы правы, модульное тестирование GUI (View) не легко, и многие люди чувствуют себя хорошо без него (кроме того, тестирование GUI не является частью TDD). Напротив, модульное тестирование вашего Controller / Presenter / ViewModel / любого промежуточного уровня настоятельно рекомендуется, на самом деле это одна из основных причин, по которой используются такие шаблоны, как MVC или MVVM.
Если ваша бизнес-логика сложна, это нормально, что ваши модульные тесты сложно спроектировать. Вы должны сделать их как можно более атомарными, каждый из которых проверяет только одну ответственность за тестируемый объект. Модульные тесты тем более необходимы в сложной среде, поскольку они обеспечивают сеть безопасности, гарантирующую, что вы не нарушите бизнес-правила или требования при внесении изменений в код.
Точно нет. Успешное программное обеспечение требует, чтобы требования были на 100% правильными;) Юнит-тесты просто отражают ваше видение требований в настоящее время; если видение ошибочно, ваш код и ваше программное обеспечение тоже будут, модульные тесты или нет ... И именно здесь блеска модульных тестов: с достаточно явными названиями тестов ваши проектные решения и интерпретация требований становятся прозрачными, что облегчает указывать ваш палец на то, что должно быть изменено в следующий раз, когда ваш клиент говорит: «это бизнес-правило не совсем то, что я хотел бы».
источник
Я должен смеяться, когда слышу, как кто-то жалуется, что причина, по которой он не может использовать TDD для тестирования своего приложения, заключается в том, что его приложение настолько сложное. Какая альтернатива? Есть ли тестовые обезьяны, стучащие по акрам клавиатур? Пусть пользователи будут тестерами? Что еще? Конечно это сложно и сложно. Как вы думаете, Intel не тестирует свои чипы, пока они не отправят? Насколько это "голова в песке"?
источник
Я обнаружил, что TDD (и модульное тестирование в целом) практически невозможно по связанной причине: сложные, новые и / или нечеткие алгоритмы. Проблема, с которой я сталкиваюсь чаще всего в исследовательских прототипах, которые я пишу, заключается в том, что я понятия не имею, какой правильный ответ, кроме выполнения моего кода. Это слишком сложно, чтобы разумно разобраться вручную для чего-то, кроме смехотворно тривиальных случаев. Это особенно верно, если алгоритм включает в себя эвристику, аппроксимации или недетерминизм. Я все еще пытаюсь протестировать функциональность более низкого уровня, от которой зависит этот код, и интенсивно использовать ее для проверки работоспособности. Мой последний метод тестирования - написать две разные реализации, в идеале на двух разных языках, используя два разных набора библиотек, и сравнить результаты.
источник
Из моего опыта: Да для Unittests (тестирование модулей / функций в изоляции), потому что они в основном не имеют проблемы, которые вы упоминаете: (Gui, Mvvm, Business-Modell). У меня никогда не было более 3 макетов / заглушек, чтобы полностью заполнить один юнит-тест (но, возможно, вашему домену требуется больше).
Однако я не уверен, что TDD сможет решить проблемы, упомянутые вами при интеграции или сквозном тестировании с помощью тестов в стиле BDD.
Но, по крайней мере, некоторые проблемы могут быть уменьшены .
Это верно, если вы хотите выполнить полное покрытие на уровне интеграционного теста или сквозного теста. Может быть проще сделать полное покрытие на уровне юнит-теста.
Пример: проверка сложных полномочий пользователя
Тестирование функции
IsAllowedToEditCusterData()
на уровне интеграционного тестирования потребовало бы запроса у различных объектов информации о пользователе, домене, клиенте, среде ....Издеваться над этими частями довольно сложно. Это особенно верно, если
IsAllowedToEditCusterData()
нужно знать эти разные объекты.На уровне Unittest у вас будет функция,
IsAllowedToEditCusterData()
которая принимает, например, 20 параметров, которые содержат все, что функция должна знать. ПосколькуIsAllowedToEditCusterData()
не нужно знать, в каких полях auser
, adomain
, acustomer
, .... это легко проверить.Когда я должен был реализовать, у
IsAllowedToEditCusterData()
меня было две перегрузки:Одна перегрузка, которая не делает ничего, кроме получения этих 20 параметров, а затем вызывает перегрузку с 20 параметрами, которые принимают решения.
(у моего
IsAllowedToEditCusterData()
было только 5 параметров, и мне нужно было 32 различные комбинации, чтобы полностью его протестировать)пример
источник
Печальный ответ заключается в том, что ничего не работает для больших сложных проектов!
TDD так же хорош, как и все остальное, и лучше, чем большинство, но только TDD не гарантирует успеха в большом проекте. Это, однако, увеличит ваши шансы на успех. Особенно при использовании в сочетании с другими дисциплинами управления проектами (проверка требований, сценарии использования, матрица отслеживаемости требований, прохождение кода и т. Д. И т. Д.).
источник
Помните, что модульные тесты - это обязательные спецификации . Это особенно ценно в сложных проектах. Если ваша старая кодовая база не имеет каких-либо тестов для ее резервного копирования, никто не посмеет ничего изменить, потому что они будут бояться что-либо сломать.
«Wtf. Почему эта ветвь кода вообще существует? Не знаю, может, кому-то это нужно, лучше оставить ее там, чем кого-то расстраивать ...» Со временем сложные проекты становятся мусорной землей.
С помощью тестов каждый может с уверенностью сказать: «Я произвел радикальные изменения, но все тесты все еще проходят». По определению он ничего не сломал. Это приводит к более гибким проектам, которые могут развиваться. Возможно, одна из причин, по которой нам все еще нужны люди для поддержки COBOL, заключается в том, что с тех пор тестирование не было популярным
источник
Я видел, как большой сложный проект полностью провалился, когда использовался исключительно TDD, то есть, по крайней мере, без настройки в отладчике / IDE. Макетные данные и / или тесты оказались недостаточными. Реальные данные бета-клиентов были конфиденциальными и не могли быть скопированы или зарегистрированы. Таким образом, команда разработчиков никогда не могла исправить фатальные ошибки, которые проявлялись, когда указывалось на реальные данные, и весь проект был свернут, все уволены, все биты.
Чтобы устранить эту проблему, можно было бы запустить ее в отладчике на клиентском сайте, сравнить с реальными данными, пройтись по коду с точками останова, наблюдать за переменными, наблюдать за памятью и т. Д. Однако эта команда, которые считали, что их кодекс подходит для украшения лучших башен из слоновой кости, в течение почти одного года ни разу не запустили свое приложение. Это взорвало мой разум.
Так что, как и все, баланс является ключом. TDD может быть хорошим, но не полагайтесь исключительно на это.
источник
Я так думаю, см. Test Driven Development действительно работает
источник
Если комбинация бюджета, требований и командных навыков находится в квадранте пространства проекта, помеченного как «оставь надежду всем, кто входит сюда», то, по определению, в подавляющем большинстве случаев проект потерпит неудачу.
Возможно, требования сложны и нестабильны, инфраструктура нестабильна, команда младшая и с высокой текучестью, или архитектор идиот.
В проекте TDD симптомом этого надвигающегося сбоя является то, что тесты не могут быть записаны по расписанию; Вы пытаетесь, только чтобы обнаружить «это займет так много времени, а у нас есть только это ».
Другие подходы покажут другие симптомы, когда они потерпят неудачу; чаще всего доставка системы, которая не работает. Политика и контракты будут определять, является ли это предпочтительным.
источник
TDD
Это может показаться болезненным, но в долгосрочной перспективе это будет ваш лучший друг, поверьте мнеTDD
, в долгосрочной перспективе приложение действительно будет обслуживаемым и безопасным.источник