Как я (или я) модульное тестирование конкретной зависимости - PullRequest
7 голосов
/ 24 июля 2011

У меня есть класс бизнес-уровня, который использует System.IO.File для чтения информации из различных файлов. Чтобы выполнить модульное тестирование этого класса, я решил заменить зависимость от класса File на введенную зависимость следующим образом:

using System.IO;

public interface IFileWrapper
{
    bool FileExists( string pathToFile );
    Stream Open( string pathToFile );
}

Теперь я могу проверить свой класс, используя макет, и с миром все в порядке. Отдельно мне нужна конкретная реализация. У меня есть следующее:

using System;
using System.IO;

public class FileWrapper : IFileWrapper
{
    public bool FileExists( string pathToFile )
    {
        return File.Exists( pathToFile );
    }

    public Stream Open( string pathToFile )
    {
        return File.Open( pathToFile, FileMode.Open, FileAccess.Read, FileShare.Read );
    }
}

Теперь мой бизнес-класс больше не зависит от класса System.IO.File и может быть протестирован с использованием Mock of IFileWrapper. Я не вижу необходимости тестировать класс System.IO.File, так как полагаю, что он был тщательно протестирован Microsoft и проверен в бесчисленных случаях.

Как проверить конкретный класс FileWrapper? Хотя это простой класс (низкий риск), у меня есть примеры большего размера, которые следуют тому же подходу. Я не могу приблизиться к 100% охвату кода (если это важно), не завершив этого.

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

Ответы [ 3 ]

7 голосов
/ 24 июля 2011

Как правило, вам следует тестировать весь производственный код, который вы пишете.Тем не менее, из-за особенностей того, как спроектирован .NET, всегда будут такие классы, как класс Adapter и выше, которые не могут быть должным образом проверены модулем.

Мое личное правило:что если вы можете уменьшить каждый элемент в адаптере до цикломатической сложности из 1, то можно объявить его смиренным объектом .

AFAIK. Нет способов исключитькод из отчетов о покрытии, но вы можете реализовать свои скромные объекты в отдельных сборках, которые исключены из отчетов о покрытии.

1 голос
/ 24 июля 2011

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

В других случаях вы можете иметь дополнительную логику в таких типах, как FileWrapper, и в этих случаях вам может помочь интеграционное тестирование.

Большой вопрос здесь, я полагаю, как преодолеть разрыв между модульное тестирование и интеграционное тестирование?

Как правило, вы должны использовать эти два вида тестирования отдельно. Интеграционное тестирование должно быть на более высоком уровне, тестируя интеграцию между двумя компонентами, поэтому, если вы чувствуете, что вам нужно проверить эту зависимость - продолжайте, в противном случае не пишите такие тесты. Интеграционные тесты всегда сложнее, намного дольше выполняются и более сложны в обслуживании, чем модульное тестирование, поэтому вам следует дважды подумать перед написанием каждого интеграционного теста. Поэтому я бы не сказал, что если вы напишете несколько тестов для FileWrapper, это будет Integration Test . Поэтому я хочу сказать, что между модульным и интеграционным тестированием нет разрыва, они решают разные проблемы.

0 голосов
/ 25 июля 2011

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

Ваш модульный тест должен быть очень простым, но должен использовать конкретную реализацию. Это означает, что он, вероятно, будет относительно медленным (> 5 мс) и несколько раздражающим при настройке / демонтаже. Мое определение модульного теста - это то, которое выполняется сравнительно быстро и тестирует небольшой объем кода, в данном случае один класс.

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

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

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