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


Руководство. Тестирование библиотеки классов .NET

В этом руководстве показано, как автоматизировать модульное тестирование путем добавления тестового проекта в решение.

Предпосылки

В этом руководстве описано решение, которое вы создаете в Создание библиотеки классов .NET.

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

Модульные тесты обеспечивают автоматическое тестирование программного обеспечения во время разработки и публикации. MSTest является одной из трех платформ тестирования, которые можно выбрать. Другие — xUnit и nUnit.

  1. Запустите Visual Studio.

  2. Откройте решение ClassLibraryProjects, созданное в разделе "Create a .NET class library".

  3. Добавьте в решение новый проект модульного теста с именем StringLibraryTest.

    1. Щелкните правой кнопкой мыши решение в Обозреватель решений и выберите Add>New project.

    2. На странице Добавление нового проекта введите mstest в поле поиска. Выберите C# или Visual Basic в списке языков и выберите платформы All из списка платформ.

    3. Выберите шаблон проекта тестирования MSTest , а затем выберите Далее.

    4. На странице Настройка нового проекта введите StringLibraryTest в поле имени проекта . Затем нажмите кнопку "Далее".

    5. На странице Additional information выберите .NET 10 в поле Framework> выберите Microsoft.Testing.Platform для Test runner и выберите Create.

    Введите дополнительные сведения для тестового проекта MSTest

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

    namespace StringLibraryTest
    {
    
        [TestClass]
        public sealed class Test1
        {
            [TestMethod]
            public void TestMethod1()
            {
            }
        }
    }
    
    Imports Microsoft.VisualStudio.TestTools.UnitTesting
    
    Namespace StringLibraryTest
        <TestClass>
        Public Class Test1
            <TestMethod>
            Sub TestSub()
    
            End Sub
        End Class
    End Namespace
    

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

    Каждый метод, помеченный [TestMethod] в классе тестирования, помеченном [TestClass] , выполняется автоматически при выполнении модульного теста.

  1. Запустите Visual Studio Code.

  2. Откройте решение ClassLibraryProjects, созданное в Создайте библиотеку классов .NET.

  3. В Обозреватель решений выберите New Project или в палитре команд выберите .NET: Новый проект.

  4. Выберите проект тестирования MSTest, присвойте ему имя StringLibraryTest, выберите каталог по умолчанию и нажмите кнопку "Создать проект".

    Шаблон проекта создает StringLibraryTest/Test1.cs со следующим кодом:

    namespace StringLibraryTest;
    
    [TestClass]
    public class Test1
    {
        [TestMethod]
        public void TestMethod1()
        {
        }
    }
    

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

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

    Каждый метод, помеченный [TestMethod] в классе тестирования, помеченном [TestClass] , выполняется автоматически при вызове модульного теста.

  1. Откройте терминал и перейдите в папку учебников, содержащую проекты StringLibrary и ShowCase.

  2. Создайте тестовый проект MSTest:

    dotnet new mstest -n StringLibraryTest
    

    Шаблон проекта создает StringLibraryTest/Test1.cs со следующим кодом:

    namespace StringLibraryTest;
    
    [TestClass]
    public class Test1
    {
        [TestMethod]
        public void TestMethod1()
        {
        }
    }
    

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

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

    Каждый метод, помеченный [TestMethod] в классе тестирования, помеченном [TestClass] , выполняется автоматически при вызове модульного теста.

Добавление ссылки на проект

Чтобы тестовый проект работал с классом, добавьте ссылку на проект в ваш проект.

  1. В Обозреватель решений щелкните правой кнопкой мыши на узле Dependencies проекта StringLibraryTest и выберите Добавить ссылку на проект в контекстном меню.

  2. В диалоговом окне диспетчера ссылок выберите поле рядом с StringLibrary.

    Добавьте StringLibrary в качестве ссылки на проект для StringLibraryTest.

  3. Нажмите ОК.

  1. В Обозреватель решений щелкните правой кнопкой мыши проект StringLibraryTest и выберите Add Project Reference.

  2. Выберите StringLibrary.

  1. Перейдите в папку StringLibraryTest и добавьте ссылку на проект:

    cd StringLibraryTest
    dotnet add reference ../StringLibrary/StringLibrary.csproj
    

Добавление и запуск методов модульного теста

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

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

Методы Assert Функция
Assert.AreEqual Проверяет, равны ли два значения или объекты. Утверждение завершается ошибкой, если значения или объекты не равны.
Assert.AreSame Проверяет, что две переменные объекта ссылаются на один и тот же объект. Утверждение завершается ошибкой, если переменные ссылаются на разные объекты.
Assert.IsFalse Проверяет, что условие соответствует . Утверждение завершается ошибкой, если условие .
Assert.IsNotNull Проверяет, что объект не является . Утверждение завершается ошибкой, если объект .

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

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

Так как метод библиотеки обрабатывает строки, вы также хотите убедиться, что он успешно обрабатывает пустую строку () и строку. Пустая строка — это строка, которая не имеет символов и имеет значение 0. Строка — это строка, которая не была инициализирована. Можно вызывать непосредственно как статический метод и передавать один аргумент. Или вы можете вызвать это как метод расширения на переменной, назначенной для .

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

Чтобы создать методы тестирования, выполните следующие действия.

  1. В окне кода Test1.cs или Test1.vb замените код следующим кодом:

    using UtilityLibraries;
    
    namespace StringLibraryTest
    {
        [TestClass]
        public sealed class Test1
        {
            [TestMethod]
            public void TestStartsWithUpper()
            {
                // Tests that we expect to return true.
                string[] words = ["Alphabet", "Zebra", "ABC", "Αθήνα", "Москва"];
                foreach (var word in words)
                {
                    bool result = word.StartsWithUpper();
                    Assert.IsTrue(result, $"Expected for '{word}': true; Actual: {result}");
                }
            }
    
            [TestMethod]
            public void TestDoesNotStartWithUpper()
            {
                // Tests that we expect to return false.
                string[] words = ["alphabet", "zebra", "abc", "αυτοκινητοβιομηχανία", "государство",
                              "1234", ".", ";", " "];
                foreach (var word in words)
                {
                    bool result = word.StartsWithUpper();
                    Assert.IsFalse(result, $"Expected for '{word}': false; Actual: {result}");
                }
            }
    
            [TestMethod]
            public void DirectCallWithNullOrEmpty()
            {
                // Tests that we expect to return false.
                string?[] words = [string.Empty, null];
                foreach (var word in words)
                {
                    bool result = StringLibrary.StartsWithUpper(word);
                    Assert.IsFalse(result, $"Expected for '{word ?? "<null>"}': false; Actual: {result}");
                }
            }
        }
    }
    
    Imports Microsoft.VisualStudio.TestTools.UnitTesting
    Imports UtilityLibraries
    
    Namespace StringLibraryTest
        <TestClass>
        Public Class UnitTest1
            <TestMethod>
            Public Sub TestStartsWithUpper()
                ' Tests that we expect to return true.
                Dim words() As String = {"Alphabet", "Zebra", "ABC", "Αθήνα", "Москва"}
                For Each word In words
                    Dim result As Boolean = word.StartsWithUpper()
                    Assert.IsTrue(result,
                           $"Expected for '{word}': true; Actual: {result}")
                Next
            End Sub
    
            <TestMethod>
            Public Sub TestDoesNotStartWithUpper()
                ' Tests that we expect to return false.
                Dim words() As String = {"alphabet", "zebra", "abc", "αυτοκινητοβιομηχανία", "государство",
                                   "1234", ".", ";", " "}
                For Each word In words
                    Dim result As Boolean = word.StartsWithUpper()
                    Assert.IsFalse(result,
                           $"Expected for '{word}': false; Actual: {result}")
                Next
            End Sub
    
            <TestMethod>
            Public Sub DirectCallWithNullOrEmpty()
                ' Tests that we expect to return false.
                Dim words() As String = {String.Empty, Nothing}
                For Each word In words
                    Dim result As Boolean = StringLibrary.StartsWithUpper(word)
                    Assert.IsFalse(result,
                           $"Expected for '{If(word Is Nothing, "<null>", word)}': false; Actual: {result}")
                Next
            End Sub
        End Class
    End Namespace
    

    Тест прописных символов в методе включает греческую заглавную букву альфа (U+0391) и кириллическую заглавную букву ЭМ (U+041C). Тест маленьких символов в методе включает в себя греческую маленькую букву альфа (U+03B1) и маленькую кириллическую букву г (U+0433).

  2. На строке меню выберите FileSave Test1.cs As или FileSave Test1.vb As. В диалоговом окне Сохранить файл как щелкните стрелку рядом с кнопкой Сохранить и нажмите кнопку Сохранить с помощью кодировки.

  3. В диалоговом окне Подтвердить сохранение как выберите кнопку Да для сохранения файла.

  4. В диалоговом окне "Дополнительные параметры сохранения" выберите Юникод (UTF-8 с подписью) — Codepage 65001 в раскрывающемся списке кодировки и нажмите кнопку ОК.

    Если не удается сохранить исходный код в виде файла в кодировке UTF8, Visual Studio может сохранить его в виде ФАЙЛА ASCII. В этом случае среда выполнения не декодирует символы UTF8 за пределами диапазона ASCII, а результаты теста неверны.

  5. В строке меню выберите ТестВыполнить все тесты. Если окно Обозреватель тестов не открыто, откройте его, выбрав ТестОбозреватель тестов. Три теста перечислены в разделе Пройденные тесты, а раздел Сводка сообщает результат выполнения тестов.

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

  1. Откройте StringLibraryTest/Test1.cs и замените весь код следующим кодом.

    using UtilityLibraries;
    
    namespace StringLibraryTest
    {
        [TestClass]
        public sealed class Test1
        {
            [TestMethod]
            public void TestStartsWithUpper()
            {
                // Tests that we expect to return true.
                string[] words = ["Alphabet", "Zebra", "ABC", "Αθήνα", "Москва"];
                foreach (var word in words)
                {
                    bool result = word.StartsWithUpper();
                    Assert.IsTrue(result, $"Expected for '{word}': true; Actual: {result}");
                }
            }
    
            [TestMethod]
            public void TestDoesNotStartWithUpper()
            {
                // Tests that we expect to return false.
                string[] words = ["alphabet", "zebra", "abc", "αυτοκινητοβιομηχανία", "государство",
                              "1234", ".", ";", " "];
                foreach (var word in words)
                {
                    bool result = word.StartsWithUpper();
                    Assert.IsFalse(result, $"Expected for '{word}': false; Actual: {result}");
                }
            }
    
            [TestMethod]
            public void DirectCallWithNullOrEmpty()
            {
                // Tests that we expect to return false.
                string?[] words = [string.Empty, null];
                foreach (var word in words)
                {
                    bool result = StringLibrary.StartsWithUpper(word);
                    Assert.IsFalse(result, $"Expected for '{word ?? "<null>"}': false; Actual: {result}");
                }
            }
        }
    }
    

    Тест прописных символов в методе включает греческую заглавную букву альфа (U+0391) и кириллическую заглавную букву ЭМ (U+041C). Тест маленьких символов в методе включает в себя греческую маленькую букву альфа (U+03B1) и маленькую кириллическую букву г (U+0433).

  2. Сохраните свои изменения.

Создание и запуск тестов

  1. В Обозреватель решений щелкните решение правой кнопкой мыши и выберите Build или в палитре команд выберите .NET: Build.

  2. Выберите окно тестирования , выберите "Выполнить тесты " или в палитре команд, выберите "Тест: выполнить все тесты".

    Visual Studio Code Проводник тестов

  1. Откройте StringLibraryTest/Test1.cs и замените весь код следующим кодом:

    using UtilityLibraries;
    
    namespace StringLibraryTest
    {
        [TestClass]
        public sealed class Test1
        {
            [TestMethod]
            public void TestStartsWithUpper()
            {
                // Tests that we expect to return true.
                string[] words = ["Alphabet", "Zebra", "ABC", "Αθήνα", "Москва"];
                foreach (var word in words)
                {
                    bool result = word.StartsWithUpper();
                    Assert.IsTrue(result, $"Expected for '{word}': true; Actual: {result}");
                }
            }
    
            [TestMethod]
            public void TestDoesNotStartWithUpper()
            {
                // Tests that we expect to return false.
                string[] words = ["alphabet", "zebra", "abc", "αυτοκινητοβιομηχανία", "государство",
                              "1234", ".", ";", " "];
                foreach (var word in words)
                {
                    bool result = word.StartsWithUpper();
                    Assert.IsFalse(result, $"Expected for '{word}': false; Actual: {result}");
                }
            }
    
            [TestMethod]
            public void DirectCallWithNullOrEmpty()
            {
                // Tests that we expect to return false.
                string?[] words = [string.Empty, null];
                foreach (var word in words)
                {
                    bool result = StringLibrary.StartsWithUpper(word);
                    Assert.IsFalse(result, $"Expected for '{word ?? "<null>"}': false; Actual: {result}");
                }
            }
        }
    }
    

    Тест прописных символов в методе включает греческую заглавную букву альфа (U+0391) и кириллическую заглавную букву ЭМ (U+041C). Тест маленьких символов в методе включает в себя греческую маленькую букву альфа (U+03B1) и маленькую кириллическую букву г (U+0433).

  2. Сохраните изменения и запустите тесты:

    dotnet test
    

    Тесты должны успешно завершиться.

Управление сбоями тестов

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

  1. Измените массив в методе , чтобы включить строку "Error".

    string[] words = { "alphabet", "Error", "zebra", "abc", "αυτοκινητοβιομηχανία", "государство",
                       "1234", ".", ";", " " };
    
    Dim words() As String = { "alphabet", "Error", "zebra", "abc", "αυτοκινητοβιομηχανία", "государство",
                       "1234", ".", ";", " " }
    
    
  1. Запустите тест, выбрав тестзапустить все тесты в строке меню. В окне обозревателя тестов указано, что два теста успешно выполнены, а один завершился сбоем.

    окно обозревателя тестов с неудачными тестами

  2. Выберите проваленный тест, .

    В окне обозревателя тестов отображается сообщение, созданное выражением assert: "Assert.IsFalse завершилось сбоем. Ожидается значение "Error": false; фактическое: истина. Из-за ошибки строки в массиве после "Error" не были проверены.

    окно обозревателя тестов , показывающее ошибку утверждения IsFalse

  1. Запустите тесты, щелкнув зеленую ошибку рядом с тестом в редакторе.

    Выходные данные показывают, что тест завершается ошибкой, и он предоставляет сообщение об ошибке для неудачного теста: "Assert.IsFalse не удалось. Ожидалось для 'Error': false; фактически: true. Из-за сбоя строки массива после "Ошибка" не были проверены.

    Неудача теста в Visual Studio Code

  1. Выполните тесты:

    dotnet test
    

    Выходные данные показывают, что тест не прошёл, и предоставляется сообщение об ошибке для теста, завершившегося неудачей: "Assert.IsFalse завершился неудачей. Ожидается для 'Error': false; фактически: true. Из-за сбоя строки массива после "Ошибка" не были проверены.

  1. Удалите строку "Ошибка", которую вы добавили.

  2. Повторно запустите тест, и тесты проходят.

Тестирование релизной версии библиотеки

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

Чтобы протестировать релизную сборку, выполните следующие действия.

  1. На панели инструментов Visual Studio измените конфигурацию сборки с Debug на Release.

  2. В Обозреватель решений щелкните правой кнопкой мыши проект StringLibrary и выберите Build в контекстном меню для повторной компиляции библиотеки.

  3. Запустите модульные тесты, выбрав из строки меню ТестВыполнить все тесты. Тесты успешно пройдены.

Запустите тесты с конфигурацией сборки Release.

dotnet test StringLibraryTest/StringLibraryTest.csproj --configuration Release

Тесты успешно пройдены.

Запустите тесты с конфигурацией сборки релиза.

dotnet test --configuration Release

Тесты успешно пройдены.

Отладка тестов

Если вы используете Visual Studio в качестве интегрированной среды разработки, можно использовать тот же процесс, что и в Tutorial: отладка консольного приложения .NET для отладки кода с помощью проекта модульного теста. Вместо запуска приложения ShowCase, щелкните правой кнопкой мыши проект StringLibraryTests и выберите пункт Отладка тестов в контекстном меню.

Visual Studio запускает тестовый проект с присоединенным отладчиком. Выполнение останавливается в любой точке останова, которую вы добавили в тестовый проект или базовый код библиотеки.

Если вы используете Visual Studio Code в качестве интегрированной среды разработки, можно использовать тот же процесс, который показан в Debug консольного приложения .NET для отладки кода с помощью проекта модульного тестирования. Вместо запуска проекта приложения ShowCase откройте StringLibraryTest/Test1.cs и выберите "Тесты отладки" в текущем файле между строками 7 и 8. Если ее найти не удается, нажмите клавиши CTRLSHIFTP , чтобы открыть палитру команд и ввести окно перезагрузки.

Visual Studio Code запускает тестовый проект с присоединенным отладчиком. Выполнение остановится в любой точке останова, которую вы добавили в тестовый проект или код базовой библиотеки.

Дополнительные ресурсы

  • модульное тестирование .NET

Очистка ресурсов

#REF! автоматически удаляет пространство кода через 30 дней бездействия. Если вы планируете ознакомиться с дополнительными руководствами в этой серии, вы можете оставить ваш Codespace активным. Если вы готовы посетить сайт .NET, чтобы скачать пакет SDK .NET, можно удалить пространство codespace. Чтобы удалить ваш Codespace, откройте окно браузера и перейдите к вашим Codespace. В окне вы видите список ваших codespaces. Выберите три точки () в записи пространства кода учебного руководства. Затем нажмите кнопку "Удалить".

Дальнейшие шаги

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

Создание и публикация пакета с помощью dotnet CLI

Если вы публикуете библиотеку в виде пакета NuGet, другие пользователи могут установить и использовать ее. Чтобы узнать, как это сделать, следуйте инструкциям по NuGet.

Установка и использование пакета с помощью dotnet CLI

Библиотеку не нужно распространять как пакет. Его можно объединить с консольным приложением, использующим его. Чтобы узнать, как опубликовать консольное приложение, ознакомьтесь с предыдущим руководством в этой серии: