Мога ли да изключа част от метод от покритието на кода?

Подозирам, че отговорът е не, но все пак ще попитам...

TL;DR

Знам, че мога да изключа клас или метод от анализа на покритието с атрибута [ExcludeFromCodeCoverage], но има ли начин да изключа само част от метод?

Конкретен пример

Имам метод, който лениво генерира поредица от int.MaxValue елемента:

private static IEnumerable<TElement> GenerateIterator<TElement>(Func<int, TElement> generator)
{
    for (int i = 0; i < int.MaxValue; i++)
    {
        yield return generator(i);
    }
}

На практика той никога не се изброява напълно, така че краят на метода никога не се достига. Поради това DotCover счита, че 20% от метода не е покрит, и подчертава затварящата скоба като непокрита (което съответства на return false в генерирания MoveNext метод).

Бих могъл да напиша тест, който консумира цялата последователност, но отнема много време за изпълнение, особено с активирано покритие.

Така че бих искал да намеря начин да кажа на DotCover, че последната инструкция не е необходимо да се покрива.

Забележка: Знам, че наистина не е необходимо да имам целия код, обхванат от модулни тестове; някои части от код не могат или не трябва да бъдат тествани и обикновено изключвам тези с атрибута [ExcludeFromCodeCoverage]. Но ми харесва да имам 100% отчетено покритие за кода, който тествам, защото това улеснява откриването на нетествани части от кода. Да имаш метод с 80% покритие, когато знаеш, че няма какво повече да тестваш в него, е доста досадно...


person Thomas Levesque    schedule 08.06.2014    source източник
comment
Е, този метод е статичен, но бих помислил да намеря начин да заместя int.MaxValue, когато тествате с нещо управляемо, освен ако тази стойност действително не е подходяща по някакъв начин.   -  person Anthony Pegram    schedule 08.06.2014
comment
@AnthonyPegram, това е добра идея; стойността не е наистина уместна, просто искам последователност, която е практически безкрайна.   -  person Thomas Levesque    schedule 08.06.2014
comment
От друга страна, правенето на кода по-сложен, само за да се избегне непокрита затваряща скоба, не изглежда правилно...   -  person Thomas Levesque    schedule 08.06.2014
comment
Разбира се, разбирам аргумента срещу прекаленото инженерство. Все пак свойство на вътрешен статичен максимален брояч със стойност по подразбиране MaxValue може да помогне и няма да добави никаква реална значителна сложност. След това вашите тестове могат да се настройват и разрушават, като зададете работеща стойност и след това я нулирате, ако е приложимо. (Това също би изисквало излагане на вътрешни елементи на вашия проект за тестване на модули, ако още не сте го направили.) Както и да е, само една мисъл.   -  person Anthony Pegram    schedule 08.06.2014
comment
Ако трябваше да замените това с отложена LINQ заявка, това също ще работи ли за покритие на код? Тоест: return Enumerable.Range(0, int.MaxValue).Select(generator);? РЕДАКТИРАНЕ: По същество вие бихте прехвърлили отговорността за итерацията/самото предаване на LINQ кода, който няма да бъде отчетен от покритието на кода.   -  person Chris Sinclair    schedule 08.06.2014
comment
@AnthonyPegram, всъщност възприех различен подход: добавих параметър exclusiveUpperBound към метода GenerateIterator. Общественият Generate метод, който го извиква, преминава int.MaxValue, а тестът директно извиква GenerateIterator (който направих вътрешен) с друга стойност. Мисля, че е по-чист от променливото статично състояние... Както и да е, това решава проблема за този конкретен сценарий, но не и за общия случай, така че въпросът остава отворен;)   -  person Thomas Levesque    schedule 08.06.2014
comment
Аз разбирам, че. Аз лично не пиша твърде много статични методи, така че бих могъл просто да предам зависимост към самия клас, ако трябва, ако тестването иначе е проблематично (личен пример: код за тестване, който може да присвои текущата дата и час). Накарайте публичния конструктор да не се нуждае от зависимостта с вътрешен конструктор, който го приема (и публичният конструктор предава инстанция по подразбиране на вътрешния). Не съвсем същият подход тук, но от вашето описание изглежда достатъчно близо на ниво метод.   -  person Anthony Pegram    schedule 08.06.2014
comment
@ChrisSinclair, прав си! Не знам как го пропуснах; това очевидно е най-добрият начин да го направите. Но както и да е, въпросът все още стои, защото има други сценарии, при които бих искал да изключа части от методи...   -  person Thomas Levesque    schedule 08.06.2014


Отговори (2)


Не, няма начин да изключите „част от метод“ от анализа на покритието с dotCover.

В общия смисъл имате няколко опции:

  1. Извлечете непокритата част в нейния собствен метод, за да можете правилно да игнорирате този метод от анализа
  2. Игнорирайте проблема

В този случай може да има трети вариант. Тъй като вашият тестов код упражнява по-голямата част от вашия метод, може би трябва просто да напишете тестов метод, който гарантира, че кодът работи докрай?

person Lasse V. Karlsen    schedule 26.07.2014
comment
Имам итератор, който определено работи до завършване в foreach цикъл в единичен тест; все още не показва 100% покритие, не използва dotCover, а само вградения изследовател на тестове, и подчертава кода със същия ефект, показва последните две скоби, подчертани като непокрити. - person BrainSlugs83; 12.06.2015

Първо и най-важно, докато „покритието на кода“ може да бъде важен показател, човек трябва да осъзнае, че просто може да не е възможно да има 100% „покритие на кода“. 100% покритие на кода е един от онези показатели, които трябва да се стремите да постигнете, но никога няма да го постигнете; т.е. приближете се колкото е възможно по-близо.

OTOH, не се побърквайте, опитвайки се да получите 100% покритие на кода. По-важното е, че вашият код е четим? Може ли да се тества (предполагам, че е така, тъй като гледате покритието на кода)? Поддържа ли се? ТВЪРД ли е? Имате ли успешни тестове за единица, интеграция и тестове от край до край? Тези неща са по-важни от постигането на 100% покритие на кода. Това, което покритието на кода ще ви каже, е колко обширно е вашето тестване (не съм сигурен дали вградената машина за анализ на покритието на кода включва само тестове за единици или включва всички видове тестове при изчисляване на своите статистики), което ви дава индикация за независимо дали имате достатъчно тестове. Освен това, въпреки че ще ви каже колко обширни са вашите тестове (т.е. колко реда код се изпълняват от вашите тестове), той няма да ви каже дали вашите тестове са добри (т.е. вашите тестове наистина ли тестват това, което трябва да се тества за да сте сигурни, че вашето приложение работи правилно).

Както и да е, това може да не е отговор, а храна за размисъл.

person fourpastmidnight    schedule 26.07.2014