Можно ли улучшить эти модульные тесты в стиле тестирования строк, чтобы они соответствовали хорошим методам проектирования TDD? - PullRequest
1 голос
/ 28 октября 2011

Можно ли улучшить следующий юнит-тест в соответствии с хорошими методами проектирования TDD (именование, использование тестов строк, проектирование классов) в любой из платформ .NET TDD / BDD?

Кроме того, есть ли лучший способ в любой из фреймворков иметь тесты строк, где я могу иметь индивидуальное ожидание для каждой строки, как я это делаю в этом (NUnit) примере?

Тестируемая система - это класс Constraint, который может иметь несколько диапазонов допустимых целых чисел. Тестовый метод NarrowDown, который может уменьшить допустимые диапазоны на основе другого ограничения.

[TestFixture]
internal class ConstraintTests
{
    [Test]
    public void NarrowDown_Works()
    {
        RowTest_NarrowDown(
            new Range[] { new Range(0, 10), new Range(20, 30), new Range(40, 50) },
            new Range[] { new Range(1, 9), new Range(21, 29), new Range(41, 49) },
            new Range[] { new Range(1, 9), new Range(21, 29), new Range(41, 49) });

        RowTest_NarrowDown(
            new Range[] { new Range(0, 10), new Range(20, 30), new Range(40, 50), new Range(60, 70) },
            new Range[] { new Range(1, 9), new Range(21, 29), new Range(41, 49) },
            new Range[] { new Range(1, 9), new Range(21, 29), new Range(41, 49) });

        RowTest_NarrowDown(
            new Range[] { new Range(0, 10), new Range(20, 30), new Range(40, 50) },
            new Range[] { new Range(1, 9), new Range(21, 29), new Range(41, 49), new Range(60, 70) });
    }

    private static void RowTest_NarrowDown(IEnumerable<Range> sut, IEnumerable<Range> context)
    {
        Constraint constraint = new Constraint(sut);
        Constraint result = constraint.NarrowDown(new Constraint(context));
        Assert.That(result, Is.Null);
    }

    private static void RowTest_NarrowDown(IEnumerable<Range> sut, IEnumerable<Range> context, IEnumerable<Range> expected)
    {
        Constraint constraint = new Constraint(sut);
        Constraint result = constraint.NarrowDown(new Constraint(context));
        Assert.That(result, Is.Not.Null);
        Assert.That(result.Bounds, Is.EquivalentTo(expected));
    }
}

Ответы [ 2 ]

2 голосов
/ 28 октября 2011

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

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

Ваше построение тестовых данных довольно сложное, рассмотрите возможность использования matchers подобно NHamcrest для уменьшения суммыданных утверждения, которые вам нужны вместо использования Is.EquivalentTo.

Вы также можете использовать конструкторы или конструкторы фабрики, чтобы упростить инициализацию для класса Constraint, а не передавать его вмассив Ranges.

0 голосов
/ 30 октября 2011

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

[TestFixture]
internal class ConstraintTests
{
    static object[] TwoRanges = 
    {
        new object[]
            {
                new[] { new Range(0, 10), new Range(20, 30), new Range(40, 50) },
                new[] { new Range(1, 9), new Range(21, 29), new Range(41, 49), new Range(60, 70) }
            }
    };

    static object[] ThreeRanges = 
    {
        new object[]
            {
                new[] { new Range(0, 10), new Range(20, 30), new Range(40, 50) },
                new[] { new Range(1, 9), new Range(21, 29), new Range(41, 49) },
                new[] { new Range(1, 9), new Range(21, 29), new Range(41, 49) }
            },
        new object[]
            {
                new[] { new Range(0, 10), new Range(20, 30), new Range(40, 50), new Range(60, 70) },
                new[] { new Range(1, 9), new Range(21, 29), new Range(41, 49) },
                new[] { new Range(1, 9), new Range(21, 29), new Range(41, 49) }
            }
    };

    [Test, TestCaseSource("TwoRanges")]
    public void NarrowDown_WhenCalledWithTwoRanges_GivesTheExpectedResult(IEnumerable<Range> sut, IEnumerable<Range> context)
    {
        Constraint constraint = new Constraint(sut);
        Constraint result = constraint.NarrowDown(new Constraint(context));
        Assert.That(result, Is.Null);
    }

    [Test, TestCaseSource("ThreeRanges")]
    public void NarrowDown_WhenCalledWithThreeRanges_GivesTheExpectedResult(IEnumerable<Range> sut, IEnumerable<Range> context, IEnumerable<Range> expected)
    {
        Constraint constraint = new Constraint(sut);
        Constraint result = constraint.NarrowDown(new Constraint(context));
        Assert.That(result, Is.Not.Null);
        Assert.That(result.Bounds, Is.EquivalentTo(expected));
    }
}

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

HTH!

...