IlanGreen Ответов: 4

Как я могу покрыть 100% своего проекта в тестах?


Я только что начал новую работу в качестве младшего разработчика .Net, и моя первая задача-охватить решение, которое имеет 80% успеха с помощью модульных тестов, чтобы убедиться, что каждый фрагмент кода работает правильно.
Я смог сделать это до 37% после покрытия всех публичных методов, просто вызвав их из своих тестов, но я понятия не имею, как получить доступ к частным/защищенным методам извне их классов.
Загвоздка в том, что мне не разрешается изменять ни один фрагмент существующего кода.

Проект написан на C# .net framework 4.7.2
Для анализа покрытия кода я использую OpenCover
Фреймворк тестирования: Nunit 3.11.0

Любой совет приветствуется!

Что я уже пробовал:

Я пытался найти решение этой проблемы, но, к сожалению, самый распространенный совет-просто не тестировать частные методы.
Другой альтернативой было изменение методов на общедоступные, но это не вариант, так как мне не разрешено изменять какой-либо фрагмент существующего кода.

CPallini

"До определенного момента лучше просто позволить корягам [ошибкам] быть там, чем тратить такое время на дизайн, что их нет."
--Алан М. Тьюринг

-Отладка? Клингоны не отлаживают. Ошибки хороши для формирования характера у пользователя."
-- Клингонские разработчики

IlanGreen

Я не согласен с вами @CPallini. Каждая ошибка, которую вы устраняете или ловите в производстве, экономит вам массу времени после этого

4 Ответов

Рейтинг:
2

GregoryPres

Наша команда использует изолятор Typemock в качестве насмешливого фреймворка и имеет возможность тестировать частные методы.

Простой Api для проверки вызовов частных методов:
Изолировать.Проверить.NonPublic.WasCalled(<instance>, "PrivateMethodname");
Кроме того, вы можете подделать частные экземпляры и изменить их поведение, что поможет вам противостоять вызовам БД и всем этим жестким зависимостям

У него есть недостаток, совсем не дешевый, но если я не ошибаюсь, у него есть 7 дней бесплатной пробной версии.
Скачать Изолятор - Typemock[^]

надеюсь, это поможет


IlanGreen

Приятно! такой дружественный Api, более простой в использовании, чем отражение с этим огромным количеством опций.

Рейтинг:
2

F-ES Sitecore

Плохая новость заключается в том, что ваша задача, вероятно, невыполнима. Модульное тестирование-это не то, что вы можете приспособить к приложению, оно должно быть написано с учетом модульного тестирования. Попытка переоборудовать модульное тестирование в приложение, не предназначенное для него, часто приводит к серьезному рефакторингу кода.

Однако, чтобы охватить ваш конкретный вопрос, вы, как правило, обеспечиваете охват в частных методах, манипулируя публичными методами, которые вызывают эти методы. Так что если у меня есть код, как показано ниже;

public class TestClass
{
    public int Add(int x, int y)
    {
        if (!IsValid(x) || !IsValid(y))
        {
            throw new ArgumentException();
        }

        return x + y;
    }

    private bool IsValid(int number)
    {
        if (number >= 0)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
}


Я не могу вызвать IsValid непосредственно из моих модульных тестов, но я могу убедиться, что все пути в функции покрыты вызовом Add как с допустимыми, так и с недопустимыми параметрами;

[TestMethod]
public void WhenParamsValidAddReturnsSum()
{
    // Arrange
    TestClass testClass = new TestClass();

    // Act
    int result = testClass.Add(1, 2);

    // Assert
    Assert.AreEqual(3, result);
}

[TestMethod]
[ExpectedException(typeof(ArgumentException))]
public void WhenParamsInvalidAddReturnsException()
{
    // Arrange
    TestClass testClass = new TestClass();

    // Act
    int result = testClass.Add(-1, 2);
}


Прочтите это вслух

Модульное Тестирование - Visual Studio | Microsoft Docs[^]


IlanGreen

Спасибо за совет @F-ES Sitecore, я попробовал этот сценарий, и охват private bool IsValid(int number) действительно составляет 100%, так как его существа полностью выполнены.
Моя проблема начинается, когда этот частный метод обращается к другим местам, например к БД, которая не может быть достигнута, и я не могу проверить этот сценарий

F-ES Sitecore

Это проблема с попыткой переосмыслить модульное тестирование. Ваши модульные тесты не должны требовать никаких внешних ресурсов, поэтому нет доступа к БД, нет доступа к сети и т. д. Если вы тестируете код, требующий доступа к БД, вам необходимо абстрагировать этот доступ к классу, который разрешен с помощью dependency injection\IoC. Таким образом, ваш фактический производственный код получит класс, который читает БД, но ваш модульный тест может ввести фиктивный\издевательский класс, который возвращает жестко закодированные результаты, а не нуждается в доступе к БД. Если ваше решение не закодировано таким образом, то вам либо нужно изменить решение, либо принять код, который не может быть протестирован модульно.

IlanGreen

Большое вам спасибо за Ваш вклад. под этим вы подразумеваете, что я должен издеваться над всеми зависимостями этих методов, чтобы проверить их эффективным способом?

F-ES Sitecore

Да, однако это означает, что код должен получить конкретный класс для использования из преобразователя зависимостей, чего он, вероятно, в настоящее время не делает, поэтому добавление модульных тестов обычно включает в себя много изменений в коде.

Рейтинг:
1

jerry.nothstine

Вы можете получить доступ к частным методам с помощью рефлексии:

MethodInfo myPrivateMethod = typeof(MyClassBeingTested).GetMethod(
"PrivateMethodName",
"Флаг bindingflags.Непубличные | BindingFlags.Пример);

myPrivateMethod.Взывать(
instanceOfMyClassBeingTested,
новый объект[] {
параметр1,
параметр2});


Когда я сталкиваюсь с такого рода проблемой, я пишу метод, который реализует приведенный выше код, а затем отправляю ему все необходимые параметры. Таким образом, я могу использовать его несколько раз.


Рейтинг:
0

BillWoodruff

1. пожалуйста, объясните, что это значит: "решение, которое имеет 80% успеха"

2. В общем случае вы не тестируете частные методы юнит-тестирования; в конце концов, по определению они используются только из публичного API

3. конечно, архитектура приложения может быть настолько испорчена, что вы не можете изолировать определенные классы; как вы описываете, вам может быть запрещено изменять код и т. д. Модульное тестирование не может касаться структурных проблем, которые.

4. Если вам действительно нужно возиться с частными методами, вы можете использовать рефлексию: [^]

5. Вы можете использовать инструменты AOP, такие как PostSharp (коммерческий) [^], и Fody (open source) [^] чтобы ввести/сплести код ведения журнала в приложение времени выполнения

Я предлагаю вам поговорить с членами вашей команды и/или менеджером и получить некоторые разъяснения о том, что от вас ожидается. Никто не будет думать о тебе хуже из-за этого !

имхо, модульное тестирование-это ключевая часть более широкого процесса контроля качества программного обеспечения, который включает в себя протоколирование, выявление узких мест, а также ошибок, настройку производительности и наличие реальных людей (предпочтительно "наивных" конечных пользователей), которые пытаются сломать ваше все, что угодно.


IlanGreen

1.80% покрытия последовательности, извините меня за опечатку
2.Ну, мне было поручено это сделать, а также как вы вообще достигаете более чем 50% покрытия кода? Я имею в виду, очевидно, что весь ваш проект не может быть публичным
4.я попробую это сейчас, спасибо за статью
5.Плохо проверьте те toold прямо сейчас

В общем, спасибо Вам большое, вы меня успокоили, я был уверен, что у меня нет больших неприятностей
быть в состоянии сделать такую легкую задачу