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


День в жизни разработчика devops: написание нового кода для истории пользователя

Azure DevOps Services | Azure DevOps Server 2022 — Azure DevOps Server 2019

Visual Studio 2019 | Visual Studio 2022

В этом руководстве описывается, как вы и ваша команда могут получить максимальную выгоду от последних версий система управления версиями Team Foundation (TFVC) и Visual Studio для создания приложения. В этом руководстве приведены примеры использования Visual Studio и TFVC для проверка и обновления кода, приостановки работы при прерывании работы, запроса проверки кода, проверка в изменениях и выполнения других задач.

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

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

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

Примечание.

Функции проверки кода и работы Visual Studio доступны со следующими выпусками:

  • Visual Studio 2022: Visual Studio Community, Visual Studio Professional и Visual Studio Enterprise
  • Visual Studio 2019: Visual Studio Professional и Visual Studio Enterprise

Просмотр рабочих элементов и подготовка к началу работы

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

В visual Studio Team Обозреватель на странице "Моя работа" вы перетащите эту задачу из списка доступных рабочих элементов в список "Выполняется работа".

Просмотр невыполненной работы и подготовка задач для начала работы

Снимок экрана: страница

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

  2. На домашней странице выберите "Моя работа".

  3. На странице "Моя работа" перетащите задачу из списка доступных рабочих элементов в раздел "Выполняется работа".

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

Проект добавочного плана работы

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

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

Вы не проверка в коде на Azure DevOps Server, пока не завершите всю задачу.

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

  1. Создайте заглушку метода теста, то есть только сигнатуру метода.
  2. Удовлетворить один конкретный типичный случай.
  3. Проверьте широкий диапазон. Убедитесь, что код правильно реагирует на большой диапазон значений.
  4. Исключение на отрицательное. Справься с неправильными параметрами.
  5. Покрытие кода. Убедитесь, что по крайней мере 80% кода выполняется модульными тестами.

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

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

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

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

  1. Выберите Файл>Создать проект.
  2. В диалоговом окне "Создание проекта" щелкните стрелку рядом со всеми языками и выберите C#, щелкните стрелку рядом со всеми типами проектов и выберите "Тест" и выберите "Тестовый проект MSTest".
  3. Выберите Далее и нажмите Создать.

Снимок экрана: модульный тест, выбранный в диалоговом окне

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

using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Fabrikam.Math.UnitTest
{
    [TestClass]
    public class UnitTest1
    {
        [TestMethod]
        // Demonstrates how to call the method.
        public void SignatureTest()
        {
            // Create an instance:
            var math = new Fabrikam.Math.LocalMath();

            // Get a value to calculate:
            double input = 0.0;

            // Call the method:
            double actualResult = math.SquareRoot(input);

            // Use the result:
            Assert.AreEqual(0.0, actualResult);
        }
    }
}

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

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

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

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

  1. Создайте тестовый проект с помощью предыдущих шагов. Вы можете выбрать такие языки, как C#, F# и Visual Basic.

  2. Добавьте тесты в предоставленный тестовый класс. Каждый модульный тест — один метод.

    • Каждый модульный тест должен быть префиксирован атрибутом TestMethod , а метод модульного теста не должен иметь параметров. Вы можете использовать любое имя, которое требуется для метода модульного теста:

      [TestMethod]
      public void SignatureTest()
      {...}
      
      <TestMethod()>
      Public Sub SignatureTest()
      ...
      End Sub
      
    • Каждый метод теста должен вызывать метод Assert класса, чтобы указать, прошел ли он или завершился сбоем. Как правило, убедитесь, что ожидаемые и фактические результаты операции равны:

      Assert.AreEqual(expectedResult, actualResult);
      
      Assert.AreEqual(expectedResult, actualResult)
      
    • Методы тестирования могут вызывать другие обычные методы, которые не имеют атрибута TestMethod .

    • Тесты можно упорядочить в несколько классов. Каждый класс должен быть префиксирован атрибутом TestClass .

      [TestClass]
      public class UnitTest1
      { ... }
      
      <TestClass()>
      Public Class UnitTest1
      ...
      End Class
      

Сведения о написании модульных тестов в C++см. в статье "Написание модульных тестов для C/C++ с помощью Платформы модульного тестирования Майкрософт для C++".

Создание заглушки для нового кода

Затем создайте проект библиотеки классов для нового кода. Теперь существует проект для кода, который находится в процессе разработки, и проект для модульных тестов. Добавьте ссылку на проект из тестового проекта в код, который выполняется при разработке.

Снимок экрана: Обозреватель решений с проектами тестов и классов.

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

public double SquareRoot(double p)
{
    throw new NotImplementedException();
}

Создание классов и методов из тестов

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

Создание класса

  1. Поместите курсор в пример класса, который вы хотите создать, например, LocalMathи выберите быстрые действия и рефакторинги.
  2. В контекстном меню выберите "Создать новый тип".
  3. В диалоговом окне "Создать тип" задайте проект библиотеки классов Project. В этом примере это Fabrikam.Math.

Создание метода

  1. Поместите курсор на вызов метода, например, SquareRootи выберите быстрые действия и рефакторинг.
  2. В контекстном меню выберите "Создать метод SquareRoot".

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

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

Снимок экрана: тестовый Обозреватель с одним неудачным тестом.

Внесите простое изменение в код:

public double SquareRoot(double p)
{
    return 0.0;
}

Запустите тест еще раз, и он проходит.

Снимок экрана: модульное тестирование Обозреватель с одним переданным тестом.

Выполнение модульных тестов

Чтобы запустить модульные тесты, выполните следующую команду:

  • Выбор тестового>запуска всех тестов
  • Или, если тест Обозреватель открыт, выберите "Выполнить или запустить все тесты в представлении".

Снимок экрана:

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

  • Чтобы просмотреть полный список тестов, нажмите кнопку "Показать все".

  • Чтобы просмотреть сведения о результатах теста, выберите тест в Обозреватель теста.

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

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

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

Согласитесь с интерфейсом

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

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

[TestMethod]
public void QuickNonZero()
{
    // Create an instance to test:
    LocalMath math = new LocalMath();

    // Create a test input and expected value:
    var expectedResult = 4.0;
    var inputValue = expectedResult * expectedResult;

    // Run the method:
    var actualResult = math.SquareRoot(inputValue);

    // Validate the result:
    var allowableError = expectedResult/1e6;
    Assert.AreEqual(expectedResult, actualResult, allowableError,
        "{0} is not within {1} of {2}", actualResult, allowableError, expectedResult);
}

Совет

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

Красный, зеленый, рефакторинг...

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

Красный

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

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

Снимок экрана: проверка Обозреватель с одним неудачным тестом.

Зеленый

Записывает первую попытку кода метода, который вы разрабатываете:

public class LocalMath
{
    public double SquareRoot(double x)
    {
        double estimate = x;
        double previousEstimate = -x;
        while (System.Math.Abs(estimate - previousEstimate) > estimate / 1000)
        {
            previousEstimate = estimate;
            estimate = (estimate * estimate - x) / (2 * estimate);
        }
        return estimate;
    }

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

Снимок экрана: модульное тестирование Обозреватель с двумя переданными тестами.

Рефакторинг

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

public class LocalMath
{
    public double SquareRoot(double x)
    {
        double estimate = x;
        double previousEstimate = -x;
        while (System.Math.Abs(estimate - previousEstimate) > estimate / 1000)
        {
            previousEstimate = estimate; 
            estimate = (estimate + x / estimate) / 2;
            //was: estimate = (estimate * estimate - x) / (2 * estimate);
        }
        return estimate;
    }

Убедитесь, что тесты по-прежнему проходят.

Советы

  • Каждое изменение, внесенные при разработке кода, должно быть рефакторингом или расширением:

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

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

  • Запустите тесты после каждого изменения.

... и повторите

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

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

[TestMethod]
public void SqRtValueRange()
{
    LocalMath math = new LocalMath();
    for (double expectedResult = 1e-8;
        expectedResult < 1e+8;
        expectedResult = expectedResult * 3.2)
    {
        VerifyOneRootValue(math, expectedResult);
    }
}
private void VerifyOneRootValue(LocalMath math, double expectedResult)
{
    double input = expectedResult * expectedResult;
    double actualResult = math.SquareRoot(input);
    Assert.AreEqual(expectedResult, actualResult, expectedResult / 1e6);
}

Этот тест проходит при первом запуске.

Снимок экрана: тестовый Обозреватель с тремя переданными тестами.

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

Совет

Всегда завершайте тест сбоем, прежде чем пройти его.

Исключения

Теперь перейдите к написанию тестов для исключительных входных данных:

[TestMethod]
public void RootTestNegativeInput()
{
    LocalMath math = new LocalMath();
    try
    {
        math.SquareRoot(-10.0);
    }
    catch (ArgumentOutOfRangeException)
    {
        return;
    }
    catch
    {
        Assert.Fail("Wrong exception on negative input");
        return;
    }
    Assert.Fail("No exception on negative input");
}

Этот тест помещает код в цикл. Нажмите кнопку "Отмена" в тестовом Обозреватель. Это завершает код в течение 10 секунд.

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

[TestMethod, Timeout(1000)]
public void RootTestNegativeInput()
{...

Явное время ожидания делает тест сбоем.

Обновите код, чтобы справиться с этим исключительным случаем:

public double SquareRoot(double x)
{
    if (x <= 0.0) 
    {
        throw new ArgumentOutOfRangeException();
    }

Регрессия

Новый тест проходит, но есть регрессия. Тест, который использовался для передачи, завершается ошибкой:

Снимок экрана: сбой модульного теста, который ранее прошел.

Найдите и исправьте ошибку:

public double SquareRoot(double x)
{
    if (x < 0.0)  // not <=
    {
        throw new ArgumentOutOfRangeException();
    }

После исправления все тесты проходят:

Снимок экрана: модульное тестирование Обозреватель с четырьмя пройденными тестами.

Совет

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

Покрытие кода

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

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

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

Чтобы получить отчет о охвате кода, в меню "Тест Visual Studio" выберите команду "Анализ покрытия кода для всех тестов". Все тесты выполняются снова.

Снимок экрана: результат покрытия кода и кнопка

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

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

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

Когда вы закончите?

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

  • Все доступные модульные тесты проходят.

    В проекте с очень большим набором модульных тестов это может быть непрактично для разработчика, чтобы дождаться их выполнения. Вместо этого проект управляет вложенной службой проверка-in, в которой все автоматизированные тесты выполняются для каждого проверка проверка набора полок перед объединением в исходное дерево. Проверка отклоняется, если выполнение завершается ошибкой. Это позволяет разработчикам выполнять минимальный набор модульных тестов на собственных компьютерах, а затем продолжать работу, не выполняя риск нарушения сборки. Дополнительные сведения см. в статье Об использовании процесса сборки проверка шлюза для проверки изменений.

  • Покрытие кода соответствует стандарту команды. 75 % — это типичное требование проекта.

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

  • Код легко понять и расширить.

Когда все эти критерии выполнены, вы готовы проверка код в управление версиями.

Принципы разработки кода с помощью модульных тестов

При разработке кода применяются следующие принципы:

  • Разработка модульных тестов вместе с кодом и их частое выполнение во время разработки. Модульные тесты представляют спецификацию компонента.
  • Не изменяйте модульные тесты, если только требования не изменились или тесты не были неправильными. Постепенно добавляйте новые тесты, расширяя функциональные возможности кода.
  • Нацелитесь на не менее 75% кода, которые будут охвачены тестами. Просмотрите результаты покрытия кода с интервалами и перед проверка в исходном коде.
  • Проверьте модульные тесты вместе с кодом, чтобы они выполнялись непрерывными или регулярными сборками сервера.
  • Где практическая, для каждого элемента функциональности сначала напишите модульный тест. Перед разработкой кода, удовлетворяющего этому коду, выполните это.

Проверка изменений

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

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

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

Проверка изменений

  1. На странице "Моя работа" в команде Обозреватель нажмите кнопку "Войти".

    Снимок экрана: проверка в разделе

  2. На странице "Ожидающие изменения" убедитесь, что:

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

  4. Нажмите кнопку "Войти".

    Снимок экрана: проверка в ожидающих изменениях.

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

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

Снимок экрана: страница

Дополнительные сведения см. в разделе "Запуск, мониторинг и управление сборками".

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