С#: Как вы тестируете метод IEnumerable.GetEnumerator()?
Скажем, например, у меня есть этот класс, который генерирует числа Фибоначчи:
public class FibonacciSequence : IEnumerable<ulong>
{
public IEnumerator<ulong> GetEnumerator()
{
var a = 0UL;
var b = 1UL;
var c = a + b;
while (true)
{
yield return c;
c = a + b;
a = b;
b = c;
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
Затем я могу написать тест, который гарантирует, что n первых чисел в последовательности верны.
[Test]
public void GetEnumerator_FirstFifteenNumbers_AreCorrect()
{
var sequence = new FibonacciSequence().Take(15).ToArray();
CollectionAssert.AreEqual(sequence, new[] {1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610});
}
Когда я проверяю наличие покрытия, я увижу, что метод IEnumerable.GetEnumerator() не проверен, и мой охват будет ниже, чем это действительно нужно. Справедливо. Но как я должен проверить этот метод?
Как вы обычно справляетесь с этим?
Ответы
Ответ 1
EDIT: Обновлено на основе того, что сказал Марк.
Ну, вы можете получить покрытие, сделав:
// Helper extension method
public static IEnumerable AsWeakEnumerable(this IEnumerable source)
{
foreach (object o in source)
{
yield return o;
}
}
...
[Test]
public void GetEnumerator_FirstFifteenNumbers_AreCorrect()
{
IEnumerable weak = new FibonacciSequence().AsWeakEnumerable();
var sequence = weak.Cast<int>().Take(15).ToArray();
CollectionAssert.AreEqual(sequence,
new[] {1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610});
}
Обратите внимание, что weak
объявляется неродным IEnumerable
типом... что означает, что вам нужно вызвать Cast
на нем, чтобы передать каждый возвращенный объект в int
.
Я не уверен, что буду беспокоиться, хотя...
Ответ 2
Я бы не стал его тестировать. Я попытался бы отфильтровать метод из инструмента покрытия. Я думаю, что освещение должно проверять вещи, которые я хочу охватить, и не все. Из других комментариев вы, кажется, используете TestDriven.Net. Я не знаю, насколько хорошо эти фильтры, но это возможно с помощью NCover. Вы также можете попробовать PartCover.
Ответ 3
Вам понадобится использовать IEnumerable
(не общий); Я отправил ответ с помощью Cast<T>
, но это все равно будет обманывать (он проверял нужный тип как специальный случай) - вам может понадобиться что-то вроде:
public static int CountUntyped(this IEnumerable source) {
int count = 0;
foreach(object obj in source) { count++; }
return count;
}
IEnumerable<T> source = ...
Assert.AreEqual(typed.Count(), source.CountUntyped());