Нещодавно я натрапив на якийсь нещодавно написаний код, який перемішувався з великою кількістю Debug.Assert (C #).
Чи повинні ми все ще широко використовувати це, незважаючи на використання TDD, BDD та Unit Testing в цілому?
Нещодавно я натрапив на якийсь нещодавно написаний код, який перемішувався з великою кількістю Debug.Assert (C #).
Чи повинні ми все ще широко використовувати це, незважаючи на використання TDD, BDD та Unit Testing в цілому?
Відповіді:
Я не бачу жодної причини, чому ви не повинні використовувати Assert. Тим самим ви вже визнали потребу в охоронцях, як-от передумови та інваріанти, і робите рух у напрямку проектування за контрактом . Затвердження - це лише один із способів досягнення цього ...
// Precondition using Asert
void SomeMethod(Foo someParameter)
{
Debug.Assert(someParameter != null)
}
// Precondition using If-Then-Throw
void SomeMethod(Foo someParameter)
{
if (someParameter == null)
throw new ArgumentNullException("someParameter");
}
// Precondition using Code Contracts
void SomeMethod(Foo someParameter)
{
Contract.Requires(someParameter != null);
}
// Precondition using some custom library
void SomeMethod(Foo someParameter)
{
Require.ArgumentNotNull(() => someParameter);
}
Усі способи досягнення одного і того ж: надійність у коді. Це просто зводиться до вибору варіанту, з яких Assert є правильним вибором.
Зауважте, що я досі не згадував одиничні тести, оскільки вони виконують щось зовсім інше. Тест одиниці формально доводить надійність коду, здійснюючи охорону:
[Test]
void SomeMethod_WhenGivenNull_ThrowsArgumentNullException()
{
delegate call = () => someObject.SomeMethod(null);
Assert.That(call).Throws<ArgumentNullException>();
}
Це зовсім інший вид твердження ...
** Зауважте, що в деяких рамках фактично досить складно провести тест на збій твердження, оскільки помилка твердження може знизити весь час виконання, тому один із інших варіантів може бути кращим ... *
Я розглядаю Debug.Assert як передчасну оптимізацію в наш час. Якщо вам дійсно не потрібна продуктивність, придушення Assert в режимі випуску може приховувати помилки довше.
Як зазначає MattDavey, кодові контракти можуть бути вищими, забезпечуючи статичну перевірку замість динамічної перевірки, і якщо такої немає, я б вважав за краще Trace.Assert або звичайний старийif(x) throw SomeException;
Debug
класу можуть бути пропущені з компіляції ... тому придушення викликів Assert
просто для продуктивності - це не просто передчасна оптимізація, це проста дурниця.