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


Пошаговое руководство. Разработка на основе тестов с помощью обозревателя тестов

Создайте модульные тесты, чтобы обеспечить правильную работу кода с помощью добавочных изменений кода. Существует несколько платформ, которые можно использовать для написания модульных тестов, включая некоторые, разработанные сторонними разработчиками. Некоторые платформы тестирования специализированы для тестирования на разных языках или платформах. Обозреватель тестов предоставляет единый интерфейс для модульных тестов в любой из этих платформ. Дополнительные сведения об Обозревателе тестов см. в разделе «Запуск модульных тестов с помощью Обозревателя тестов» и Часто задаваемые вопросы по Обозревателю тестов.

В этом пошаговом руководстве показано, как разработать тестируемый метод в C# с помощью Microsoft Test Framework (MSTest). Его можно легко адаптировать для других языков или других платформ тестирования, таких как NUnit. Дополнительные сведения см. в установке сторонних фреймворков модульного тестирования.

Создать тест и генерировать код

  1. Создайте проект библиотеки классов C# для .NET или .NET Standard. Этот проект будет содержать код, который мы хотим протестировать. Назовите проект MyMath.

  2. В том же решении добавьте новый тестовый проект MSTest для .NET.

    В Visual Studio 2019 версии 16.9 имя шаблона проекта MSTest — проект модульного тестирования.

    Назовите тестовый проект MathTests.

    Новые проекты кода и тестирования

    Новые проекты кода и тестирования

  3. В тестовом проекте напишите простой метод теста, который проверяет результат, полученный для определенных входных данных. Добавьте следующий код в Test1 класс или UnitTest1 класс:

    [TestMethod]
    public void BasicRooterTest()
    {
      // Create an instance to test:
      Rooter rooter = new Rooter();
      // Define a test input and output value:
      double expectedResult = 2.0;
      double input = expectedResult * expectedResult;
      // Run the method under test:
      double actualResult = rooter.SquareRoot(input);
      // Verify the result:
      Assert.AreEqual(expectedResult, actualResult, delta: expectedResult / 100);
    }
    
  4. Создайте тип из тестового кода.

    1. Поместите курсор на Rooter, и затем откройте меню лампочки.

      Выберите "Создать новый тип".

      Сгенерировать быстрое действие нового типа

      Выберите "Создать тип Rooter">Создать новый тип.

      Сгенерировать быстрое действие нового типа

    2. В диалоговом окне "Создать тип " задайте для Project значение MyMath, проект библиотеки классов и нажмите кнопку "ОК".

      Диалоговое окно создания типа в Visual Studio 2019

      Диалоговое окно создания типа в Visual Studio 2019

  5. Создайте метод из тестового кода. Переместите курсор на SquareRoot, затем в меню лампочки выберите «Создать метод SquareRoot» или «Создать метод Rooter.SquareRoot».

  6. Запустите модульный тест.

    1. Откройте обозреватель тестов.

      Чтобы открыть обозреватель тестов в меню "Тест" , выберите "Обозреватель тестов".

      Чтобы открыть обозреватель тестов в меню"Тест", выберите обозреватель тестов >.

    2. В обозревателе тестов нажмите кнопку "Запустить все ", чтобы запустить тест.

    Решение собирается, тест запускается и завершается сбоем.

  7. Выберите имя теста.

    Сведения о тесте отображаются в области сводки сведений о тесте .

    Сводка сведений о тестах в обозревателе тестов

    Сводка сведений о тестах в обозревателе тестов

  8. Выберите верхнюю ссылку в разделе "Трассировка стека ", чтобы перейти к расположению, где произошел сбой теста.

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

Проверка изменения кода

  1. В файле Class1.cs улучшите код SquareRoot:

    public double SquareRoot(double input)
    {
        return input / 2;
    }
    
  2. В обозревателе тестов выберите "Выполнить все".

    Решение собирается, и тесты выполняются и проходят успешно.

    Обозреватель тестов, показывающий прохождение теста

    Обозреватель тестов, показывающий прохождение теста

Расширение диапазона входных данных

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

Подсказка

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

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

    [TestMethod]
    public void RooterValueRange()
    {
        // Create an instance to test.
        Rooter rooter = new Rooter();
    
        // Try a range of values.
        for (double expected = 1e-8; expected < 1e+8; expected *= 3.2)
        {
            RooterOneValue(rooter, expected);
        }
    }
    
    private void RooterOneValue(Rooter rooter, double expectedResult)
    {
        double input = expectedResult * expectedResult;
        double actualResult = rooter.SquareRoot(input);
        Assert.AreEqual(expectedResult, actualResult, delta: expectedResult / 1000);
    }
    
  2. В обозревателе тестов выберите "Выполнить все".

    Новый тест завершается сбоем (хотя первый тест по-прежнему проходит). Чтобы найти точку сбоя, выберите неудачный тест, а затем просмотрите сведения в области "Сводка сведений о тестах".

  3. Проверьте тестируемый метод, чтобы увидеть, что может быть неправильно. Измените SquareRoot код следующим образом:

    public double SquareRoot(double input)
    {
      double result = input;
      double previousResult = -input;
      while (Math.Abs(previousResult - result) > result / 1000)
      {
        previousResult = result;
        result = result - (result * result - input) / (2 * result);
      }
      return result;
    }
    
  4. В обозревателе тестов выберите "Выполнить все".

    Оба теста теперь проходят.

Добавление тестов для исключительных случаев

  1. Добавьте новый тест для отрицательных входных данных:

    [TestMethod]
    public void RooterTestNegativeInput()
    {
        Rooter rooter = new Rooter();
        Assert.ThrowsException<ArgumentOutOfRangeException>(() => rooter.SquareRoot(-1));
    }
    
  2. В обозревателе тестов выберите "Выполнить все".

    Новый тест неудачен.

    Если тестируемый метод зацикливается, нажмите Отмена на панели инструментов Обозревателя тестов. Тест останавливает выполнение и завершается сбоем.

  3. Исправьте код SquareRoot, добавив в начале метода следующую инструкцию if.

    public double SquareRoot(double input)
    {
        if (input <= 0.0)
        {
            throw new ArgumentOutOfRangeException();
        }
        ...
    
  4. В обозревателе тестов выберите "Выполнить все".

    Все тесты пройдены.

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

Перепишите код, но не изменяйте тесты.

Подсказка

Рефакторинг — это изменение, которое предназначено для улучшения или упрощения понимания кода. Он не предназначен для изменения поведения кода, поэтому тесты не изменяются.

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

  1. Измените строку, которая вычисляет result, в методе SquareRoot следующим образом:

    public double SquareRoot(double input)
    {
        if (input <= 0.0)
        {
            throw new ArgumentOutOfRangeException();
        }
    
        double result = input;
        double previousResult = -input;
        while (Math.Abs(previousResult - result) > result / 1000)
        {
            previousResult = result;
            result = (result + input / result) / 2;
            //was: result = result - (result * result - input) / (2*result);
        }
        return result;
    }
    
  2. Выберите Запустить все и убедитесь, что все тесты по-прежнему проходят.

    Обозреватель тестов, показывающий 3 успешно пройденных теста

    Обозреватель тестов, показывающий 3 успешно пройденных теста