2010-01-14 3 views
10

Как вы считаете, самый чистый способ сделать несколько утверждений на результат? Раньше я тестировал все те же тесты, но это начинает чувствовать себя немного грязным, я просто играл с другой идеей, используя настройку.Рекомендации по нескольким утверждениям по одному и тому же результату в C#

[TestFixture] 
public class GridControllerTests 
{ 
    protected readonly string RequestedViewId = "A1"; 

    protected GridViewModel Result { get; set;} 

    [TestFixtureSetUp] 
    public void Get_UsingStaticSettings_Assign() 
    { 
     var dataRepository = new XmlRepository("test.xml"); 

     var settingsRepository = new StaticViewSettingsRepository(); 

     var controller = new GridController(dataRepository, settingsRepository); 

     this.Result = controller.Get(RequestedViewId); 

    } 

    [Test] 
    public void Get_UsingStaticSettings_NotNull() 
    { 
     Assert.That(this.Result,Is.Not.Null); 
    } 

    [Test] 
    public void Get_UsingStaticSettings_HasData() 
    { 
     Assert.That(this.Result.Data,Is.Not.Null); 
     Assert.That(this.Result.Data.Count,Is.GreaterThan(0)); 
    } 

    [Test] 
    public void Get_UsingStaticSettings_IdMatches() 
    { 
     Assert.That(this.Result.State.ViewId,Is.EqualTo(RequestedViewId)); 
    } 

    [Test] 
    public void Get_UsingStaticSettings_FirstTimePageIsOne() 
    { 
     Assert.That(this.Result.State.CurrentPage, Is.EqualTo(1)); 
    } 
} 

ответ

3

Что вам нужно соблюдать это образец Arrange, Act, Assert (а затем закончить тест). В вашем случае все расположение находится в TestFixtureSetUp, равно как и тестируемое действие. Я бы немного перестроил это, это может стать громоздким, когда у вас будет больше тестов. Как отмечает Докерс, следует избегать тяжелых тестовых установок, они могут стать проблемами - они «подходят для всех» по всем тестам в классе и поэтому могут стать тяжелее, чем требуется большинству тестов.

Если у вас возникло соблазн перейти к следующему действию, а затем еще несколько утверждений, поместите это в отдельный тест.

У меня нет проблем с размещением нескольких утверждений в одном и том же тесте, если они вносят вклад в тестирование одной и той же вещи (т. Е. Являются частью одного и того же «логического утверждения»). В этом случае любое количество утверждений о содержимом этого файла .Result.Data было бы в порядке, я бы просмотрел одно и то же значение результата. Ваш Get_UsingStaticSettings_HasData делает это очень четко. Лучше всего использовать уникальное сообщение об ошибке для каждого утверждения, чтобы было легче сказать, какой из утверждений не прошел.

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

В сводке
* Выполните одно действие на тест
* После того, как действие, использовать как многие связанные утверждает, как вам нужно, чтобы проверить одну вещь
* Завершение теста там.

15

Наличие нескольких утверждений в одном тесте может привести к Assertion Roulette, так что это то, о чем вы всегда должны быть осторожны.

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

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

+0

«Логические утверждения» - хорошее слово для этого. Интересно, что пример Assertion Roulette является, по сути, примером того, как «ошибиться, не делая Arrange-Act-Assert». Различаются ли понятия? – Anthony

+0

@ Энтони: понятия различаются, хотя они тесно связаны между собой. У вас гораздо меньше шансов почувствовать боль в Assertion Roulette, если вы будете следовать AAA (или четырехфазному тесту, как это делают тестовые шаблоны xUnit), но я все равно буду отличаться от полностью несвязанных утверждений в том же блоке Assert. –

+3

Идею Assertion Roulette можно свести к минимуму в NUnit, указав комментарий в утверждении Assert. Вместо того, чтобы делать «Assert.That (condition)« use »Assert.That (condition, failureMessage)», где «failMessage» - это информация о проверке Assert. Это позволит вам точно знать, какой из утверждений в рамках единичного теста не удался. – Pedro

2

Вы можете использовать Oapt - An NUnit надстройку для запуска Один Assert на тест:

[TestFixture] 
public class GridControllerTests 
{ 
    [TestCase, ForEachAssert] 
    public void Get_UsingStaticSettings_Assign() 
    { 
     var dataRepository = new XmlRepository("test.xml"); 
     var settingsRepository = new StaticViewSettingsRepository(); 
     var controller = new GridController(dataRepository, settingsRepository); 

     var result = controller.Get("A1"); 

     AssertOne.From(
     () => Assert.That(this.Result,Is.Not.Null), 
     () => Assert.That(this.Result.Data,Is.Not.Null), 
     () => Assert.That(this.Result.Data.Count,Is.GreaterThan(0)), 
     () => Assert.That(this.Result.State.ViewId,Is.EqualTo(RequestedViewId)), 
     () => Assert.That(this.Result.State.CurrentPage, Is.EqualTo(1))); 
    } 
} 

Это создаст 5 различных тестовых случаев, по одному для каждого утверждают.

0

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

AssertThatMyObjectMatches(field1, field2, field3, field4, myObject); 

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

Assert.True(list.IsEmpty()); 

list.Add(new Thing()); 
Assert.False(list.IsEmpty()); 

Другие, в том числе большая часть сообщества Ruby, имеют другое мнение по этому поводу.Это в основном за счет блоге Дейва Astels', здесь:

http://www.artima.com/weblogs/viewpost.jsp?thread=35578

Я считаю „Одно утверждение на тест“ метод очень полезно для таких вещей, как проверка, где каждый маленький аспект является ценным. В противном случае я об этом не беспокоюсь.

Что бы ни работало для вас и вашей команды, это, вероятно, правильный путь. Я, как правило, делаю все, что кажется простым и легким в изменении, чтобы быть верным позже, когда у меня есть лучшее представление о том, что правильно. Я также поставил много комментариев уровня Given/When/Then в более сложных примерах и разбил класс, если он становится слишком сложным для понимания.

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