Поделиться через


Основные сведения о модульных тестах

В этом разделе описываются основы создания и запуска модульных тестов в Обозревателе тестов в Visual Studio.Он содержит следующие подразделы:

Unit testing overview

  • Quick starts

The MyBank Solution example

Creating the unit test projects

Writing your tests

Running tests in Test Explorer

  • Running and viewing tests from the Test Explorer toolbar

  • Running tests after every build

  • Filtering and grouping the test list

Debugging unit tests

Additional tools for unit tests

  • Generating application code from tests

  • Generating multiple tests by using data driven test methods

  • Analyzing unit test code coverage

  • Isolating unit test methods with Microsoft Fakes

Общие сведения о модульном тестировании

Обозреватель тестов новой Visual Studio предназначен для поддержки разработчиков и коллективов, применяющих модульное тестирование на практике при разработке программного обеспечения.Модульное тестирование помогает обеспечить корректность программы, проверяя, что код приложения делает именно то, что вы от него ожидаете.В модульном тестировании, вы анализируете функциональность программы для обнаружения дискретных тестовых сценариев поведения, которые можно тестировать как отдельные единицы.Вы используете платформу модульного тестирования для создания тестов для этих сценариев поведения и отчета по результатам этих тестов.

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

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

Представления обозревателя тестов могут отображать все тесты или только тесты, которые прошли удачно, не удались, еще не были запущены, или были пропущены.Можно отфильтровать тесты в любом представлении, введя текст в поле поиска на глобальном уровне, либо выбрав один из предопределенных фильтров.Можно выполнить любую выборку тестов в любое время.При использовании Visual Studio Ultimate, тесты можно выполнять автоматически после каждого построения.Результаты тестового запуска немедленно отображаются на панели "пройден/неудача" в верхней части окна обозревателя.Подробные сведения о результатах выполнения метода тестирования отображаются при выборе теста.

Hh694602.collapse_all(ru-ru,VS.110).gifКраткое руководство

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

Пример решения MyBank

В этом разделе в качестве примера используется разработка выдуманного приложения под названием MyBank.Нет необходимости в фактическом коде, что бы следить за объяснениями в этом разделе.Методы тестов написаны на языке C# и представленны с помощью платформы модульных тестов Microsoft для управляемого кода, однако концепции легко переносятся на другие языки и платформы.

Решение MyBank

Наша первая попытка при создании приложения MyBank включает компонент учетных записей, представляющий отдельную учетную запись и ее транзакции с банком и компонент базы данных, представляющий функциональные возможности для статистической обработки и управления отдельными учетными записями.

Создайте решение MyBank, содержащее два проекта:

  • Accounts

  • BankDb

Наша первая попытка при создании проекта Accounts содержит класс для хранения основных сведений об учетной записи, интерфейс, который определяет общие функциональные возможности любого типа учетной записи, например внесение и снятие средств со счета, и класс, производный от интерфейса, представляющий текущий счет.Мы начнем проект Accounts с создания следующих исходных файлов:

  • AccountInfo.cs определяет основные сведения об учетной записи.

  • IAccount.cs задает стандартный интерфейс IAccount для учетной записи, в том числе методы для внесения и снятия средств со счета и извлечения баланса счета.

  • CheckingAccount.cs содержит класс CheckingAccount, реализующий интерфейс IAccounts для текущего счета.

По опыту мы знаем, что перед снятием средств с текущего счета необходимо убедиться, что снимаемая сумма меньше баланса счета.Таким образом мы переопределяем метод IAccount.Withdaw в CheckingAccount методом, который проверяет данное условие.Метод может выглядеть следующим образом:

public void Withdraw(double amount)
{
    if(m_balance >= amount)
    {
        m_balance -= amount;
    }
    else
    {
        throw new ArgumentException(amount, "Withdrawal exceeds balance!")
    }
}

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

Создание проекта модульного теста

Проект модульных тестов обычно отражает структуру отдельного проекта кода.В примере MyBank добавляется два проекта модульных тестов с именами AccountsTests и BankDbTests в решение MyBanks.Имя проекта тестов произвольно, но рекомендуется принять стандартное соглашение об именовании.

Добавление нового проекта модульных тестов в решение:

  1. В меню Файл выберите Создать а затем выберите Проект (клавиатура: Ctrl + Shift + N).

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

  3. Для использования одной из платформ модульного тестирования Microsoft выберите Проект модульного теста из списка шаблонов проектов.В противном случае выберите шаблон проекта платформы модульного тестирования, которую хотите использовать.Для тестирования проекта Accounts из нашего примера, назовите тестовый проект AccountsTests.

    Предупреждающее замечаниеВнимание

    Не все сторонние платформы модульного тестирования предоставляют шаблон проекта Visual Studio.Дополнительные сведения о создании проекта см. в документации платформы.

  4. В проекте модульного теста, добавьте ссылку на проект тестируемого кода, в данном примере на проект Accounts.

    Создание ссылки на проект кода:

    1. Выберите проект в обозревателе решений.

    2. В меню Проект выберите команду Добавить ссылку.

    3. В диалоговом окне диспетчера ссылок, откройте узел Решение и выберите Проекты.Выберите имя проекта и закройте диалоговое окно.

Каждый проект модульных тестов содержит классы, которые отражают имена классов в проекте кода.В данном примере, проект AccountsTests будет содержать следующие классы:

  • Класс AccountInfoTests содержит методы модульного теста для класса AccountInfo в проекте BankAccount

  • Класс CheckingAccountTests содержит методы модульного теста для класса CheckingAccount.

Написание тестов

Платформа модульного тестирования, которую вы используете, и Visual Studio IntelliSense помогут вам создать модульные тесты для проекта кода.Для запуска в Обозревателе тестов, большинство платформ требуют добавления определенных атрибутов, чтобы определить методы модульного теста.Платформы также предоставляют способ — обычно через заявления Assert или атрибуты метода — для определения того, прошел ли метод теста или нет.Другие атрибуты определяют необязательные методы настройки, которые выполняются при инициализации класса и перед каждым методом теста, а так же методы уничтожения, которые выполняются после каждого метода теста и перед уничтожением класса.

Шаблон AAA (Arrange, Act, Assert) является распространенным способом написания модульных тестов для тестируемого метода.

  • Раздел Arrange метода модульного теста инициализирует объекты и задает значение данных, которые передаются тестируемому методу.

  • Раздел Act вызывает тестируемый метод с подготовленными параметрами.

  • Раздел Assert проверяет, что действие тестируемого метода работает как ожидалось.

Чтобы проверить метод CheckingAccount.Withdraw нашего примера можно написать 2 теста: один, который проверяет стандартное поведение метода и один, который проверяет, что снятие суммы превышающей баланс завершается ошибкой.Добавьте следующие методы в класс CheckingAccountTests:

[TestMethod]
public void Withdraw_ValidAmount_ChangesBalance()
{
    // arrange
    double currentBalance = 10.0;
    double withdrawal = 1.0;
    double expected = 9.0;
    var account = new CheckingAccount("JohnDoe", currentBalance);
    // act
    account.Withdraw(withdrawal);
    double actual = account.Balance;
    // assert
    Assert.AreEqual(expected, actual);
}

[TestMethod]
[ExpectedException(typeof(ArgumentException))]
public void Withdraw_AmountMoreThanBalance_Throws()
{
    // arrange
    var account = new CheckingAccount("John Doe", 10.0);
    // act
    account.Withdraw(1.0);
    // assert is handled by the ExcpectedException
}

Обратите внимание, что Withdraw_ValidAmount_ChangesBalance использует явное заявление Assert, чтобы указать, прошел ли метод теста или нет, в то время как Withdraw_AmountMoreThanBalance_Throws использует атрибут ExpectedException, чтобы указать успешность метода теста.Платформа модульного тестирования оборачивает методы теста в блоки try/catch.В большинстве случаев, если исключения перехватываются, то тестовый метод считается проваленным и исключения игнорируются.Атрибут ExpectedException приводит к тому, что метод теста считается пройденным, если выбрасывается указанное исключение.

Дополнительные сведения о платформах модульного тестирования Microsoft см. в одном из следующих разделов:

Запуск тестов в Обозревателе тестов

При создании тестового проекта, тесты отображаются в Обозревателе тестов.Если Обозреватель тестов не отображается, выберите пункт Тест в меню Visual Studio, выберите Окна, а затем выберите Обозреватель тестов.

Обозреватель модульных тестов

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

Hh694602.collapse_all(ru-ru,VS.110).gifВыполнение и просмотр тестов из панели инструментов Обозревателя тестов

Панель инструментов Обозревателя тестов помогает обнаружить, организовать и выполнить тесты, которые вас интересуют.

Запуск тестов из панели инструментов обозревателя тестов

Можно нажать Выполнить все, чтобы выполнить все тесты или нажать Выполнить для выбора подмножества тестов для выполнения.После выполнения набора тестов, отчет о тестовом запуске отображается в нижней части окна Обозревателя тестов.Выберите тест, чтобы просмотреть подробные сведения по нему в нижней панели.Выберите в контекстном меню Открыть тест (клавиатура: F12) для отображения исходного кода для выбранного теста.

Hh694602.collapse_all(ru-ru,VS.110).gifЗапуск тестов после каждого построения

Предупреждающее замечаниеВнимание

Выполнение модульных тестов после каждого построения поддерживаются только в Visual Studio Ultimate.

Запуск после построения

Для выполнения модульных тестов после каждого локального построения в стандартном меню выберите Тест, на панели инструментов Обозревателя тестов выберите команду Выполнить тесты после построения .

Hh694602.collapse_all(ru-ru,VS.110).gifФильтрация и группирование списка тестов

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

Категории фильтров поиска

Кнопка группы обозревателя тестов

Для группирования тестов по категориям, нажмите кнопку Группировка.

Дополнительные сведения см. в разделе Выполнение модульных тестов с помощью обозревателя тестов.

Отладка модульных тестов

Для запуска сеанса отладки тестов можно использовать Обозреватель тестов.Пошаговое выполнение кода с отладчиком Visual Studio легко осуществляет переход между модульными тестами и тестируемым проектом.Начало отладки:

  1. В редакторе Visual Studio, установите точку останова в одном или нескольких методах теста, которые требуется отладить.

    ПримечаниеПримечание

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

  2. В Обозревателе тестов выберите методы теста, а затем выберите Отладка выбранных тестов в контекстном меню.

Дополнительные сведения об отладчике см. в разделе Отладка в Visual Studio.

Дополнительные инструменты для модульных тестов

Hh694602.collapse_all(ru-ru,VS.110).gifСоздание кода приложения из тестов

Если тесты написаны прежде чем написан код проекта, можно использовать IntelliSense для создания классов и методов в коде проекта.Напишите оператор в методе теста, который вызывает класс или метод, который требуется создать, а затем откройте меню IntelliSense под вызовом.Если вызывается конструктор нового класса, выберите из меню Сформировать новый тип и следуйте мастеру, чтобы добавить класс в проект кода.Если вызывается метод, выберите Создать новый метод из меню IntelliSense.

Меню Intellisense "Сформировать заглушку метода"

Hh694602.collapse_all(ru-ru,VS.110).gifСоздание нескольких тестов с помощью методов теста, управляемого данными

ПримечаниеПримечание

Эти процедуры применяются только к методам теста, созданным с помощью платформы модульного тестирования Microsoft для управляемого кода.Если вы используете другую платформу, обратитесь к документации платформы для соответствующей функциональности.

Методы теста, управляемого данными позволяют проверить диапазон значений в одном методе модульного теста.Для создания метода модульного теста, управляемого данными, снабдите метод атрибутом DataSource, определяющим источник данных и таблицу, содержащую переменные значения, которые требуется проверить.В теле метода, значения строки присваиваются переменным с помощью индексатора TestContext.DataRow[ColumnName].

Например, предположим, что мы добавили ненужный метод к классу CheckingAccount с именем AddIntegerHelper.AddIntegerHelper добавляет два целых числа.

Для создания теста управляемого данными, для метода AddIntegerHelper, мы сначала создадим базу данных Access с именем AccountsTest.accdb и таблицу с именем AddIntegerHelperData.Таблица AddIntegerHelperData определяет столбцы для указания первого и второго операнда для добавления и столбец, чтобы задать ожидаемый результат.Мы заполняем несколько строк соответствующими значениями.

    [DataSource(
        @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Projects\MyBank\TestData\AccountsTest.accdb", 
        "AddIntegerHelperData"
    )]
    [TestMethod()]
    public void AddIntegerHelper_DataDrivenValues_AllShouldPass()
    {
        var target = new CheckingAccount();
        int x = Convert.ToInt32(TestContext.DataRow["FirstNumber"]);
        int y = Convert.ToInt32(TestContext.DataRow["SecondNumber"]); 
        int expected = Convert.ToInt32(TestContext.DataRow["Sum"]);
        int actual = target.AddIntegerHelper(x, y);
        Assert.AreEqual(expected, actual);
    }

Метод с атрибутами выполняется один раз для каждой строки в таблице.Обозреватель тестов информирует о сбое теста для метода, если хотябы одна итерация завершается с ошибкой.Панель подробностей результатов теста для метода показывает успешность метода для каждой строки данных.

Дополнительные сведения см. в разделе Практическое руководство. Создание модульного теста, управляемого данными.

Hh694602.collapse_all(ru-ru,VS.110).gifАнализ покрытия кода модульными тестами

ПримечаниеПримечание

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

Объем кода продукта, который был фактически протестирован модульными тестами, можно определить с помощью средства покрытия кода Visual Studio.Определение покрытия кода можно выполнить на выбранных тестах или на всех тестах в решении.Окно "Результаты покрытия кода" отображает процент блоков рабочего кода продукта по строкам, функциям, классам, пространствам имен и модулям.

Для запуска определения покрытия кода для методов теста в решении,

  1. выберите Тесты в меню Visual Studio, а затем выберите Анализ покрытия кода.

  2. Выберите один из следующих параметров:

    1. Выбранные тесты запустит методы теста, выбранные в обозревателе тестов.

    2. Все тесты запустит все методы теста в решении.

Результаты покрытия отображаются в окне "Результаты покрытия кода".

Результаты покрытия кода

Дополнительные сведения см. в разделе Использование покрытия кода для определения объема протестированного кода.

Hh694602.collapse_all(ru-ru,VS.110).gifИзоляция методов модульных тестов с помощью Microsoft Fakes

ПримечаниеПримечание

Microsoft Fakes доступно только в Visual Studio Ultimate.Microsoft Fakes можно использовать только с помощью методов теста, написанных с помощью платформ модульного тестирования для управляемого кода.

Проблема

Методы модульных тестов, направленные на проверку внутреннего кода в функции может быть трудно писать, когда тестируемый метод вызывает функции, которые вводят внешние зависимости.Например, в данном примере методы класса CheckingAccount должны, скорее всего, вызывать методы компонента BankDb для обновления основной базы данных.Мы можем выполнить рефакторинг класса CheckingAccount что бы он выглядел следующим образом:

class CheckingAccount : IAccount
{
    public CheckingAccount(customerName, double startingBalance, IBankDb bankDb)
    {
        m_bankDb = bankDb;
        // set up account
    }

    public void Withdraw(double amount)
    {
        if(m_balance >= amount)
        {
            m_balance = m_MyBankDb.Withdraw(m_accountInfo.ID, amount);
        }
        else
        {
            throw new ArgumentException(amount, "Withdrawal exceeds balance!")
        }
    }

    private IBankDb m_bankDb = null;
    // ...

Модульные тесты этого метода CheckingAccount.Withdraw, теперь могут завершиться ошибкой из-за проблем, вызванных вызовом m_bankDb.Withdraw.База данных или сетевое подключение могут быть утеряны или разрешения на базу данных могут быть неверны.Сбой при вызове m_bankDB.Withdraw вызвал бы завершение теста с ошибкой по причинам, не относящимся к его внутреннему коду.

Решение Microsoft Fakes

Microsoft Fakes создает сборку, содержащую классы и методы, которыми можно заменить классы в методах модульных тестов, которые вызывают зависимости.Замещающий класс в сгенерированном Fakes модуле объявляет метод и делегат для каждого открытого метода в компоненте целевого объекта.В методе теста, вы реализуете делегат, чтобы создать точное поведение вызова зависимостей в методе, который требуется протестировать.

В нашем примере, можно создать сборку Fakes для проекта BankDb, а затем использовать класс StubIBankDb, который создан Fakes, и является производным от интерфейса IBankDb, чтобы удалить неопределенность, вызванную взаимодействиями с базой данных.Исправленная версия метода теста Withdraw_ValidAmount_ChangesBalance может выглядеть следующим образом:

[TestMethod]
public void Withdraw_ValidAmount_ChangesBalance()
{
    // arrange
    double currentBalance = 10.0;
    double withdrawal = 1.0;
    double expected = 9.0;

    // set up the Fakes object and delegate
    var stubBankDb = new MyBank.Stubs.StubIBankDb();
    stubBankDb.WithdrawDoubleDouble = (id, amount) => { return 9.0; }
    var account = new CheckingAccount("JohnDoe", currentBalance, stubBankDb);

    // act
    account.Withdraw(withdrawal);
    double actual = account.Balance;

    // assert
    Assert.AreEqual(expected, actual);
}

Эта линия в методе теста:

stubBankDb.WithdrawDoubleDouble = (id, amount) => { return 9.0; }

реализует делегат Fakes для метода Withdraw с помощью lamba-выражения.Метод stubBankDb.Withdraw вызовает делегат и поэтому всегда возвращает указанное число, которое позволяет методу теста надежно проверить поведение методов Accounts.

Дополнительные сведения о Microsoft Fakes

Microsoft Fakes использует два подхода к созданию подстановочных классов:

  1. Заглушки создают подстановочные классы, производные от родительского интерфейса целевого класса зависимости.Методы заглушки могут быть заменены на открытые виртуальные методы целевого класса.

  2. Прокладки используют инструменты времени выполнения для перенаправления вызовов целевого метода к заменяющему методу-прокладке для не-виртуальных методов.

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

Дополнительные сведения см. в разделе Изоляция тестируемого кода с помощью Microsoft Fakes.