Можно ли исключить часть метода из покрытия кода?

Подозреваю, что нет, но все же спрошу...

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
Конечно, я понимаю аргументы против чрезмерной инженерии. Тем не менее, внутреннее статическое свойство счетчика max со значением по умолчанию 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