Лучшие практики для нескольких утверждений на одном и том же результате в C # - PullRequest
10 голосов
/ 14 января 2010

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

[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));
    }
}

Ответы [ 4 ]

15 голосов
/ 14 января 2010

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

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

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

3 голосов
/ 14 января 2010

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

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

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

Кроме того, вы можете заключить связанные утверждения в один метод. это полезно по обычным СУХИМЫМ причинам, если вы используете его более одного раза, но в остальном я не вижу большой разницы.

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

2 голосов
/ 29 мая 2010

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

[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 голосов
/ 23 июня 2010

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

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

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

Assert.True(list.IsEmpty());

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

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

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

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

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

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

...