Слишком много внимания уделяется тестированию?

Что я имею в виду, так это то, что иногда архитекторы стремятся упростить и улучшить тестируемость за счет других важных сил.

Например, я просматриваю очень сложное приложение, сделанное таким образом, путем широкого использования шаблонов проектирования, которые чрезмерно способствуют тестированию, например. IoC, DI, АОП и т.д.

Теперь, как правило, мне нравятся эти вещи, но эта система должна быть намного проще - хотя и не просто простой интерфейс для CRUD на db, но он все еще не намного сложнее, чем это (даже учитывая некоторые внутренние рабочие процессы, процессы и т.д.). С другой стороны, просто просмотр кода становится серьезной болью в heinie, едва читаемым (хотя его хорошо написано), и кодирование его, должно быть, было болью.

Реализованная сложность - это явный нарушитель KISS (принцип, а не группа)... и "единственное" преимущество - улучшенная тестируемость, использование тестовых фреймворков и mocks и...

Теперь, прежде чем вы, поклонники TDD, скажете мне, я не умаляю важность тестируемости, но я задаю вопрос о превосходстве рассмотрения этой конкретной силы (против всех остальных).
Или я что-то пропустил?


Я хотел бы добавить еще один момент - мне кажется, что все эти разговоры о "тестируемости" касаются, в частности, модульного тестирования, который отличается от общего тестирования системы и может привести к в пропущенных тестах, когда отдельные единицы объединены вместе. По крайней мере, это кажется точкой IoC/DI для тестирования...
Кроме того, я хотел бы указать, что эта система (и другие, которых я видел проповедью) имеет только один конкретный объект для каждого интерфейса, а IoC/DI предназначен только для - вы догадались - заменяя конкретные объекты тестируемыми макетами для только тестирование.


Я почувствовал необходимость добавить эту цитату из Википедия на IoC:

В то время как опасность в процедурном программировании заканчивалась кодами спагетти, опасность при использовании инверсии управления заканчивается кодом макарон

Yup, это выражает мое чувство именно: D

Ответ 1

Чтобы ответить на ваш общий вопрос, я бы сказал "все в меру". Акцент на тестируемости, конечно же, замечательный. Но не тогда, когда это происходит за счет исключения, скажем, читаемого кода или логического API.

Ответ 2

TDD, сделанный хорошо, может улучшить читаемость. TDD, выполненный плохо, без учета других важных принципов, может уменьшить читаемость.

Парень, с которым я работал в середине 90-х, сказал бы: "Вы всегда можете сделать систему более гибкой, добавив слой косвенности. Вы всегда можете сделать систему проще, удалив слой косвенности". И гибкость, и простота являются важными качествами системы. Эти два принципа часто могут жить вместе в гармонии, но часто они работают друг против друга. Если вы заходите слишком далеко друг к другу, вы удаляетесь от идеала, который существует там, где эти два принципа сбалансированы.

TDD отчасти касается тестирования, отчасти о дизайне. TDD, сделанный плохо, может слишком сильно повлиять на гибкость или простоту. Это может привести к слишком большой гибкости. Объекты становятся более проверяемыми и часто проще, но присущая сложность проблемы домена вытесняется из объектов во взаимодействие объектов. Мы получили гибкость, и наивный взгляд может выглядеть так, как будто мы получили простоту, потому что наши объекты проще. Однако сложность все еще существует. Он переместился из объектов и в взаимодействие с объектом, где его сложнее контролировать. Есть запахи кода, которые могут действовать как красные флаги здесь - система с сотнями мелких объектов и не более крупными объектами одна, много объектов с только однострочными методами - это другое.

TDD, выполненный плохо, может двигаться в другом направлении, то есть к слишком большой простоте. Итак, мы делаем TDD, сначала пишем тест, но это мало влияет на наш дизайн. У нас все еще есть длинные методы и огромные объекты, и это запахи кода, которые могут красным обозначить эту проблему.

Теперь TDD по своей природе не сбивает вас с баланса в любом направлении, если оно хорошо применяется. Используйте другие методы, чтобы держать вас в курсе. Например, нарисуйте фотографии того, что вы делаете, прежде чем делать это. Очевидно, не все время. Для этого некоторые вещи слишком просты. Некоторые фотографии стоит сэкономить, некоторые из них - просто эскизы, которые помогают нам визуализировать проблему, и мы, в различной степени, в основном визуальные ученики. Если вы не можете нарисовать картину проблемы, вы ее не понимаете.

Как это поможет с TDD? Это поможет сохранить систему слишком далеко на стороне гибкости, в стороне от простоты. Если вы рисуете картину, и это уродливо, это красный флаг. Иногда это необходимо, но часто, когда вы рисуете изображение, ваш ум быстро увидит вещи, которые могут быть упрощены. Решение становится более изящным и упрощенным, легче поддерживать и более приятным для работы. Если вы не можете или не рисуете изображения своей системы, вы теряете эту возможность, чтобы сделать ваше программное обеспечение более прочным, более элегантным, красивее, чтобы его видеть и легче поддерживать.

Применение этого происходит с опытом, а некоторые кодеры никогда не поймут ценность, которую обеспечивает хороший баланс. Там нет показателя, который вы можете запустить, который говорит вам, что вы в нужном месте. Если кто-то дает вам предписанный метод, чтобы прийти к этому гармоничному моменту, он лжет вам. Что еще более важно, он, вероятно, лгал себе, не осознавая этого.

Итак, мой ответ на ваш вопрос "да": проверьте все, не забывая о других хороших принципах.

Любая хорошая практика заставит вас отказаться от курса, если он не будет сбалансирован с другими хорошими практиками.

Ответ 3

"Я что-то пропустил?"

Да.

Вещь работает, не так ли?

И, что более важно, вы можете продемонстрировать, что он работает.

Относительная степень сложности, добавляемая для проверки, не очень интересна по сравнению с тем фактом, что она действительно работает, и вы можете продемонстрировать, что она действительно работает. Кроме того, вы можете внести изменения и продемонстрировать, что вы не нарушили его.

Альтернативы (могут или не могут работать, не демонстрировать, если они работают, не могут внести изменения, не нарушая их) уменьшает значение программного обеспечения до нуля.


Edit

"Сложность" - это скользкая концепция. Существуют объективные меры сложности. Еще важнее ценность, создаваемая увеличением сложности. Повышенная сложность дает вам возможность тестирования, конфигурируемость, позднюю привязку, гибкость и адаптируемость.

Кроме того, объективная мера сложности обычно ориентирована на кодирование внутри метода, а не на более сложную взаимосвязь между классами и объектами. Сложность кажется объективной, но она не определена на всех уровнях архитектуры программного обеспечения.

"Тестемость" также скользкая. Могут быть объективные меры проверки. В основном, однако, они посвящены тестированию покрытия. И охват тестирования не является очень значимой метрикой. Каким образом вероятность сбоя производства зависит от охвата тестирования? Это не так.

Вы можете обвинить сложность в фокусировании на тестируемости. Вы можете обвинить сложность во многих вещах. Если вы внимательно посмотрите на высоко проверяемый код, вы обнаружите, что он также очень гибкий, настраиваемый и адаптируемый.

Выделение "проверяемости" в качестве основной причины "сложности" не соответствует точке.

Дело в том, что существует множество взаимосвязанных факторов качества. "It Works" - это способ обобщения наиболее важных. Другие, менее важные, включают адаптивность, гибкость, ремонтопригодность. Эти дополнительные факторы обычно коррелируют с проверяемостью, и их также можно описать негативно как "сложность".

Ответ 4

Я видел первые веб-сайты, прошедшие все unit test, прошедшие все тесты автоматизированного интерфейса, прошедшие нагрузочные тесты, прошедшие практически каждый тест, но явно и, очевидно, имели проблемы при просмотре человеком.

Это приводит к анализу кода, который обнаруживает утечки памяти, проблемы кэширования, плохой код и недостатки дизайна. Как это произошло, когда последовало несколько методик тестирования и прошли все тесты? Ни одна из "единиц" не имела утечек памяти или проблем с кэшированием, а только системы в целом.

Лично я считаю, потому что все было написано и предназначено для прохождения тестов, а не для того, чтобы быть элегантным, простым и гибким в дизайне. В тестировании очень много. Но только потому, что код проходит тест, это не значит, что он хороший код. Это означает, что это "книжный умный" код, а не "уличный умный" код.

Ответ 5

На мой взгляд, учитывая достаточно большую или важную часть программного обеспечения, стоит добавить некоторую сложность для повышения тестируемости. Кроме того, по моему опыту, места, где сложность трудно понять, заключается в том, когда слои абстракции добавляются для обертывания фрагмента кода, который по своей природе является невосприимчивым к нему (например, к закрытым фреймворческим классам). Когда код написан с точки зрения проверяемости в качестве первого принципа, я обнаружил, что код, по сути, легко читается и не сложнее, чем необходимо.

Я на самом деле довольно устойчив к добавлению сложности, где я могу избежать этого. Я еще не перешел на рамки DI/IoC, например, предпочитая использовать приложения для ввода вручную только там, где это необходимо для тестирования. С другой стороны, когда я, наконец, принял практику, которая "увеличивает" сложность - как насмешливые рамки - я обнаружил, что объем сложности на самом деле меньше, чем я боялся, и пользы больше, чем я себе представлял. Возможно, я, в конце концов, найду, что это справедливо для фреймворков DI/IoC, но я, вероятно, не поеду туда, пока у меня не будет достаточно небольшого проекта, чтобы экспериментировать, не откладывая его необоснованно, изучая новые вещи.

Ответ 6

"Или я что-то пропустил?"

Там подразумевается прямая связь в вопросе о том, как тестируемый код и как сложный код. Если бы это был ваш опыт, я бы сказал, вы делаете это неправильно.

Код не должен быть более сложным, чтобы быть более проверяемым. Код рефакторинга, который должен быть более проверенным, имеет тенденцию к более гибкому и более компактному коду. Это не обязательно означает более сложный (который уже является загруженным термином) или что на расстоянии должно быть действие на расстоянии.

Не зная подробностей, я могу дать общий совет. Убедитесь, что вы используете не только шаблон в неделю. Если у вас есть метод, который требует большого количества настроек или сложных способов переопределить его поведение, часто внутри него существует ряд более простых, детерминированных методов. Извлеките эти методы, а затем вы можете легко unit test их.

Тесты не должны быть такими же чистыми и хорошо продуманными, как и код его тестирования. Часто лучше делать то, что обычно будет неприятным взломом в тесте, а не делать много редизайна кода. Это особенно хорошо для тестирования отказов. Нужно ли имитировать сбой подключения к базе данных? Коротко замените метод connect() тем, который всегда терпит неудачу. Нужно знать, что происходит, когда диск заполняется? Замените метод открытого файла на тот, который не работает. Некоторые языки хорошо поддерживают эту технику (Ruby, Perl), другие - не так много. Как правило, ужасный стиль становится мощным методом тестирования, который прозрачен для вашего производственного кода.

Одна вещь, которую я окончательно скажу, - никогда не вводить код в производство, который полезен только для тестирования. Все, что нравится if( TESTING ) { .... }, прямо. Он просто загромождает код.

Ответ 7

Проверяемый продукт - это тот, который дает возможность ответить на вопросы об этом. Возможность тестирования, как и качество, является многомерным и субъективным. Когда мы оцениваем продукт как (не) проверяемый, важно признать, что проверяемость для кого-то может быть добавлена ​​или излишняя сложность для кого-то другого.

Продукт, который имеет множество модульных тестов, может быть прекрасно проверен программистам, но если нет никаких крючков для автоматизации, продукт может быть трудно протестирован для тестирующего инструментария. Тем не менее, тот же продукт, если он имеет чистый рабочий процесс, элегантный пользовательский интерфейс и протоколирование, может быть прекрасно проверен интерактивным тестером черного ящика. Продукт без единичных тестов может быть настолько чистым и четким, что он очень поддается проверке и обзору, что является еще одной формой тестирования.

Я говорю о тестируемости здесь. Джеймс Бах говорит об этом здесь.

--- Майкл Б.

Ответ 8

(Это написано целиком с точки зрения программиста. Для ответа на более высокий клиент я бы рекомендовал Майкл Болтон ответить.)

Если приложение, которое вы пишете, составляет < 10 строк кода, то да, добавление тестов значительно увеличивает сложность. Вы можете ПОСМОТРЕТЬ НА ЭТО и проверить его вручную, и вы, вероятно, будете в порядке. На 100 линиях не так много, 1000 строк, не столько, 10 000 строк, 100 000 строк... и т.д.

Вторая ось - это изменение. Будет ли эта база бухты/когда-либо/изменена? На сколько? Чем больше код изменится, тем более ценными будут тесты.

Итак, да, для приложения с 150-строчным кодом, которое представляет собой преобразование edi-format-to-edi-формата script, которое работает в пакетном режиме, который никогда не изменится, может потребоваться сильное модульное тестирование над убийством.

Как правило, для больших приложений я обнаружил, что изменение проверяемого кода улучшает качество дизайна и API. Поэтому, если вы пишете что-то гораздо большее или что будет развиваться итеративно, и подумайте (автоматизированное) модульное тестирование имеет высокую стоимость/низкое значение, я бы серьезно рассмотрел, почему вы считаете, что это так.

Одно из объяснений заключается в том, что ваш босс имеет склонность к шаблону. Другим может быть то, что вы видите шаблоны и тестирование как обсуждение "да/нет" или "ничего". Третье состоит в том, что код уже написан, и он переписывает подлежащий тестированию, что вы боитесь. Если какой-либо из этих случаев имеет место, я бы предложил хирургический подход - сосредоточьтесь на нескольких тестах с высоким взломом для теста, которые очень быстро добавляют ценность. Развивайте свой тестовый пакет медленно, по мере продвижения кода. Рефакторинг по шаблонам, когда вы видите ценность и простоту, а не сложность.

Ответ 9

Прибыль от этого подхода вернется, приложение IF станет достаточно большим. В противном случае - это просто пустая трата времени. Иногда даже drag & drop 'coding' и после шаблона SmartUI удовлетворяют достаточно.

Ответ 10

Из описания это похоже на то, что проект потерял контроль над YANGI, развивая большие структуры, чтобы при необходимости можно было протестировать.

В TDD все оправдано тестом, поэтому тот факт, что у вас есть все это IoC, DI, AOP, было либо требовалось, как простейшее решение, чтобы сделать существующие тесты пройденными или (что гораздо более вероятно) чрезмерно встроенным решением для проверки кода.

Одна из ошибок, которые я видел, что приводит к такой сложности, - это желание испытать испытание по дизайну, а не наоборот. Что может случиться, так это то, что желание придерживаться определенного труднопрофильного дизайна приводит к внедрению всех видов обходных путей для открытия API, а не для разработки более простого и простого тестирования API.

Ответ 11

Для лучшего или худшего TDD помогло мне разбить мои приложения на более управляемые компоненты, где моя способность тестировать объекты в изоляции заставила меня держать вещи краткими. Тесты также послужили хорошим источником документации, когда я вводил других в свой код. Прохождение тестов может быть хорошим способом для обзора работы приложения, когда вещи изолированы достаточно, чтобы вы могли обернуть голову вокруг функциональных частей. Еще один приятный продукт заключается в том, что когда вы использовали шаблон дизайна в приложении, тесты имеют сходство с другими приложениями, в которых вы использовали этот шаблон.

Все, что было сказано, было бы действительно глупо реализовать, скажем, Command Pattern и иметь только две команды, когда вы знаете, что приложение будет выполнять только две функции. Теперь вы оседлали себя, написав кучу тестов. Что было получено? Вы всегда можете тестировать общедоступные методы, но с шаблоном на месте у вас есть сложность в решении проблемы, и они понесли технический долг со всем дополнительным тестом, который вы должны поддерживать.

Еще один фактор, который необходимо учитывать, - это то, что может поддерживать ваша архитектура. Все ли члены команды на одинаковом уровне понимания TDD, или будет меньшинство людей, которые могут понять тесты? Видит ли насмешливый объект, чтобы кто-то заглянул в глаза, и это само по себе становится запретительным фактором для своевременного обслуживания?

В конце концов, объем приложения должен также управлять дизайном. Сложность ради того, чтобы быть "чистым", не является хорошим суждением. TDD не вызывает этого; скорее, отсутствие опыта может.

Ответ 12

Я понятия не имею, что вы подразумеваете под этим, это едва читаемо, так как даже при использовании AOP и DI каждая часть должна быть легко понята. Понимание всего этого может быть сложнее из-за этих технологий, но это более важно, чтобы объяснить, как с помощью моделей или текста, как работает приложение.

В настоящее время я работаю над приложением, где нет ни одного unit test, поэтому теперь я начинаю вводить DI, чтобы упростить тестирование, но это затруднит понимание другими разработчиками системы, так как могут быть подключены различные конкретные классы, и вы не будете знать, какой из них есть, пока вы не посмотрите файл app.config.

Это может привести к мысли, что код не читается, потому что они не могут просто просто перетекать с одного уровня на другой, но нужно совершить боковое путешествие, чтобы увидеть, какой конкретный класс использовать.

Но в долгосрочной перспективе это будет более гибкая и стабильная система, поэтому я думаю, что стоит того, чтобы участвовать в некоторых тренировках.:)

Вам просто нужно посмотреть, как получить лучшую системную модель для приложения, посмотреть, как все связано.

Ответ 13

Я просматриваю очень сложные применение, сделанное таким образом в широком использовании шаблонов дизайна, которые чрезмерно благоприятствуют испытания, например. IoC, DI, AOP и т.д.

В этом случае тестирование не является проблемой, его шаблоны проектирования и общая архитектура, которые виноваты, что-то обычно критикуется Joel и Jeff в обсуждениях против астронавтов архитектуры. Здесь у нас есть что-то, что было решено на основе "wow cool architecture", и если 1 шаблон дизайна хорош, 2 должен быть отличным, а 3 должен быть фантастическим - посмотрим, сколько шаблонов мы можем создать из этого приложения.

Если тестирование, возможно, необходимо для надежной работы этих шаблонов (хм, что-то говорит о них действительно), но вы не должны путать тестирование с хорошей архитектурой, поскольку некоторые архитектурные проекты являются плохими.

Итак, нет, не стесняйтесь сосредоточиться на тестировании без беспокойства - например, Extreme Programming - очень простая методология разработки, которая фокусируется на тестировании, если бы вы написали свое приложение таким способом свободной формы, каким бы вы не попали в ваш беспорядок, что у вас есть не ошибка разработки, основанной на тестах, а выбор дизайна, который был сделан.

Если вы можете начать отказываться от него, сделайте это - ремонтопригодность - это самый важный фактор в программном обеспечении, если его нелегко модифицировать, тогда вы можете запечатать его и начать сначала, поскольку это, вероятно, будет стоить вам больше, чтобы его поддерживать.