Модульные тесты действительно так полезны? [закрыто]


98

Я только что закончил со степенью в CS, и в настоящее время у меня есть работа в качестве младшего разработчика .NET (C #, ASP.NET и веб-форм). Когда я еще учился в университете, тема модульного тестирования все-таки освещалась, но я никогда не видел ее преимуществ. Я понимаю, что он должен делать, а именно определить, пригоден ли блок кода для использования. Однако мне никогда раньше не приходилось писать модульные тесты, и я никогда не чувствовал в этом необходимости.

Как я уже упоминал, я обычно разрабатываю с помощью веб-форм ASP.NET, и недавно я подумал о написании некоторых модульных тестов. Но у меня есть несколько вопросов по этому поводу.

Я читал, что модульное тестирование часто происходит посредством написания «макетов». Хотя я понимаю эту концепцию, я не могу понять, как я должен писать макеты для веб-сайтов, которые являются полностью динамическими, и где почти все зависит от данных, поступающих из базы данных. Например: я использую много репитеров, которые имеют события ItemDataBound и т. Д. (Опять же, в зависимости от данных, которые «неизвестны»).

Итак, вопрос №1: Является ли написание модульных тестов для веб-форм ASP.NET чем-то, что часто делается, и если да, то как мне решить проблему с «динамической средой»?

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

Итак, вопрос № 2: Не могли бы вы, ребята, посоветовать мне начать писать модульные тесты? Я думаю, что это может помочь мне в реальной реализации, но опять же я чувствую, что это может замедлить меня.


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

9
Как именно вы охватили юнит-тестирование без написания юнит-тестов? Была ли это одна из тех школ, где вы сами «оцениваете себя» или «разрабатываете свою учебную программу»?
Джеффо

4
Модульные тесты сомнительны - отлично подходит для динамических языков, менее полезен, чем строже ваш язык, но ДЕЛАЙТЕ ИСПЫТАНИЯ. Это не обязательно модульные тесты, но у вас действительно должны быть интеграционные тесты, которые вы можете запустить с помощью JUnit, они очень полезны.
Билл К

13
-1 Извините, я все за веские аргументы, даже если я не согласен, но это просто неправильно. Никто не утверждает, что «модульные тесты предназначены для отлова ошибок в новом коде», так что это глупость - модульные тесты предназначены для отлова регрессий . А цитата Дейкстры вырвана из контекста - контекст в том, что тестирование бессмысленно, если у вас есть формальная спецификация вашей проблемы .
Слёске

9
«модульные тесты для ловли регрессий». Нет. Автоматизированные тесты для ловли регрессий. Регрессии неизменно требуют, чтобы одни и те же тесты выполнялись много сотен раз, поэтому стоит их автоматизировать. К сожалению, многие ответы и комментарии по этому вопросу действительно касаются вопроса «Являются ли автоматизированные тесты такими полезными?». Модульные тесты могут быть формой автоматизированного тестирования, но они имеют совершенно другую цель. Я, конечно, считаю, что автоматизированные тесты ценятся на вес золота, но это не должно использоваться в качестве аргумента для обоснования модульных тестов (или TDD в этом отношении).
njr101

Ответы:


124

На мой взгляд: да, они есть, и да, вы должны.

  1. Они дают вам уверенность в изменениях, которые вы делаете (все остальное все еще работает). Эта уверенность - то, что вам нужно для формирования кода, иначе вы можете бояться что-то изменить.

  2. Они делают ваш код лучше; самые простые ошибки обнаруживаются на ранних этапах юнит-тестов. Раннее обнаружение ошибок и их исправление всегда дешевле, чем их исправление позже, например, когда приложение находится в производстве.

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

Первая проблема, с которой вы сталкиваетесь, заключается в том, что ASP.NET сам по себе не помогает вам писать модульные тесты - на самом деле он работает против вас. Если у вас есть выбор, начните использовать ASP.NET MVC , который был создан с учетом модульного тестирования. Если вы не можете использовать ASP.NET MVC, вы должны использовать шаблон MVP в ASP.NET, чтобы, по крайней мере, вы могли легко тестировать свою логику.

Кроме того, вам просто нужно научиться писать модульные тесты. Если вы практикуете TDD, ваш код создается тестируемым - иными словами, красивым и чистым.

Я бы посоветовал вам попрактиковаться и в парной программе. Во время чтения:

Или, для первого обзора:


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

21
Если юнит-тесты работают как документация, значит что-то не так. Чтение 500 строк кода, чтобы понять, как работают 5 строк кода, является обратным.
Кодер

4
@Coder: когда вы тестируете методы более высокого уровня, он включает в себя более 5 строк кода.

7
@coder: документация класса сообщает вам об услугах, которые предоставляют экземпляры класса. Он сообщает вам меньше информации о том, как экземпляры этого класса используются в более широком контексте, то есть о взаимодействии между объектами. Тесты дают вам типичный код взаимодействия в некоторых случаях, который был ценным отправным пунктом так много раз, что я даже не могу их сосчитать.
Стефано Борини

21
@ Кодер: он не документирует, что делает код, он документирует предположения, присущие этому коду, то есть, почему и когда он должен работать. Если лежащие в основе предположения становятся недействительными в результате изменения SUT, один или несколько модульных тестов не пройдут. Это не заменяет высокоуровневую документацию по дизайну / архитектуре или даже документы XML, но охватывает то, что эти вещи никогда не могут.
Ааронаут

95

Нет.

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

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

Джикстра разрушил концепцию проверки как доказательства правильности еще в 1988 году, и то, что он написал, остается в силе и сегодня:

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

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

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

Есть некоторые сообщения об автоматизированном тестировании, которое действительно полезно в тех случаях, когда стабильность и надежность имеют первостепенное значение. Например, проект базы данных SQLite. Но то, что требуется для достижения их уровня надежности , крайне неэкономично для большинства проектов: соотношение тест-факт-SQLite-код почти 1200: 1. Большинство проектов не могут себе этого позволить, и все равно не нуждаются в этом.


69
Это доказывает, что ваш код ведет себя правильно для этих тестов. Это чертовски много, если вы спросите меня.
Стефано Борини

111
Кто сегодня на самом деле верит, что модульные тесты являются «доказательством правильности»? Никто не должен так думать. Вы правы в том, что они только доказывают, что эти тесты пройдены, но это еще одна точка данных, которую вы имели до написания модульных тестов. Вам нужно тестировать на разных уровнях, чтобы понять качество своего кода. Модульные тесты не доказывают, что ваш код свободен от дефектов, но они повышают вашу уверенность (или должны ...) в том, что код выполняет то, для чего вы его разработали, и продолжает делать завтра то же, что и сегодня.
Брайан Оукли

40
> but if the test itself is buggy, then you have false confidenceи если ручной тестер не выполняет свою работу правильно, у вас также есть ложная уверенность.
Стефано Борини

33
@MasonWheeler: извини, Мейсон, я не уверен. За более чем пару десятилетий программирования я не думаю, что когда-либо лично видел случай, когда тест давал ложное чувство безопасности. Возможно, некоторые из них сделали это, и мы исправили их, но стоимость этих юнит-тестов никоим образом не перевешивала огромных преимуществ их наличия. Я уверен, что если вы можете писать код без тестирования его на уровне модулей, то подавляющее большинство программистов не в состоянии сделать это последовательно.
Брайан Оукли

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

60

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

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

Здесь тоже забавный образ ... введите описание изображения здесь

Я нашел это изображение здесь:
http://www.howtogeek.com/102420/geeks-versus-non-geeks-when-doing-repetitive-tasks-funny-chart/


2
Да, ты можешь. Изолируйте веб-слой в своих модульных тестах для проверки веб-конфигурации (URL-адреса, проверка входных данных и т. Д.). Заглушив веб-слои и слои базы данных, вы можете протестировать бизнес-уровень без базы данных или веб-сервера. Я использую dbunit для проверки моей БД. Если вы хотите, вы можете провести полное интеграционное тестирование, но я делаю это как конкретную задачу после разработки.
Хит Лилли

12
Симпатичная графика, но у нее неправильный масштаб. Как я указывал в своем ответе, для полного охвата тестов SQLite требуется примерно в 1200 раз больше кода в тестах, чем в самом коде самого продукта. И даже если вы не что обсессивны о полном охвате, вам все еще нужно несколько раз больше испытаний , чем продукт даже подходить к любому полезному уровню охвата в тестах. Чтобы быть точным здесь, вертикальная часть этой красной линии должна будет идти вверх и вверх примерно на 3 страницы.
Мейсон Уилер

27
@MasonWheeler Это очень хорошая лошадь, которую вы бьете, я думаю, что она, возможно, умерла, хотя ... У SQLite столько тестов, потому что это чертова база данных. Я хочу убедиться, что это работает. В качестве другого примера, платформа Silverstripe имеет соотношение тесты: код, близкое к 1: 1, поэтому SQLite не является репрезентативным.
Aatch

15
@MasonWheeler Вы терпите неудачу в первом из парадоксов Зенона . Если вы хотите увеличить это изображение до уровня тестирования SQLite, ось X также должна будет расшириться примерно в 100 раз по сравнению с текущей длиной.
Изката

2
Это особенно актуально, когда вы бэкэнд-разработчик, у которого нет времени, чтобы начать делать черно-белую веб-страницу только для того, чтобы вы могли проверить свою логику. Все, что мне нужно сделать, это предоставить фиктивные объекты запроса и сеанса и запустить мои контроллеры через модульное тестирование, и в конце всего этого я знаю, правильно это или неправильно. Если вы используете DI, просто внедрите DAO, который взаимодействует с базой данных в памяти, чтобы ваша база данных не изменилась, или просто бросьте Exceptionи перехватите ее, чтобы ваши данные не были зафиксированы. Я говорю ДА на модульное тестирование.
Варун Ахар

49

В наши дни модульное тестирование имеет нечто мистическое. Люди считают, что 100% тестирование - это святой Грааль, а модульное тестирование - единственный верный путь разработки программного обеспечения.

Они упускают суть.

Модульное тестирование не является ответом. Тестирование есть.

Теперь, когда возникает эта дискуссия, кто-то (часто даже я) высказывает цитату Дейкстры: «Тестирование программы может продемонстрировать наличие ошибок, но никогда не продемонстрировать их отсутствие». Дейкстра прав: тестирования недостаточно, чтобы доказать, что программное обеспечение работает как задумано. Но это необходимо : на каком-то уровне должна быть возможность продемонстрировать, что программное обеспечение делает то, что вы хотите.

Многие люди тестируют вручную. Даже стойкие энтузиасты TDD будут проводить ручное тестирование, хотя иногда они этого не признают. С этим ничего не поделаешь: перед тем, как идти в конференц-зал, чтобы продемонстрировать свое программное обеспечение своему клиенту / боссу / инвесторам / и т. Д., Вы пробуете его вручную, чтобы убедиться, что оно будет работать. В этом нет ничего плохого, и на самом деле было бы сумасшествием ожидать, что все пройдет гладко, не выполняя ручную работу, то есть тестирование даже если у вас 100% покрытие модульных тестов и абсолютная уверенность в ваших тестах ,

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

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

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

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

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

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

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

TL; DR: пока не беспокойтесь о модульном тестировании . Просто беспокойтесь о тестировании вашего программного обеспечения в первую очередь.


Модульные тесты тоже написаны людьми и могут ошибаться.
Сеун Осева

41

По-разному

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

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

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


Это хороший момент. Вы должны знать, как писать хорошие тесты, которые фиксируют значение SUT.
Энди

3
Это в основном охватывает то, как меня учили выполнять модульные тесты - сначала писать тесты, чтобы охватить наиболее важные / разрушаемые ситуации, а затем добавить дополнительные тесты, когда ваши предположения оказались неверными (я думал, что что-то может "никогда не потерпеть неудачу", но это произошло) ,
Восстановить Монику

38

Проекты, выполненные для университетских классов, сильно отличаются от бизнес-приложений, которые вы будете писать на работе. Разница в продолжительности жизни. Как долго живет университетский проект? В большинстве случаев он начинается, когда вы пишете первую строку кода, и заканчивается, когда вы получаете оценку. Можно сказать, что, по сути, он живет только во время реализации. «Выпуск» обычно равен его «смерти».

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

Мы подошли к одному очень важному моменту - регрессии . На месте, где я работаю, у нас есть две команды, которые поддерживают два приложения; один, написанный около 5-6 лет назад с очень небольшим охватом тестов кода *, и второй - более новая версия первого приложения с полным набором тестов (модуль, интеграция и что-то еще). Обе команды имеют специальных ручных (человеческих) тестеров. Хотите знать, сколько нужно времени, чтобы представить новую, довольно базовую функцию для первой команды? 3-4 недели. Половина этого времени «проверяет, все ли еще работает». Это напряженное время для ручных тестеров. Звонят телефоны, люди расстраиваются, что-то снова сломалось. Вторая команда обычно занимается такими вопросами менее чем за 3 дня.

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

И последнее, но не менее важное, комментарий Брайана, который, как мне кажется, пригвоздит весь вопрос:

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

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

* Они медленно вводят все больше и больше тестов в свою кодовую базу, но мы все знаем, как обычно это выглядит.


10
+1000 за ссылку на Software_Regression. Колледжи выставляют юнит-тесты как нечто, что вы должны делать из чистой веры, без подробного объяснения, что существует заболевание, которое нужно предотвращать и контролировать, и что это заболевание называется регрессией . (тогда есть проблема с регрессионными тестами, которые сильно отличаются от юнит-тестов, потому что единственное чтение, которое я нашел, объясняя это хорошо, это бесплатный образец из этой книги )
ZJR

25

пишет модульные тесты для веб-форм ASP.NET, что часто делается, и если да, то как решить проблему «динамической среды»?

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

Не могли бы вы, ребята, посоветовать мне начать писать модульные тесты? Я думаю, что это может помочь мне в реальной реализации, но опять же я чувствую, что это может замедлить меня.

Где применимо, да. Они могут быть очень полезны при проверке конкретных случаев повторяющимся образом. Они помогают действовать как «трение» против неприятных изменений и как отказоустойчивый, когда вы делаете лучшие изменения.

Стоит отметить, что они обычно замедляют вас.

Это хорошо.

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


8
+1 за фактический ответ на вариант использования вопроса! Все остальные запрыгнули на часть «модульного теста» и забыли о части «ASP.NET веб-формы» ...
Изката

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

11

Я только что закончил со степенью в CS, и в настоящее время у меня есть работа младшего разработчика .NET (в C # и обычно ASP.NET, веб-формы - не ASP.NET MVC). Когда я еще учился в университете, тема модульного тестирования все же освещалась, но я никогда не видел его преимуществ.

Это потому что ты никогда не программировал.

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

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

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

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

- Не могли бы вы, ребята, посоветовать мне начать писать модульные тесты?

Да, черт возьми. Сначала прочитайте «Разработка на основе тестирования» Бека .

Я думаю, что это может помочь мне в реальной реализации, но опять же я чувствую, что это может замедлить меня.

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

Любой совет будет оценен :)

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


8

Изменить: я, конечно, присоединился к TDD Pro / Con Dogpile и пропустил вопрос № 1:

1 - Реализация модульных тестов в веб-формах ASP.net:

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

2 - стоит ли в первую очередь юнит-тесты:

Хорошо, полное раскрытие:

  • Я в основном самоучка. Мое формальное обучение сводится к тому, чтобы мне нравились один класс JavaScript, PHP и C #, а также мое личное изучение принципов ООП и чтение таких вещей, как Design Patterns.

Тем не мение,

  • Я в основном пишу для клиентской части сети, и в действительности программирование написано на одном из самых быстрых и свободных языков в отношении динамической типизации, функций первого класса и изменчивости объектов.

Это означает, что я не пишу для того же компилятора или виртуальной машины. Я пишу примерно для 4-20 различных интерпретаций трех языков (да, два из них просто декларативные, но также определяют фундаментальное физическое пространство пользовательского интерфейса, с которым я иногда работаю по-разному), и делаю это, поскольку интерпретации были намного разнообразнее, чем сегодня. И нет, я не просто ребенок, который использует JQuery для одноразовых приложений. Я помогаю создавать и поддерживать довольно сложные вещи с большим количеством элементов пользовательского интерфейса.

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

Мое понимание того, что TDD должен сделать для вас, заключается в том, что тесты больше направлены на то, чтобы заставить вас более тщательно продумать дизайн и сосредоточиться на требованиях. Справедливо, но проблема здесь в том, что это сводит на нет то, что вы должны делать, то есть проектирование интерфейса, к чему-то тонко, но принципиально другому, то есть к тестированию интерфейса. Разница для меня заключается в том, чтобы нарисовать ясную картину, в которой маме не нужно будет угадывать смысл, и заполнить всю страницу зеленым цветом очень быстро, чтобы вы могли стать первым ребенком, который хлопнет своими карандашами по столу и выкрикивает: «Готово! " Перенося приоритет на результаты, а не на процессы и дизайн, вы, в основном, поощряете продолжение реализации мусорного кода, который, как правило, изначально был причиной ваших проблем.

И, конечно же, есть «нереальная точка», но часто превозносимая побочная выгода самих модульных тестов, помогающих обнаруживать ошибки регрессии. Сторонники TDD, как правило, немного недовольны тем, является ли это целью или просто изощренным побочным эффектом, IMO, потому что они чертовски хорошо знают или, по крайней мере, подозревают, что этого просто недостаточно, чтобы установить отсутствие ошибок в вашем код, особенно в более динамичном языке, таком как JavaScript, где предполагается, что вы даже можете предсказать каждый возможный сценарий в длинной цепочке зависимостей, безрассудно.

В JS есть место для автоматического тестирования, но гораздо лучше использовать свое время, чем присоединять модульный тест к каждому отдельному «модулю» вашего кода, который вступает в контакт с другим, - это гарантирует, что у вас нет кучки мусорные объекты, которые дублируют работу или чье предполагаемое использование семантически неоднозначно там во-первых. Вы следуете принципу СУХОЙ. Вы абстрагируете вещи для повторного использования / переносимости, когда ценность этого становится очевидной (а не минутой раньше). Вы устанавливаете последовательные процессы и способы ведения дел, следуя принципу больше кнута, чем принципа кнута (т.е. слишком легко использовать ваши вещи правильным способом, чтобы беспокоиться о желании сделать это неправильно). И ради любви ко всему, foo и bar, вы никогда не будете потворствовать масштабным каскадным анти-шаблонам схем наследования как средству повторного использования кода.

Все вышеперечисленное помогло мне серьезно сократить количество трудно диагностируемых ошибок в моем коде, и вы можете поверить, что это является большим приоритетом для того, кто придумал как разработчик с набором браузеров, которому нечего сказать вам лучше, чем " э-э, была проблема с объектом типа 'Объект' в этом воображаемом номере строки в неуказанном файле. " (ну и дела, спасибо IE6) TDD, в моей работе, не будет поощрять эти вещи. Это сместит фокус на 100% результаты по сравнению с процессом, где то, что находится между точкой A и B, не имеет большого значения, пока оно работает. Это бесполезная трата времени, которую лучше использовать, чтобы убедиться, что ваши вещи разборчивы, портативны и легко модифицируются, без каких-либо путаниц.

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


1
Я пишу много юнит-тестов. Я не буду писать код без них. Но я согласен с твоими чувствами. Тесты должны направлять , а не стимулировать разработку. Вы не можете автоматизировать тщательное размышление о проблеме.
FizzyTea

У меня нет проблем с автоматическим тестированием. Но массовое принятие этого на каждом этапе кажется мне скорее паникой, чем процессом. Я предпочитаю экономить время на проектирование и автоматизировать тестирование и валидацию в местах, где вы можете взаимодействовать с множеством вещей, которые вы не контролируете.
Эрик Реппен

5

По моему опыту, юнит-тесты действительно очень полезны, когда вы начинаете с них и остаетесь с ними, то есть с помощью тест-ориентированной разработки. Вот почему:

  • Модульные тесты заставляют вас думать о том, что вы хотите, и о том, как проверить, что вы его получили, прежде чем писать код, который это делает . В сценарии TDD вы сначала пишете тест. Таким образом, вы должны знать, что должен делать код, который вы собираетесь написать, и как вы можете убедиться, что он успешно это сделал, чтобы написать «красный» тест, который вы затем сделаете «зеленым», написав код в пропусти это. Во многих случаях это заставляет вас задуматься над алгоритмом, который вы собираетесь написать, чтобы пройти этот тест, и это всегда хорошо, так как уменьшает логические ошибки и «угловые случаи». Пока вы пишете тест, вы думаете, «как это может провалиться» и «что я здесь не тестирую», что приводит к более надежному алгоритму.

  • Модульные тесты заставляют задуматься о том, как будет использоваться код, который вы собираетесь написать . До того, как я изучил TDD, было много раз, когда я писал код, ожидающий, что зависимость будет работать в одну сторону, а затем мне давали зависимость, написанную коллегой, который работал совершенно по-другому. Хотя это все еще возможно с TDD, модульный тест, который вы пишете, заставляет задуматься о том, как вы хотите использовать объект, который вы пишете, потому что это пример использования указанного объекта. Затем, мы надеемся, вы напишите объект таким образом, чтобы его было легко потреблять, и, таким образом, адаптировать его при необходимости (хотя программирование на предопределенные интерфейсы является лучшим общим решением этой проблемы, которое не требует TDD).

  • Модульные тесты позволяют вам «кодировать путем тестирования» . Инструмент рефакторинга, такой как ReSharper, может стать вашим лучшим другом, если вы позволите. Вы можете использовать его для определения основы новой функциональности при определении использования в тесте.

    Например, скажем, вам нужно создать новый объект MyClass. Вы начинаете с создания экземпляра MyClass. «Но MyClass не существует!» - жалуется ReSharper. «Тогда создай это», - говорите вы, нажимая Alt + Enter. И до того, как у вас есть определение класса. В следующей строке тестового кода вы вызываете метод MyMethod. «Но этого не существует!» - говорит РеШарпер. «Тогда создай это», повторяешь ты, с помощью Alt + Enter. Вы с помощью нескольких нажатий клавиш определили «каркас» вашего нового кода. По мере того, как вы продолжаете конкретизировать использование, IDE сообщит вам, когда что-то не подходит, и обычно решение достаточно простое, чтобы IDE или инструмент, который подключается к нему, знал, как это исправить.

    Более экстремальные примеры соответствуют модели Triple-A; «Организовать, действовать, утверждать». Настройте все, выполните реальную логику, которую вы тестируете, затем подтвердите, что логика верна. При таком кодировании очень естественно закодировать решение в тесте; затем, с помощью нескольких нажатий клавиш, вы можете извлечь эту логику и поместить ее куда-нибудь, где ее можно будет использовать в производственном коде, а затем внести небольшие изменения в тест, которые указывают ее на новом месте логики. Это заставляет вас создавать модульный и простой в использовании код, поскольку тестируемые модули должны быть по-прежнему доступны.

  • Модульные тесты выполняются на много порядков быстрее, чем любой ручной тест, о котором вы только могли подумать. Существует момент, который очень быстро достигается в случае более крупных проектов, когда накладные расходы на модульное тестирование начинают окупаться за счет сокращения времени, затрачиваемого на ручное тестирование. Вы должны ВСЕГДА запускать код, который вы только что написали. Традиционно вы делали это вручную, запуская большую программу, перемещаясь по пользовательскому интерфейсу, чтобы настроить ситуацию, для которой вы изменили поведение, и затем проверяя результаты снова через пользовательский интерфейс или в форме полученных данных. Если код был TDDed, вы просто запускаете модульные тесты. Я гарантирую вам, если вы пишете хорошие модульные тесты, последний вариант будет во много раз быстрее, чем первый.

  • Модульные тесты ловят регрессию . Опять же, было много раз, прежде чем я узнал TDD, где я вошел, сделал то, что я думал, было хирургическим изменением куска кода, проверил, что изменение исправило ошибочное поведение (или произвело новое желаемое поведение) в сообщаемой ситуации и проверил его на выпуск, только чтобы обнаружить, что изменение нарушило какой-то другой угловой случай в совершенно другом модуле, который случайно использовал тот же самый блок кода. В проекте TDD я могу написать тест, проверяющий изменение, которое я собираюсь внести, внести изменения, а затем запустить полный набор, и если все остальные варианты использования кода были TDDed, и мои изменения что-то сломали, тесты для них другие вещи потерпят неудачу, и я могу расследовать.

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

  • Модульные тесты формируют архитектуру типично выгодным способом . Модульные тесты - это тесты, выполненные изолированно от любой другой логики. Для того, чтобы иметь возможность модульного тестирования вашего кода, вы должны написать код таким образом, чтобы вы моглиизолировать это. Таким образом, удачные конструктивные решения, такие как слабая связь и внедрение зависимостей, естественным образом вытесняют процесс TDD; зависимости должны быть введены так, чтобы в тесте вы могли внедрить «макет» или «заглушку», которые производят ввод или обрабатывают вывод для тестируемой ситуации, не создавая «побочных эффектов». Менталитет TDD «сначала использовать» обычно приводит к «кодированию интерфейсов», сущности слабой связи. Эти хорошие принципы проектирования затем позволяют вносить изменения в производство, такие как замена всего класса, без необходимости изменения больших масс кодовой базы для адаптации.

  • Модульные тесты показывают, что код работает, а не доказывает, что код работает . На первый взгляд вы можете подумать, что это недостаток; неужели доказательство лучше демонстрации? Теория великолепна; вычислительная и алгоритмическая теория - основа нашей работы. Но математическое доказательство правильности алгоритма не является доказательством правильности реализации . Математическое доказательство только показывает, что код, придерживающийся алгоритма, должен быть правильным. Тест блока показывает , что код на самом деле написано делает то , что вы думали , что он будет делать, и, таким образом , доказательство того, что является правильным. Как правило, это гораздо более ценно, чем теоретическое доказательство.

Теперь все сказанное имеет недостатки для юнит-тестирования:

  • Вы не можете тестировать все, Вы можете спроектировать свою систему так, чтобы минимизировать количество LOC, не охваченных модульным тестом, но довольно просто будут определенные области системы, которые не могут быть протестированы модульно. Ваш уровень доступа к данным может быть смоделирован при использовании другим кодом, но сам уровень доступа к данным содержит много побочных эффектов, и, как правило, не представляется возможным провести модульное тестирование большей части (большей части?) Репозитория или DAO. Точно так же код, который использует файлы, устанавливает сетевые подключения и т. Д., Имеет встроенные побочные эффекты, и вы просто не можете выполнить модульное тестирование строки кода, которая делает это. Элементы пользовательского интерфейса часто не могут быть проверены юнитами; вы можете тестировать методы codebehind, такие как обработчики событий, вы можете создавать конструкторы модульного теста и проверять, что обработчики подключены, но в коде просто нет замены пользователю, щелкающему мышью по определенному графическому элементу и наблюдающему, как вызывается обработчик. Достижение этих границ между тем, что может и не может быть надлежащим образом проверено модулем, называется «очисткой края песочницы»; после этого вы можете использовать интеграционные тесты, автоматические приемочные тесты и ручное тестирование для проверки поведения.

  • Многие преимущества модульного тестирования не применяются без TDD, Вполне возможно написать код, а затем написать тесты, которые осуществляют код. Они по-прежнему являются «модульными тестами», однако при первом написании кода вы теряете многие преимущества, присущие разработке «сначала тест»: код не обязательно спроектирован таким образом, чтобы его можно было легко протестировать или даже использовать в производстве. ; вы не получаете «двойную проверку» мыслительного процесса, присущего написанию теста и размышлениям о том, о чем вы не думали; вы не кодируете тестированием; и если вы пишете код, тестируете его вручную и видите, как он работает, то пишите код неудачного модульного теста, который является неправильным: код или тест? Ваши главные преимущества - это предотвращение регрессии (вы будете предупреждены о том, что код, который ранее проходил свои тесты, теперь терпит неудачу) и высокая скорость проверки по сравнению с ручным тестированием. Потеря ТДД '

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

  • Модульное тестирование требует дисциплины, Вы должны написать тесты, которые будут адекватно использовать кодовую базу (хорошее покрытие кода), вы должны запускать их регулярно (как всякий раз, когда вы фиксируете изменение, должен запускаться полный набор), и вы должны держать все «зеленым» ( все тесты пройдены). Когда что-то ломается, вы должны исправить их, исправляя код, который не соответствует ожиданиям, или обновляя ожидания тестов. Если вы меняете тесты, вы должны спрашивать «почему» и внимательно следить за собой; невероятно заманчиво просто изменить ошибочные утверждения, чтобы они соответствовали текущему поведению, или просто удалить неудачные тесты; но эти тесты должны быть основаны на требованиях, и когда они не совпадают, у вас есть проблема. Если эти вещи не сделаны,

  • Модульное тестирование требует больше оборудования, Обычным решением вышеупомянутой потребности в дисциплине и естественной склонности людей становиться ленивыми и сложными, является «сборочный бот», запускающий программный пакет «Непрерывная интеграция», такой как TeamCity, CruiseControl и т. Д., Который выполняет модульные тесты, вычисляет метрики покрытия кода и имеет другие элементы управления, такие как «triple-C» (соответствие правилам кодирования, а-ля FxCop). Аппаратное обеспечение для сборочного бота должно быть достаточно производительным (в противном случае оно не будет соответствовать скорости проверки кода, которую будет выполнять средняя команда), а процедуры регистрации на боте должны быть обновлены (если создается новая библиотека модульных тестов, сценарии сборки, запускающие модульные тесты, должны быть изменены для просмотра в этой библиотеке). Это меньше работы, чем кажется, но обычно требуется некоторый технический опыт со стороны как минимум нескольких человек в команде, которые знают, как работают различные процессы сборки (и, следовательно, могут автоматизировать их в сценариях и поддерживать указанные сценарии). Это также все еще требует дисциплины в виде того, чтобы обращать внимание, когда сборка «ломается», и исправлять то, что вызвало поломку сборки (правильно), прежде чем проверять что-то новое.

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

  • Модульное тестирование обычно запрещает стили быстрой разработки приложений, Если вы пишете юнит-тесты, вы не пишете «быстро и свободно». Как правило, это хорошо, но когда вы находитесь в рамках крайнего срока, навязанного извне вашего контроля, или вы внедряете очень ограниченные изменения, и заинтересованная сторона (или ваш начальник) задается вопросом, почему весь этот раскол должен произойти только для изменить одну строку кода, может быть просто невозможно написать и поддерживать надлежащий набор модульных тестов. Гибкие процессы обычно помогают в этом, позволяя разработчикам влиять на требования времени; помните, что все, что нужно сделать продавцу, - это сказать «да, мы можем», и они получают комиссионный чек, если в процессе не участвуют люди, которые должны фактически выполнять работу, говоря «нет, мы не можем» и на них обращают внимание. Но не каждый Agile, и Agile имеет свои ограничения.


4

Модульные тесты полезны при правильном использовании; Есть разные проблемы с вашей логикой.

«Когда я занимаюсь разработкой, мне приходится много проб и ошибок», - сказал Кевин.

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

s writing unit tests for ASP.NET web forms something that is done often

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

So, question number 2: Would you guys advise me to start writing unit tests?

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


Существуют тестовые среды, которые могут выполнять тесты на страницах aspx, чтобы просто проверить, успешно ли загружаются страницы в разных сценариях. Это может быть недостаточно хорошо, но лучше, чем ничего.
благосклонность

4

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

Когда вы пишете целую последовательность сложных шагов и отлаживаете их в конце, вы склонны находить много ошибок, и процесс, как правило, сложнее, потому что вы продвигаетесь дальше в этом процессе. В Visual Studio вы можете сгенерировать быстрый тест, немного изменить его и запустить ТОЛЬКО этот тест . Тогда вы знаете, что, например, метод, вызывающий этот метод, может положиться на него. Так что это повышает уверенность.

Модульные тесты не доказывают, что ваша программа верна! : Модульные тесты проверяют наличие регрессий в чувствительном коде и позволяют тестировать новые методы, которые вы пишете.

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

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


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

Некоторые люди, включая меня, имели такое заблуждение, когда впервые сталкивались с юнит-тестами, так что я просто проясняю это. Я не знаю, почему вы чувствуете, что я бросаю вам вызов, на самом деле я полностью согласен с вами.
Тьяарт

4

Одна вещь, которая, кажется, не затрагивается, это сложность тестирования различных типов кода.

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

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

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


4

Написание модульных тестов для приложения веб-форм ASP.NET НЕ распространено и очень сложно для выполнения. Однако это не значит, что проект должен его пропустить.

Модульные тесты являются corner stonesкритически важными приложениями, и они обеспечивают надежность и уверенность в том, что основная функциональность работает так, как ожидается.

На самом деле, вы можете гораздо проще представить модульное тестирование с шаблоном ASP.NET MVP, который можно использовать при разработке веб-форм. Это введет разделение интересов и ability to write essential unit tests.

Некоторые ссылки, которые могут быть полезны для поиска:


2
+1 Неважно, проводите ли вы юнит-тесты или нет, MVP - это то, что нужно при работе с веб-формами (возможно, и с WinForms).
Симораман

3

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


6
Без страха ложное чувство безопасности.
Кодер

Может быть, «меньше страха» - лучшая фраза, но ответ все еще в значительной степени правильный.
Восстановить Монику

1
@Coder Если ваши тесты пройдут после рефакторинга, то вы можете быть уверены, что улучшение в коде не изменило поведение приложения (грубо говоря, вы не вводили никаких новых ошибок, но это не обязательно так, потому что вы не можете достичь 100% тестовое покрытие).
m3th0dman

2

По моему опыту, да , юнит-тесты полезны.

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

Модульное тестирование дает различные преимущества:

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

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

Другим побочным эффектом является то, что это означает , что единицы вы тестируете сделать работу в изоляции. Как правило, это означает, что вы начинаете программировать для интерфейсов, а не для конкретных классов, уменьшая связность и повышая сплоченность: все общие признаки хорошего дизайна. Да: просто позволяет вам единица кода есть модульные тесты, естественно , улучшить дизайн вашего кода.

Тем не мение...

Модульное тестирование - не конец тестирования. Другие виды тестирования все еще требуются. Например, даже если вы показали, что юниты работают так, как вы ожидаете, что они будут работать, вы все равно должны показать, что каждый юнит работает так, как его ожидают юниты. То есть правильно ли интегрируются ваши компоненты?


1

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

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


1

Я хочу добавить новую сторону (на самом деле, довольно старую) к этому: модульные тесты не так полезны, если ваш код хорошо спроектирован .

Я знаю, что большинство программистов больше не занимаются разработкой программ, я все еще делаю, и я посчитал модульные тесты довольно трудоемкой необходимостью вписаться в культуру TDD, но пока я встречал только 1-2 второстепенных ошибки на тысячи строк теста моего кода - не только то, что я написал, но и то, что написали официальные тестеры.

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

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

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

В настоящее время диаграммы классов генерируются из кода, содержащего сотни, иногда тысячи классов, и они абсолютно непригодны для использования - все, что содержит более 15 элементов, не может быть признано человеком.

Вы должны знать, что имеет значение 10 + -5 классов или что вы делаете прямо сейчас, и иметь возможность проверять свой код с нескольких точек зрения, каждая диаграмма представляет ТОЧНО точки обзора, на которые вы смотрите, и вы уберете тысячи ошибок на бумаге.

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

там намного проще ...

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

Я сделал код с 95 +% покрытия кода. Конечно, я иногда провожу юнит-тесты, особенно для граничных проверок в расчетах, но мне еще предстоит встретить серьезные регрессии (серьезные: не уничтожаются в течение 24 часов) за то, что они не используют модульные тесты даже для рефакторинга.

Иногда я не делаю ни одной строки кода в течение 3-4 дней подряд, просто рисую. Затем в один день я набираю 1500-2000 строк. К следующему дню они в основном готовы к производству. Иногда пишутся юнит-тесты (с охватом более 80%), иногда (дополнительно) тестировщиков просят попытаться его сломать, каждый раз, некоторых людей просят просмотреть его, посмотрев на него.

Я еще не видел, чтобы эти юнит-тесты нашли что-нибудь.

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


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

Поверьте мне, монолитные функции не подходят для бумаги формата A4 (или US Letter). Иногда, когда я ленивый, я делаю «дизайн» на клавиатуре, но это не то же самое качество. Всякий раз, когда я делаю серьезную разработку, я делаю дизайн с UML. Когда вы рисуете их, вы пытаетесь объяснить себе и другим в очень ограниченном, но все еще структурированном виде, что происходит, и когда вы сможете объяснить код с любой точки зрения, тогда только тогда вы набираете это, и вдруг все ваши ошибки в большинстве
случаев
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.