2009-10-02 17 views
10

Допустим, я, например, иметь этот класс, который генерирует последовательность чисел Фибоначчи:C#: Как вы тестируете метод 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(); 
    } 
} 

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

[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() не тестировался, и мое освещение будет ниже, чем это действительно необходимо. Справедливо. Но как я должен проверить этот метод?

Как вы обычно справляетесь с этим?

+0

Хмм, из любопытства, как вы проверяете покрытие для испытаний? Похоже на интересную особенность. – Ian

+1

Да, я тоже об этом задумался, хе-хе. Но нашел в нем кнопку в TestDriven.Net, которая, кстати, довольно удивительна. Если вы еще не пробовали, вы должны! После его установки вы можете щелкнуть правой кнопкой мыши по вашему решению (в проводнике решений) и выбрать Test With -> Coverage. Легко, как это :) – Svish

+0

Если у вас есть версия VS Team System, инструменты тестирования включают в себя инструмент покрытия, который вы можете запускать с помощью TestDriven.Net или в обычном интерфейсе. В противном случае, если вы используете инструменты для тестирования Google для Visual Studio, их несколько. NCover может быть наиболее часто используемым. – McMuttons

ответ

11

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.

Я не уверен, что я потрудился хотя ...

+1

Нет - я проверил, и 'Cast ' фактически проверяет через 'as' для' IEnumerable ', поэтому вы будете использовать' IEnumerable .GetEnumerator() ', а не' IEnumerable.GetEnumerator() ' –

+0

Это то, что я тоже видел. Тогда я не совсем понял, как это сделать, хе-хе. – Svish

+0

Исправлено, спасибо, ребята, это случай обертывания сильной версии в слабом ... –

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()); 
+1

Но это просто сравнило бы количество элементов в перечислимых числах, не так ли? И это будет работать плохо в моем случае, поскольку FibonacciSequence никогда не заканчивается: p – Svish

+0

Lol! Да, я понимаю вашу точку зрения. Но то, что я пытаюсь выделить, работает с 'IEnumerable', а не' IEnumerable '- и я не думаю, что вы можете просто использовать' Cast ', 'cos он выглядит ... –

4

Я бы не проверить его. Я попытался бы отфильтровать метод из инструмента покрытия. Я думаю, что освещение должно проверять вещи, которые я хочу охватить, и не все. Из других комментариев вы, кажется, используете TestDriven.Net. Я не знаю, насколько хорошо эти фильтры, но это возможно с помощью NCover. Вы также можете попробовать PartCover.

+0

Конечно, и я не избиваю себя над этим или чем-то еще. Просто любопытно посмотреть, как другие справляются с этим :) – Svish

+0

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

Смежные вопросы