Подтвердить что ты не робот

Должны ли вы Unit Test простые свойства?

Должны ли вы Unit Test простые свойства класса, утверждая, что значение установлено и извлекается? Или это действительно просто модульная проверка языка?

Пример

public string ConnectionString { get; set; }

Test

public void TestConnectionString()
{
    var c = new MyClass();
    c.ConnectionString = "value";

    Assert.Equal(c.ConnectionString, "value");
}

Я думаю, я не вижу в этом значения.

4b9b3361

Ответ 1

Я бы предположил, что вам абсолютно необходимо.

  • Что такое авто-собственность сегодня, может закончиться тем, что завтра будет поле поддержки, а не вам...

  • Аргумент о том, что "вы просто проверяете компилятор или фреймворк", является немного соломеном imho; то, что вы делаете, когда вы проверяете авто-свойство, с точки зрения вызывающего, тестирует публичный "интерфейс" вашего класса. Вызывающий не имеет понятия, является ли это свойством auto с созданным фреймворком хранилищем или если в геттере/сеттере имеется миллион строк сложного кода. Поэтому вызывающий тестирует контракт, подразумеваемый этим свойством, - что если вы поместите X в поле, вы можете получить X позже.

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

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

  • Если вы делаете чистую TDD, то это заставляет вас остановиться на мгновение и подумайте, есть ли у него свойство auto 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;
}

Вы мгновенно знаете, что они что-то сломали?

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

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

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

EDIT: в соответствии с различными цепочками в этом потоке я хотел бы указать, что тест для свойства read-write смехотворно прост:

[TestMethod]
public void PropertyFoo_StoresCorrectly()
{
   var sut = new MyClass();
   sut.Foo = "hello";
   Assert.AreEqual("hello", sut.Foo, "Oops...");
}

edit: И вы даже можете сделать это в одной строке в соответствии с маркой Seeman Autofixture

Я бы сказал, что если вы обнаружите, что у вас есть такое большое количество публичных свойств, чтобы сделать 3 строки, подобные приведенным выше, для каждой из них, тогда вы должны допросить свой дизайн; Если вы полагаетесь на другой тест, чтобы указать на проблему с этим свойством, то либо

  • Тест на самом деле проверяет это свойство, или
  • Вы проведете больше времени, проверяя, что этот другой тест терпит неудачу, потому что свойство неверно (через отладчик и т.д.), чем вы бы потратили на ввод текста в указанном выше коде.
  • Если какой-либо другой тест позволяет вам сразу сказать, что свойство виновато, это не unit test!

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

/EDIT

Ответ 2

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

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

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

EDIT: согласно моему разговору с автором принятого ответа на этот вопрос, я хотел бы добавить следующее.

Я могу оценить, что пуристы TDD говорят, что вам нужно протестировать автоматические свойства. Но, как разработчик бизнес-приложений, мне нужно взвешивать, разумно количество времени, которое я мог потратить на написание и выполнение тестов на "тривиальный" код, например, на автоматические свойства по сравнению с тем, как долго он мог бы разумно исправить проблему, которая может возникнуть из не тестирование. В личном опыте большинство ошибок, возникающих при изменении тривиального кода, тривиальны, чтобы исправить 99% времени. По этой причине я бы сказал, что положительные результаты только модульного тестирования неязыковых спецификаций перевешивают негативы.

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

Ответ 3

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

Ответ 4

Вы придерживаетесь строгих правил TDD или нет?

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

Если нет, вы, вероятно, должны написать тесты. Хотя реализация тривиальна сегодня, не гарантируется, что она останется такой, и без теста, охватывающего функциональность простой операции get/set, когда будущее изменение в реализации нарушает инвариант "свойства настройки Foo со значением Bar, приводит к getter для свойства Foo, возвращающего значение Bar," модульные тесты будут продолжать проходить. Сам тест также реализуется тривиально, но защищает от будущих изменений.

Ответ 5

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

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

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

Ответ 6

Если свойства не выполняют какую-либо другую логику, тогда нет.

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

Ответ 7

Согласно книге "Тестирование модульного тестирования с примерами в .NET" , unit test охватывает не любой тип кода, он фокусируется в логическом коде. Итак, что такое логический код?

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

Использует ли простой геттер/сеттер любую логику? Ответ:

Свойства (getters/seters в Java) являются хорошими примерами кода, который обычно не содержит никакой логики, и поэтому не требует тестирования. Но не обращайте внимания: как только вы добавите чек внутри объекта, вы захотите убедитесь, что логика протестирована.

Ответ 8

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

С моей точки зрения важны следующие:

  • вы должны найти дефект как можно раньше. Для этого вам необходимо применить надлежащую стратегию тестирования. Если это тестовые свойства, вам необходимо проверить свойства. Если нет, то не делайте этого. Оба имеют цену.
  • Ваше тестирование должно быть простым и быстрым. Чем больше часть (единица измерения, интеграция и т.д.) Кода, проверенного временем сборки, тем лучше.
  • вам следует сделать анализ причинно-следственных связей, чтобы ответить на приведенные ниже вопросы и сделать вашу организацию защищенной от текущего типа ошибки. Не волнуйтесь, появится другой тип дефекта, и всегда будут извлечены уроки.
    • Какова основная причина?
    • как его избежать в следующий раз?
  • Еще один аспект - это затраты на создание/поддержание тестов. Не тестировать свойства, потому что они скучны для поддержания и/или у вас есть сотни свойств, это смешно. Вы должны создавать/применять инструменты, которые делают деревообрабатывающую работу вместо человека. В общем, вы всегда должны улучшить свою среду, чтобы быть более эффективной.
  • то, что другие говорят, не являются хорошим советником - неважно, было ли это сказано Мартином Фаулером или Симаном - среда, в которой они находятся, я почти уверен, что вы не те, что вы есть. Вы должны использовать свои знания и опыт настроить то, что хорошо для вашего проекта, и как сделать его лучше. Если вы применяете вещи, потому что они были произнесены людьми, которых вы уважаете, даже не задумываясь об этом, вы окажетесь в глубоких бедах. Я не говорю, что вам не нужны советы и/или помощь другим людям или мнение, вы должны применять здравый смысл для их применения.
  • TDD не отвечает на два важных вопроса, однако BDD дает вам ответы на вопросы ниже. Но, если вы будете следовать только одному, у вас не будет своевременной доставки и качества. Так что неважно, являетесь ли вы пуристским парнем TDD или нет.
    • что нужно проверить? (он говорит, что все должно быть проверено - неправильный ответ, на мой взгляд)
    • когда тестирование должно быть завершено?

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