Вы должны тестировать юнит простых свойств?
Следует ли вам модульному тестированию простых свойств класса, утверждая, что значение установлено и получено? Или это действительно просто модульное тестирование языка?
пример
public string ConnectionString { get; set; }
Тестовое задание
public void TestConnectionString()
{
var c = new MyClass();
c.ConnectionString = "value";
Assert.Equal(c.ConnectionString, "value");
}
Я думаю, я не вижу значения в этом.
8 ответов
Я хотел бы предложить, что вы абсолютно должны.
То, что является авто-собственностью сегодня, может закончиться тем, что против нее придет защитное поле, а не вы...
Аргумент, что "вы просто тестируете компилятор или фреймворк", является чем-то вроде соломенного имхо; то, что вы делаете, когда тестируете авто-свойство, с точки зрения вызывающего, это тестирование общедоступного "интерфейса" вашего класса. Вызывающая сторона понятия не имеет, является ли это автоматическим свойством со сгенерированным каркасом резервным хранилищем или если в getter / setter есть миллион строк сложного кода. Поэтому вызывающая сторона проверяет контракт, подразумеваемый свойством - что, если вы положите X в коробку, вы сможете вернуть X позже.
Поэтому нам следует включить тест, так как мы тестируем поведение нашего собственного кода, а не поведение компилятора.
Для написания такого теста может потребоваться минута, так что это не совсем обременительно; и вы можете достаточно легко создать шаблон T4, который автоматически сгенерирует эти тесты для вас с небольшим размышлением. На самом деле я сейчас работаю над таким инструментом, чтобы избавить нашу команду от рутины
Если вы работаете с чистым TDD, это заставляет вас остановиться на мгновение и подумать, лучше ли вообще использовать свойство public public (подсказка: часто это не так!)
Не лучше ли вам провести предварительный регрессионный тест, чтобы, когда FNG делал что-то вроде этого:
//24-SEP-2013::FNG - put backing field for ConnectionString as we're now doing constructor injection of it
public string ConnectionString
{
{get { return _connectionString; } }
{set {_connectionString="foo"; } }//FNG: I'll change this later on, I'm in a hurry
}
///snip
public MyDBClass(string connectionString)
{
ConnectionString=connectionString;
}
Вы сразу знаете, что они что-то сломали?
Если вышеупомянутое кажется надуманным для простого строкового свойства, я лично видел ситуацию, когда авто-свойство было реорганизовано кем-то, кто думал, что он такой умный, и хотел изменить его с члена экземпляра на оболочку вокруг статического члена класса. (представляющий соединение с базой данных в том виде, в каком оно происходит, резоны для изменения не важны).
Конечно, тот самый очень умный человек совершенно забыл сказать кому-либо еще, что ему нужно вызвать магическую функцию для инициализации этого статического члена.
Это привело к компиляции приложения и его отправке клиенту, после чего оно быстро вышло из строя. Не большая сделка, но это стоило нескольких часов времени поддержки == денег.... Кстати, это был я, я же!
РЕДАКТИРОВАТЬ: в соответствии с различными разговорами в этой теме, я хотел бы отметить, что тест для свойства чтения-записи смехотворно прост:
[TestMethod]
public void PropertyFoo_StoresCorrectly()
{
var sut = new MyClass();
sut.Foo = "hello";
Assert.AreEqual("hello", sut.Foo, "Oops...");
}
редактировать: и вы даже можете сделать это в одну строку в соответствии с автофиксатором Марка Симана
Я хотел бы заявить, что если вы обнаружите, что у вас есть такое большое количество общедоступных свойств, что для написания трех строк, подобных вышеперечисленным, вы должны подвергнуть сомнению свой дизайн; Если вы полагаетесь на другой тест, чтобы указать на проблему с этим свойством, то либо
- Тест на самом деле проверяет это свойство, или
- Вы потратите больше времени на проверку того, что этот другой тест не пройден, потому что свойство неверно (через отладчик и т. Д.), Чем вы потратили бы на ввод кода выше
- Если какой-то другой тест позволяет вам сразу сказать, что свойство является ошибочным, это не модульный тест!
edit (еще раз!): Как указано в комментариях, и справедливо, такие вещи, как сгенерированные модели DTO и тому подобное, вероятно, являются исключениями из вышеприведенного, потому что они являются просто тупыми старыми корзинами для перемещения данных куда-то еще, плюс, поскольку инструмент создал их проверить их вообще бессмысленно.
/РЕДАКТИРОВАТЬ
Как правило, нет. Модульный тест должен использоваться для проверки функциональности блока. Методы тестирования модуля следует применять к классу, а не к отдельным автоматическим свойствам (если вы не переопределяете метод получения или установки с помощью пользовательского поведения).
Вы знаете, что присвоение строкового значения автоматическому строковому свойству будет работать, если вы получите правильный синтаксис и значение установщика, поскольку это является частью спецификации языка. Если вы этого не сделаете, вы получите ошибку во время выполнения, чтобы указать на ваш недостаток.
Модульные тесты должны быть предназначены для проверки на логические ошибки в коде, а не на что-то, что компилятор все равно поймает.
РЕДАКТИРОВАТЬ: В соответствии с моей беседой с автором принятого ответа на этот вопрос я хотел бы добавить следующее.
Я могу оценить, что пуристы TDD сказали бы, что вам нужно проверить автоматические свойства. Но, как разработчику бизнес-приложений, мне нужно взвесить разумное количество времени, которое я мог бы потратить на написание и выполнение тестов для "тривиального" кода, такого как автоматические свойства, по сравнению с тем, сколько времени разумно потребуется для устранения проблемы, которая может возникнуть из-за не тестирую В личном опыте большинство ошибок, возникающих в результате изменения тривиального кода, тривиально, чтобы исправить 99% времени. По этой причине я бы сказал, что положительные стороны только модульного тестирования неязыковой спецификации спецификаций перевешивают отрицательные.
Если вы работаете в быстро развивающейся бизнес-среде, в которой используется подход TDD, то частью рабочего процесса для этой команды должно быть только тестирование кода, который требует тестирования, в основном любой пользовательский код. Если кто-то зайдет в ваш класс и изменит поведение автоматического свойства, он несет ответственность за настройку модульного теста для него в этот момент.
Вы придерживаетесь строгой практики TDD или нет?
Если да, то вам обязательно следует написать тесты для общедоступных методов получения и установки, иначе как вы узнаете, правильно ли вы их реализовали?
Если нет, вам все еще, вероятно, следует написать тесты. Хотя реализация сегодня тривиальна, она гарантированно не останется такой, и без теста, охватывающего функциональность простой операции get / set, когда будущее изменение в реализации нарушает инвариант "установки свойства Foo со значением Bar, результатом которого является геттер для свойства Foo, возвращающий значение Bar ", модульные тесты продолжат проходить. Сам тест также тривиально реализован, но защищает от будущих изменений.
Я бы сказал нет. Если это не сработает, у вас есть большие проблемы. Я знаю, что нет. Теперь некоторые будут утверждать, что один только код гарантирует, что тест не пройден, например, если свойство было удалено. Но я бы положил деньги на то, что если свойство будет удалено, код модульного теста будет удален в рефакторе, так что это не будет иметь значения.
Согласно книге "Искусство модульного тестирования с примерами в.NET", модульное тестирование охватывает не любой тип кода, а фокусируется на логическом коде. Итак, что такое логический код?
Логический код - это любой фрагмент кода, в котором есть какая-то логика, какой бы маленькой она ни была. Это логический код, если он имеет одно или несколько из следующего: оператор IF, цикл, операторы switch или case, вычисления или любой другой тип кода принятия решения.
Обрабатывает ли простой метод получения / установки какую-либо логику? Ответ:
Свойства (методы получения / установки в Java) являются хорошими примерами кода, который обычно не содержит никакой логики и поэтому не требует тестирования. Но будьте осторожны: как только вы добавите любую проверку внутри свойства, вы захотите убедиться, что логика проверяется.
Я вижу, что объем модульного тестирования (или тестирования в целом) зависит от того, насколько вы уверены, что код работает так, как задумано, и каковы шансы его взлома в будущем.
Если у вас более низкая достоверность взлома кода (возможно, из-за того, что код получен из-под контроля и затраты на построчную проверку высоки), возможно, подходят свойства модульного тестирования.
Однажды, что вы можете сделать, это написать вспомогательный класс, который может просмотреть все свойства get/set класса, чтобы проверить, что они по-прежнему ведут себя как задумано.
Если свойства не выполняют какую-либо другую логику, то нет.
Да, это похоже на модульное тестирование языка. В противном случае было бы совершенно бессмысленно тестировать простые автоматически реализуемые свойства.
Мой ответ с точки зрения бывшего менеджера по тестированию и в настоящее время с точки зрения менеджера по разработке (ответственного за своевременную и качественную доставку программного обеспечения). Я вижу, что люди упоминают прагматизм. Прагматизм не очень хороший советчик, потому что он может сочетаться с ленью и / или нехваткой времени. Это может привести вас на неверный путь. Если вы упоминаете прагматизм, вы должны быть осторожны, чтобы держать свои намерения на пути профессионализма и здравого смысла. Требуется смирение, чтобы принять ответы, потому что они могут не соответствовать тому, что вы хотите услышать.
С моей точки зрения, важно следующее:
- Вы должны найти дефект как можно раньше. Для этого вы должны применить правильную стратегию тестирования. Если это тестирование свойств, то вы должны проверить свойства. Если нет, то не делай этого. Оба идут с ценой.
- Ваше тестирование должно быть легким и быстрым. Большая часть (модуль, интеграция и т. Д.) Кода, тестируемого во время сборки, тем лучше.
- Вы должны выполнить анализ основных причин, чтобы ответить на вопросы ниже и защитить свою организацию от текущего типа ошибок. Не волнуйтесь, возникнет другой тип дефекта, и всегда будут уроки, которые нужно извлечь.
- в чем причина?
- как избежать этого в следующий раз?
- Другой аспект - это стоимость создания / поддержки тестов. Не тестировать свойства, потому что их скучно поддерживать, и / или у вас есть сотни свойств, просто смешно. Вы должны создать / применить инструменты, которые делают работу лесоруба вместо человека. В общем, вы всегда должны улучшать свое окружение, чтобы быть более эффективным.
- то, что говорят другие, не является хорошим консультантом - не имеет значения, было ли это сказано Мартином Фаулером или Симаном - среда, в которой они находятся, я уверен, что она не такая, как у вас. Вы должны использовать свои знания и опыт, чтобы настроить то, что хорошо для вашего проекта и как сделать его лучше. Если вы примените вещи, потому что они были сказаны людьми, которых вы уважаете, даже не подумав об этом, вы окажетесь в глубокой беде. Я не говорю, что вам не нужны советы и / или помощь или мнение других людей, вы должны применять здравый смысл, чтобы применять их.
- TDD не отвечает на два важных вопроса, однако BDD дает ответы на вопросы ниже. Но, если вы будете следовать только одному, у вас не будет доставки в срок и качество. Так что не имеет значения, являетесь ли вы пуристом парнем TDD или нет.
- что должно быть проверено? (говорит, что все должно быть проверено - неправильный ответ на мой взгляд)
- когда тестирование должно быть закончено?
В общем, нет хорошего ответа. Просто на другие вопросы, на которые вы должны ответить, чтобы получить тот временный момент, когда вы сможете решить, нужен он или нет.