Эта статья переведена вручную. Наведите указатель мыши на предложения статьи, чтобы просмотреть исходный текст. Дополнительные сведения.
|
Перевод
Текст оригинала
|
Пошаговое руководство. Создание и запуск модульных тестов для управляемого кода
Подготовка к выполнению пошагового руководства
Создание проекта модульного теста
Создание первого тестового метода
Исправление кода и повторный запуск тестов
Использование модульных тестов для улучшения кода
![]() |
---|
|
![]() |
---|
|
-
Проект "Банк". См. раздел Пример проекта для создания модульных тестов.
Подготовка к выполнению пошагового руководства
-
Запустите Visual Studio. -
В меню Файл выберите пункт Создать, а затем команду Проект. Откроется диалоговое окно Создание проекта. -
В области Установленные шаблоны выберите шаблон Visual C#. -
В списке типов приложения выберите пункт Библиотека классов. -
В поле Имя введите Bank и нажмите кнопку ОК. Примечание
Если имя "Bank" уже существует, выберите другое имя для проекта. Будет создан новый проект Bank. Этот проект отобразится в обозревателе решений, а его файл Class1.cs откроется в редакторе кода. Примечание
Если файл Class1.cs не откроется в редакторе кода, дважды щелкните Class1.cs в обозревателе решений, чтобы открыть этот файл. -
Скопируйте исходный код из раздела Пример проекта для создания модульных тестов. -
Замените исходное содержимое файла Class1.cs кодом из примера Пример проекта для создания модульных тестов. -
Сохранение файла как BankAccount.cs -
В меню Построение выберите Построить решение.
// method under test public void Debit(double amount) { if(amount > m_balance) { throw new ArgumentOutOfRangeException("amount"); } if (amount < 0) { throw new ArgumentOutOfRangeException("amount"); } m_balance += amount; }
Создание проекта модульного теста
-
В меню Файл последовательно щелкните Добавить и Новый проект.... -
В диалоговом окне "Новый проект" разверните узлы Установленные и Visual C# и выберите Тест. -
В списке шаблонов выберите Проект модульного теста. -
В поле Имя введите BankTest и нажмите кнопку ОК. Проект BankTests добавляется в решение Банк. -
В проекте BankTests добавьте ссылку на решение Банк. В области "Обозреватель решений" выберите Ссылки в проекте BankTests, а затем выберите Добавить ссылку... из контекстного меню. -
В диалоговом окне "Диспетчер ссылок" разверните Решение и выбирите элемент Bank.
Переименование файла класса
// unit test code using System; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace BankTests { [TestClass] public class BankAccountTests { [TestMethod] public void TestMethod1() { } } }
Добавление оператора using в тестируемый проект
using BankAccountNS
Требования к тестовому классу
Атрибут [TestClass] является обязательным для платформы модульных тестов Microsoft для управляемого кода в любом классе, содержащем методы модульных тестов, которые необходимо выполнить в обозревателе тестов. Каждый метод теста, который требуется выполнять с помощью обозревателя тестов, должен иметь атрибут [TestMethod].
-
Метод создает исключение [ArgumentOutOfRangeException], если сумма кредита превышает баланс. -
Он также создает ArgumentOutOfRangeException, если размер кредита меньше нуля. -
Если проверка пунктов 1.) и 2.) проходит успешно, то метод вычитает сумму из баланса счета.
Создание метода теста
-
Добавьте инструкцию using BankAccountNS; в файл BankAccountTests.cs. -
Добавьте следующий метод в этот класс BankAccountTests: // unit test code [TestMethod] public void Debit_WithValidAmount_UpdatesBalance() { // arrange double beginningBalance = 11.99; double debitAmount = 4.55; double expected = 7.44; BankAccount account = new BankAccount("Mr. Bryan Walton", beginningBalance); // act account.Debit(debitAmount); // assert double actual = account.Balance; Assert.AreEqual(expected, actual, 0.001, "Account not debited correctly"); }
Требования к методу теста
-
Метод должен быть отмечен атрибутом [TestMethod]. -
Метод должен вернуть void. -
Метод не должен иметь параметров.
Сборка и запуск теста
-
В меню Построение выберите Построить решение. При отсутствии ошибок появляется окно UnitTestExplorer с указанием Debit_WithValidAmount_UpdatesBalance в списке Незапущенные тесты. Если после успешной сборки обозреватель тестов не появляется, выберите в меню Тестирование, затем Окна, а затем Обозреватель тестов. -
Выберите Запустить все, чтобы выполнить тест. Во время выполнения теста в верхней части окна отображается анимированная строка состояния. По завершении тестового запуска строка состояния становится зеленой, если все методы теста успешно пройдены, или красной, если какие-либо из тестов не пройдены. -
В данном случае тест пройден не будет. Метод теста будет перемещен в группу Неудачные тесты. Выберите этот метод в обозревателе тестов для просмотра сведений в нижней части окна.
Анализ результатов теста
Исправление ошибки
m_balance += amount;
m_balance -= amount;
Повторный запуск теста
Анализ проблем
-
Метод создает исключение ArgumentOutOfRangeException, если сумма кредита превышает баланс. -
Он также создает ArgumentOutOfRangeException, если размер кредита меньше нуля.
Создание методов теста
//unit test method [TestMethod] [ExpectedException(typeof(ArgumentOutOfRangeException))] public void Debit_WhenAmountIsLessThanZero_ShouldThrowArgumentOutOfRange() { // arrange double beginningBalance = 11.99; double debitAmount = -100.00; BankAccount account = new BankAccount("Mr. Bryan Walton", beginningBalance); // act account.Debit(debitAmount); // assert is handled by ExpectedException }
Создать новый метод теста с именем Debit_WhenAmountIsMoreThanBalance_ShouldThrowArgumentOutOfRange. Скопировать тело метода из Debit_WhenAmountIsLessThanZero_ShouldThrowArgumentOutOfRange в новый метод. Присвоить debitAmount значение, превышающее баланс.
Запуск тестов
Продолжение анализа
throw new ArgumentOutOfRangeException("amount");
Рефакторинг тестируемого кода
// class under test public const string DebitAmountExceedsBalanceMessage = "Debit amount exceeds balance"; public const string DebitAmountLessThanZeroMessage = "Debit amount less than zero";
// method under test // ... if (amount > m_balance) { throw new ArgumentOutOfRangeException("amount", amount, DebitAmountExceedsBalanceMessage); } if (amount < 0) { throw new ArgumentOutOfRangeException("amount", amount, DebitAmountLessThanZeroMessage); } // ...
Рефакторинг тестовых методов
Проверить, что свойство ActualValue исключения (второй параметр конструктора ArgumentOutOfRangeException) больше начального баланса. В данном случае необходимо сравнить свойство ActualValue исключения со значением переменной beginningBalance метода теста, а также проверить, что значение ActualValue больше нуля. Проверить, что сообщение (третий параметр конструктора) включает DebitAmountExceedsBalanceMessage, определенное в классе BankAccount.
[TestMethod] public void Debit_WhenAmountIsGreaterThanBalance_ShouldThrowArgumentOutOfRange() { // arrange double beginningBalance = 11.99; double debitAmount = 20.0; BankAccount account = new BankAccount("Mr. Bryan Walton", beginningBalance);\ // act try { account.Debit(debitAmount); } catch (ArgumentOutOfRangeException e) { // assert StringAssert.Contains(e.Message, BankAccount. DebitAmountExceedsBalanceMessage); } }
Повторное тестирование, переписывание и анализ
При верном обнаружении ошибки в случае, если debitAmount больше баланса, проверка утверждения Contains проходит успешно, исключение игнорируется и метод теста завершается успешно. Это соответствует ожидаемому поведению. Если используется debitAmount, то проверка утверждения завершается неудачей, так как возвращается неверное сообщение об ошибке. Проверка утверждения также завершается неудачей, если ввести временное исключение ArgumentOutOfRange на другом шаге в коде тестируемого метода. Это также хорошо. Если значение debitAmount допустимо (т.е. меньше баланса, но больше нуля), то исключение перехватывается, а утверждение никогда не сработает. Метод теста проходит успешно. Это не хорошо, поскольку метод теста должен был завершиться ошибкой в том случае, если исключение не создается.
[TestMethod] public void Debit_WhenAmountIsGreaterThanBalance_ShouldThrowArgumentOutOfRange() { // arrange double beginningBalance = 11.99; double debitAmount = 20.0; BankAccount account = new BankAccount("Mr. Bryan Walton", beginningBalance);\ // act try { account.Debit(debitAmount); } catch (ArgumentOutOfRangeException e) { // assert StringAssert.Contains(e.Message, BankAccount. DebitAmountExceedsBalanceMessage); return; } Assert.Fail("No exception was thrown.") }