Можно ли улучшить эти модульные тесты в стиле тестирования строк, чтобы они соответствовали хорошим методам проектирования TDD?
Можно ли улучшить следующие юнит-тесты, следуя хорошим методам проектирования 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 ответа
Вы должны использовать управляемый данными подход с фабриками данных (в 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));
}
}
Видите, насколько теперь ваши методы испытаний стали проще? Кроме того, это приведет к тому, что каждый набор данных из исходного источника тестового примера будет запущен в отдельном тесте, поэтому все это не будет сбоем только потому, что один набор данных вызывает сбой. Помните: тест должен утверждать только одно.
НТН!
Во-первых, вы можете улучшить название вашего юнит-теста NarrowDown_Works
очень расплывчато, и я не могу сказать, что должен делать тестируемый класс.
У вас много утверждений и много данных, я не могу сказать, что важно. Попробуйте разбить ваш тест на более мелкие тесты, и их будет проще назвать. Если возможно, используйте одно утверждение на тест.
Построение тестовых данных довольно сложно, рассмотрите возможность использования таких сопоставлений, как NHamcrest, чтобы уменьшить объем необходимых данных подтверждения вместо использования Is.EquivalentTo
,
Вы также можете использовать конструктор или фабричные конструкторы, чтобы упростить инициализацию для Constraint
класс проще, чем передавать в массиве Ranges
,