Когда я использую VS для создания модульных тестов, у меня есть Assert.Inclusive для сгенерированных методов тестирования, и обычно я изменяю это утверждение так, чтобы что-то еще, когда я их работаю. Я использую вопросительные знаки Assert.Inconclusive в результатах теста в качестве маркеров, чтобы быстро сказать, какие тесты я еще не закончил.
Ну, это именно то, как я его использую. Из его названия «Неконкретный», я думаю, вы можете использовать, чтобы указать свое неопределенное состояние, пока вы документируете, что это значит.
Однако, из описания вашего метода Average()
, я думаю, что, возможно, ваш блок-тест не достаточно атомный, чтобы покрыть только один «блок», один конкретный сценарий. Иногда я пишу 2 или 3 единицы тестовых методов для одного метода. Или вы можете разбить свой метод Average()
на более мелкие методы, покрывающие отдельные обязанности. Таким образом, вы можете провести тестирование этих меньших методов перед тестированием устройства Average()
.
Johannes,
Это, как я бы реализовать Sum()
и Average()
методы.
public static class MyMath
{
private static void ValidateInput(ICollection<int> numbers)
{
if (numbers == null)
throw new ArgumentNullException("numbers", "Null input. Nothing to compute!");
if (numbers.Count == 0)
throw new ArgumentException("Input is empty. Nothing to compute!");
}
public static int Sum(int[] numbers)
{
ValidateInput(numbers);
var total = 0;
foreach (var number in numbers)
total += number;
return total;
}
public static double Average(int[] numbers)
{
ValidateInput(numbers);
return Sum(numbers)/numbers.Length;
}
}
Для простоты, я просто выбросить ArgumentException
исключения из метода ValidateInput(ICollection<int>)
. Вы также можете проверить возможность переполнения и выбросить OverflowException
в методе ValidateInput(ICollection<int>)
.
Сказанное, вот как бы я проверил функцию Average(int[])
.
[TestMethod]
public void AverageTest_GoodInput()
{
int[] numbers = {1, 2, 3};
const double expected = 2.0;
var actual = MyMath.Average(numbers);
Assert.AreEqual(expected, actual);
}
[TestMethod]
[ExpectedException(typeof(ArgumentNullException))]
public void AverageTest_NullInput()
{
int[] numbers = null;
MyMath.Average(numbers);
}
[TestMethod]
[ExpectedException(typeof(ArgumentException))]
public void AverageTest_EmptyInput()
{
var numbers = new int[0];
MyMath.Average(numbers);
}
С этими настройками тестов я могу быть уверен, что когда все тесты пройдут, моя функция верна. Ну, кроме случая переполнения. Теперь я могу вернуться к методу ValidateInput(ICollection<int>)
, чтобы добавить логику для проверки переполнения, а затем добавить еще один тест, чтобы ожидать, что OverflowException
будет выбрано для типов входов, которые вызывают переполнение. Или делайте это в обратном порядке, если вам нравится подход с использованием TDD.
Надеюсь, это поможет прояснить эту идею.
. Не могли бы вы рассказать о том, как вы подойдете к этому в этом очень особенном случае? –
Большое вам спасибо. поэтому, по сути, вы говорите, что нет необходимости писать явный тест для Sum(), но проверяя его через Average(). С точки зрения охвата кода это все равно приводит к такому же результату. –
Я бы также написал тесты для Sum(). Кто знает в мой сонный момент, я могу набрать «-» вместо «/». :) С тестами для Sum() на месте, если я получил все тесты для Sum(), но какой-то тест для Average() терпит неудачу, я могу быть очень уверен, что реализация для Average() неверна. Я не буду обвинять Sum() в том, что вы вызываете ошибку Average(). :) – tranmq