Должны ли мы писать единичный тест для геттера, который получает другой объект? [Дубликат]

Примером этого исключаемого исключения является: Когда вы пытаетесь проверить что-то, это null.

Например:

string testString = null; //Because it doesn't have a value (i.e. it's null; "Length" cannot do what it needs to do)

if (testString.Length == 0) // Throws a nullreferenceexception
{
    //Do something
} 

Время выполнения .NET исключение NullReferenceException при попытке выполнить действие над чем-то, что не было инстанцировано, т.е. код выше.

По сравнению с ArgumentNullException, которое обычно выбрано как защитная мера, если метод ожидает, что то, что происходит

Дополнительная информация находится в C # NullReferenceException и Null Parameter .

105
задан skaffman 1 June 2011 в 08:04
поделиться

10 ответов

Я бы сказал, нет.

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

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

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

133
ответ дан skaffman 25 August 2018 в 06:09
поделиться

tl; dr: Да вы должны , а с OpenPojo тривиально.

  1. Вы должны сделайте некоторую проверку в своих геттерах и сеттерах, чтобы вы их тестировали. Например, setMom(Person p) не должен позволять устанавливать кого-либо моложе себя, как свою мать.
  2. Даже если вы сейчас ничего не делаете, вероятность того, что вы будете в будущем, тогда это будет полезно для регрессионного анализа. Если вы хотите разрешить настройкам матерей null, у вас должен быть тест для этого, если кто-то изменит это позже, это усилит ваши предположения.
  3. Общей ошибкой является void setFoo( Object foo ){ foo = foo; }, где она должна быть void setFoo( Object foo ){ this.foo = foo; }. (В первом случае foo, который записывается в параметр , а не поле foo объекта].
  4. Если вы возвращаете массив или коллекцию вы должны проверить, будет ли геттер собирать защитные копии данных, переданных в сеттер, перед возвратом.
  5. В противном случае, если у вас есть самые основные сеттеры / геттеры, а затем тестирование модулей, добавит, может быть, около 10 минут максимум для каждого объекта, так что же такое потеря? Если вы добавите поведение, у вас уже есть скелетный тест, и вы получите это регрессионное тестирование бесплатно. Если вы используете Java, у вас нет оправдания, так как есть OpenPojo . Существует уже существующий набор правил, которые вы можете включить, а затем просканировать весь свой проект с ними, чтобы убедиться, что они последовательно применяются в вашем коде.

Из своих примеров :

final PojoValidator pojoValidator = new PojoValidator();

//create rules
pojoValidator.addRule( new NoPublicFieldsRule  () );
pojoValidator.addRule( new NoPrimitivesRule    () );
pojoValidator.addRule( new GetterMustExistRule () );
pojoValidator.addRule( new SetterMustExistRule () );

//create testers
pojoValidator.addTester( new DefaultValuesNullTester () );
pojoValidator.addTester( new SetterTester            () );
pojoValidator.addTester( new GetterTester            () );

//test all the classes
for(  PojoClass  pojoClass :  PojoClassFactory.getPojoClasses( "net.initech.app", new FilterPackageInfo() )  )
    pojoValidator.runValidation( pojoClass );
19
ответ дан ArtB 25 August 2018 в 06:09
поделиться

Я сделал небольшой анализ охвата, достигнутого в самом коде JUnit .

Одна категория непокрытого кода «слишком проста для проверки» . Это включает в себя простые геттеры и сеттеры, которые разработчики JUnit делают not .

С другой стороны, JUnit не имеет метода (non-debrecated) длиной более 3 линии, которые не охватываются никаким тестом.

1
ответ дан avandeursen 25 August 2018 в 06:09
поделиться

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

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

Есть очевидные причины, по которым должны использоваться свойства чтения / записи, такие как свойства ViewModel, которые привязаны к полям ввода и т. Д.

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

  1. Вам не хватает тестов, которые косвенно используют свойства
  2. . Свойства unused

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

11
ответ дан bryanbcook 25 August 2018 в 06:09
поделиться

Если цикломатическая сложность геттера и / или сеттера равна 1 (что они обычно есть), тогда ответ не будет, вы не должны.

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

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

11
ответ дан Claus Jørgensen 25 August 2018 в 06:09
поделиться

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

Кроме того, если вы используете отчет о покрытии кода, подобный нам, вы можете добавить атрибут [ExcludeFromCodeCoverage]. Наше решение состояло в том, чтобы использовать это для моделей, которые имеют только свойства с использованием геттеров и сеттеров или самим свойством. Таким образом, это не повлияет на общий охват кода% при запуске отчета о покрытии кода, предполагая, что это то, что вы используете для расчета процентного охвата кода. Счастливое тестирование!

1
ответ дан Devin C 25 August 2018 в 06:09
поделиться

Рой Ошерове в своей знаменитой книге «Искусство модульного тестирования» говорит:

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

27
ответ дан ib. 25 August 2018 в 06:09
поделиться

Да, но не всегда в изоляции

Позвольте мне уточнить:

Что такое единичный тест?

Из Эффективно работает с устаревшим кодом 1:

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

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

Что такое хороший тест?

Все требования и тесты следуют форме Логика Хора :

{P} C {Q}

Где:

  • {P} является предварительным условием (, данным )
  • C является (, когда )
  • {Q} является постусловием (, затем )

Затем следует максим :

Тестирование, а не реализация

Это означает, что вы не должны проверять, как C достигает пост-состояния, вы должны проверить, что {Q} является результатом C.

Когда дело доходит до ООП, C является классом. Таким образом, вы не должны тестировать внутренние эффекты, а только внешние эффекты.

Почему бы не тестировать получатели и сеттеры в изоляции

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

Итак, вы должны 't тестирует получателей и сеттеров в изоляции. Это плохо:

Describe 'LineItem class'

    Describe 'setVAT()'

        it 'should store the VAT rate'

            lineItem = new LineItem()
            lineItem.setVAT( 0.5 )
            expect( lineItem.vat ).toBe( 0.5 )

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

Как вы должны тестировать геттеры и сеттеры?

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

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

Например:

Describe 'LineItem class'

    Describe 'getGross()'

        it 'should return the net time the VAT'

            lineItem = new LineItem()
            lineItem.setNet( 100 )
            lineItem.setVAT( 0.5 )
            expect( lineItem.getGross() ).toBe( 150 )

Вы можете подумать для себя:

Подождите секунду, мы тестируем getGross() здесь not setVAT().

Но если setVAT(), что тест все равно потерпит неудачу.

1Feathers, M., 2004. Эффективно работает с устаревшим кодом. Prentice Hall Professional.

2Martin, R.C., 2009. Clean code: руководство по гибкому программному мастерству. Образование Пирсона.

27
ответ дан Izhaki 25 August 2018 в 06:09
поделиться

Юмористический, но мудрый прием: Путь Testivus

«Напишите тест, который вы можете сегодня»

Тестирование геттеров / сеттеров может быть чрезмерным если вы опытный тестер, и это небольшой проект. Однако, если вы только начинаете изучать модульный тест, или эти геттеры / сеттеры могут содержать логику (например, пример [Art_f []], то было бы неплохо написать тесты.

6
ответ дан muymoo 25 August 2018 в 06:09
поделиться

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

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

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

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

Еще одно: недавно работая в большом банке в Нидерландах, я заметил, что Sonar указала 100% -ный охват кода. Однако я знал, что чего-то не хватает. Проверяя процент заполнения кода на файл, он указал файл с меньшим процентом. Весь процент кодовой базы был таким большим, что в одном файле процент не отображался как 99,9%. Так что вы можете посмотреть на это ...

0
ответ дан Radboud 25 August 2018 в 06:09
поделиться
Другие вопросы по тегам:

Похожие вопросы: