Пошаговое руководство. Создание и запуск модульных тестов для приложений UWP

В этой статье объясняется, как выполнять модульное тестирование приложений универсальной платформы Windows (UWP) в Visual Studio. Visual Studio предлагает шаблоны проектов модульных тестов UWP для C#, Visual Basic и C++. Дополнительные сведения см. в статье Начало работы с приложениями UWP.

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

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

Далее приведены процедуры создания и запуска проектов модульных тестов для приложений UWP.

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

  1. В начальном окне Visual Studio выберите команду Создать проект.

  2. На странице Создание проекта в поле поиска введите фразу модульный тест. В списке шаблонов выполняется фильтрация по проектам модульного тестирования.

  3. Выберите шаблон Приложение модульного тестирования (универсальное приложение Windows) для C# или Visual Basic, а затем выберите Далее.

    Screenshot that shows creating a new UWP unit test app in Visual Studio.

  4. При необходимости измените имя и расположение проекта или решения, а затем выберите Создать.

  5. При необходимости измените целевую и минимальную версии платформы, а затем нажмите кнопку OK.

Visual Studio создаст тестовый проект и откроет его в Обозревателе решений Visual Studio.

Screenshot that shows the UWP unit test project in Solution Explorer.

  1. В начальном окне Visual Studio выберите команду Создать проект.

  2. На странице Создание проекта в поле поиска введите фразу модульный тест. В списке шаблонов выполняется фильтрация по проектам модульного тестирования.

  3. Выберите шаблон Приложение модульного тестирования (универсальное приложение Windows) для C# или Visual Basic, а затем выберите Далее.

    Screenshot that shows creating a new UWP unit test app in Visual Studio.

  4. При необходимости измените имя и расположение проекта или решения, а затем выберите Создать.

  5. При необходимости измените целевую и минимальную версии платформы, а затем нажмите кнопку OK.

Visual Studio создаст тестовый проект и откроет его в Обозревателе решений Visual Studio.

Screenshot that shows the UWP unit test project in Solution Explorer.

Изменение манифеста приложения проекта

  1. В Обозревателе решений щелкните правой кнопкой мыши файл Package.appxmanifest и выберите пункт Открыть.

  2. В конструкторе манифеста выберите вкладку Возможности.

  3. В списке Возможности выберите возможности, необходимые для кода и модульного теста. Например, если вашему коду и его модульному тесту требуется доступ к Интернету, установите флажок Интернет.

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

Screenshot that shows a unit test manifest.

Screenshot that shows a unit test manifest.

Добавление кода в модульный тест для приложения UWP

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

Запуск модульного теста с помощью Обозревателя тестов

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

  1. В меню Visual Studio Тест выберите элемент Обозреватель тестов. Откроется окно Обозреватель тестов.

  2. В Обозревателе тестов выберите значок Запустить все. Команда Запустить все используется для обнаружения тестов в проектах UWP.

    Screenshot that shows Test Explorer Run all icon.

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

Screenshot that shows the Test Explorer with completed test information.

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

Screenshot that shows a Test Explorer context menu.

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

  1. В меню Visual Studio Тест выберите элемент Обозреватель тестов. Откроется окно Обозреватель тестов.

  2. В Обозревателе тестов выберите значок Запустить все. Команда Запустить все используется для обнаружения тестов в проектах UWP.

    Screenshot that shows Test Explorer Run all icon.

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

Screenshot that shows the Test Explorer with completed test information.

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

Screenshot that shows a Test Explorer context menu.

Модульное тестирование класса C#

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

В примере проекта кода Maths класс Rooter реализует функцию, которая вычисляет предполагаемый квадратный корень числа. Проект RooterTests выполняет модульное тестирование класса Rooter.

Создание решения и проектов

Создание проекта приложения UWP:

  1. В Visual Studio в меню Файл выберите элемент Новый проект.
  2. На странице Создание проекта в поле поиска введите фразу пустое приложение, а затем выберите шаблон проекта C# Пустое приложение (универсальное приложение для Windows).
  3. На странице Настроить новый проект укажите имя проекта Maths. Затем выберите команду Создать.
  4. При необходимости измените целевую и минимальную версии платформы, а затем нажмите кнопку OK. Visual Studio создаст проект и откроет его в Обозревателе решений.

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

  1. В Обозревателе решений щелкните решение Maths правой кнопкой мыши и выберите пункты Добавить>Новый проект.
  2. На странице Добавление нового проекта в поле поиска введите фразу модульный тест, а затем выберите шаблон проекта C# Приложение модульного тестирования (универсальное приложение Windows).
  3. Задайте для тестового проекта имя RooterTests и выберите команду Создать.
  4. При необходимости измените целевую и минимальную версии платформы, а затем нажмите кнопку OK. Проект с именем RooterTests появится под решением Maths в Обозревателе решений.

Проверка с помощью Обозревателя тестов, что тесты запускаются

Класс Assert содержит несколько статических методов, которые можно использовать для проверки результатов в тестовых методах.

  1. В Обозревателе решений выберите файл UnitTest.cs в проекте RooterTests.

  2. Вставьте в TestMethod1 следующий код:

    [TestMethod]
    public void TestMethod1()
    {
        Assert.AreEqual(0, 0);
    }
    
  3. В разделе Обозреватель тестов выберите команду Запустить все тесты.

  4. Будет выполнена сборка и запуск тестового проекта, и тест появится в разделе Пройденные тесты. В области Сводка по группе справа содержатся сведения о тесте.

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

  1. В Обозревателе решений щелкните правой кнопкой мыши проект Maths и выберите элементы Добавить>Класс.

  2. Присвойте файлу класса имя Rooter.cs, а затем нажмите кнопку Добавить.

  3. В редакторе кода добавьте следующий код в класс Rooter в файле Rooter.cs:

    public Rooter()
    {
    }
    
    // estimate the square root of a number
    public double SquareRoot(double x)
    {
        return 0.0;
    }
    

    Класс Rooter объявляет конструктор и метод оценки SquareRoot. Метод SquareRoot — это минимальная реализация для проверки базовой настройки тестирования.

  4. Измените ключевое слово internal в public в объявлении класса Rooter, чтобы код теста мог получить к нему доступ.

    public class Rooter
    
  1. В Обозревателе решений щелкните правой кнопкой мыши проект Maths и выберите элементы Добавить>Класс.

  2. Присвойте файлу класса имя Rooter.cs, а затем нажмите кнопку Добавить.

  3. В редакторе кода добавьте следующий код в класс Rooter в файле Rooter.cs:

    public Rooter()
    {
    }
    
    // estimate the square root of a number
    public double SquareRoot(double x)
    {
        return 0.0;
    }
    

    Класс Rooter объявляет конструктор и метод оценки SquareRoot. Метод SquareRoot — это минимальная реализация для проверки базовой настройки тестирования.

  4. Добавьте ключевое слово public в объявление класса Rooter, чтобы код теста мог получить к нему доступ.

    public class Rooter
    

Добавление ссылки из тестового проекта в проект приложения

  1. В Обозревателе решений щелкните правой кнопкой мыши проект RooterTests и выберите элементы Добавить>Ссылка.

  2. В диалоговом окне Диспетчер ссылок — RooterTests разверните узел Проекты и выберите проект Maths.

    Screenshot that shows adding a reference to the Maths project.

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

  4. Добавьте следующую инструкцию using в UnitTest.cs после строки using Microsoft.VisualStudio.TestTools.UnitTesting;:

    using Maths;
    
  1. В Обозревателе решений щелкните правой кнопкой мыши проект RooterTests и выберите элементы Добавить>Ссылка.

  2. В диалоговом окне Диспетчер ссылок — RooterTests разверните узел Проекты и выберите проект Maths.

    Screenshot that shows adding a reference to the Maths project.

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

  4. Добавьте следующую инструкцию using в UnitTest.cs после строки using Microsoft.VisualStudio.TestTools.UnitTesting;:

    using Maths;
    

Добавление теста, использующего функцию приложения

  1. Добавьте в UnitTest.cs следующий метод теста:

    [TestMethod]
    public void BasicTest()
    {
        Maths.Rooter rooter = new Rooter();
        double expected = 0.0;
        double actual = rooter.SquareRoot(expected * expected);
        double tolerance = .001;
        Assert.AreEqual(expected, actual, tolerance);
    }
    

    В Обозревателе решений в узле Незапускавшиеся тесты в Обозревателе тестов появится новый тест.

  2. Чтобы избежать ошибки, когда полезная нагрузка содержит два или больше файлов с одним и тем же путем назначения, в Обозревателе решений разверните узел Свойства в проекте Maths и удалите файл Default.rd.xml.

  3. Сохраните все файлы.

Запуск тестов

В Обозревателе тестов выберите значок Запустить все тесты. Будет выполнена сборка решения, а также запущены и успешно пройдены тесты.

Screenshot that shows Basic Test passed in Test Explorer

В Обозревателе тестов выберите значок Запустить все тесты. Будет выполнена сборка решения, а также запущены и успешно пройдены тесты.

Screenshot that shows Basic Test passed in Test Explorer

Если при запуске теста возникает ошибка повторяющейся сущности, удалите файл директив среды выполнения из Properties\Default.rd.xml тестового проекта и повторите попытку.

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

Добавление тестов и их передача

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

  1. Добавьте в UnitTest.cs новый тест с именем RangeTest:

    [TestMethod]
    public void RangeTest()
    {
        Rooter rooter = new Rooter();
        for (double v = 1e-6; v < 1e6; v = v * 3.2)
        {
            double expected = v;
            double actual = rooter.SquareRoot(v*v);
            double tolerance = expected/1000;
            Assert.AreEqual(expected, actual, tolerance);
        }
    }
    
  2. Запустите тест RangeTest и убедитесь, что он завершается сбоем.

    Screenshot that shows the RangeTest fails in Test Explorer.

    Совет

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

  3. Исправьте код приложения, чтобы новый тест был успешно пройден. В файле Rooter.cs измените функцию SquareRoot следующим образом:

    public double SquareRoot(double x)
    {
        double estimate = x;
        double diff = x;
        while (diff > estimate / 1000)
        {
            double previousEstimate = estimate;
            estimate = estimate - (estimate * estimate - x) / (2 * estimate);
            diff = Math.Abs(previousEstimate - estimate);
        }
        return estimate;
    }
    
  4. В Обозревателе тестов выберите значок Запустить все тесты. Теперь все три теста проходятся.

  1. Добавьте в UnitTest.cs новый тест с именем RangeTest:

    [TestMethod]
    public void RangeTest()
    {
        Rooter rooter = new Rooter();
        for (double v = 1e-6; v < 1e6; v = v * 3.2)
        {
            double expected = v;
            double actual = rooter.SquareRoot(v*v);
            double tolerance = expected/1000;
            Assert.AreEqual(expected, actual, tolerance);
        }
    }
    
  2. Запустите тест RangeTest и убедитесь, что он завершается сбоем.

    Screenshot that shows the RangeTest fails in Test Explorer.

    Совет

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

  3. Исправьте код приложения, чтобы новый тест был успешно пройден. В файле Rooter.cs измените функцию SquareRoot следующим образом:

    public double SquareRoot(double x)
    {
        double estimate = x;
        double diff = x;
        while (diff > estimate / 1000)
        {
            double previousEstimate = estimate;
            estimate = estimate - (estimate * estimate - x) / (2 * estimate);
            diff = Math.Abs(previousEstimate - estimate);
        }
        return estimate;
    }
    
  4. В Обозревателе тестов выберите значок Запустить все тесты. Теперь все три теста проходятся.

Рефакторинг кода

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

Упрощение оценки квадратного корня

  1. В Rooter.cs упростите центральное вычисление в функции SquareRoot. Для этого измените следующую строку:

    estimate = estimate - (estimate * estimate - x) / (2 * estimate);

    По

    estimate = (estimate + x/estimate) / 2.0;

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

Удаление дублирующегося кода теста

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

Чтобы добавить вспомогательный метод, в UnitTest.cs сделайте следующее:

  1. Добавьте приведенный ниже метод в класс UnitTest1:

    private double ToleranceHelper(double expected)
    {
        return expected / 1000;
    }
    
  2. В RangeTest измените следующую строку:

    double tolerance = expected/1000;

    По

    double tolerance = ToleranceHelper(expected);

  3. Запустите тест RangeTest, чтобы убедиться, что он все еще успешно выполняется.

Совет

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

Следующие шаги