Как предотвратить 'излишнее тестирование' в тестовом сценарии? (C#/nUnit)

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

[Test]
public void TestNamePropertyCorrectlySetOnInstantiation()
{
  MyClass myInstance = new MyClass("Test name");
  Assert.AreEqual("Test Name", myInstance.Name);
}

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

Я осуществил рефакторинг его как это:

[Test]
public void TestNamePropertyCorrectlySetOnInstantiation()
{
  MyClass myInstance;
  string namePropertyValue;

  Assert.DoesNotThrow(() => myInstance = new MyClass("Test name"));
  Assert.DoesNotThrow(() => namePropertyValue = myInstance.Name);
  Assert.AreEqual("Test Name", namePropertyValue);
}

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

7
задан Flynn1179 23 July 2010 в 09:20
поделиться

4 ответа

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

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

12
ответ дан 6 December 2019 в 19:31
поделиться

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

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

[Test]
public void TestInvalidNameThrowsException {
  MyClass myInstance;
  string namePropertyValue;
  Assert.Throws(() => myInstance = new MyClass(null));
  Assert.Throws(() => myInstance = new MyClass("INVALID_NAME_125356232356"));
}

(например, я не знаю C# ни капли, но вы должны понять идею)

.
0
ответ дан 6 December 2019 в 19:31
поделиться

Я действительно не понимаю, что вы имеете в виду под избыточным тестированием ИМО, избыточное тестирование - это что-то вроде попытки протестировать частные методы.

Я считаю свои тесты документированием кода. Итак, если у меня есть более одного утверждения в операторе, то есть большая вероятность, что я могу реорганизовать тестируемый метод на несколько более мелких методов или иногда я разбиваю свой тестовый метод на несколько разных методов тестирования. Следование правилу one-assert-per-test позволяет вам иметь разумные имена тестовых методов, которые, в свою очередь, формируют документацию вашего кода. Я придерживаюсь соглашения об именах для методов тестирования: methodName_scenario_expectation (из книги Роя Ошерова Искусство модульного тестирования ). Итак, мы также думаем о документации кода. Вы думаете, что утверждение assert (помимо проверки ожидания) поможет вам / другому разработчику лучше понять код, а затем напишите это assert. Но, повторюсь еще раз, всегда проверяйте правильность названий методов тестирования.

1
ответ дан 6 December 2019 в 19:31
поделиться

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

0
ответ дан 6 December 2019 в 19:31
поделиться
Другие вопросы по тегам:

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