Подтвердить что ты не робот

Сбой сборки, если покрытие кода ниже порогового значения в TFS2012

Я пытаюсь сбой сборки в службе TFS (Hosted TFS2012), когда уровень покрытия кода ниже порогового значения.

Я уже возился с решением в http://scrumdod.blogspot.co.uk/2011/04/fail-build-if-code-coverage-is-low.html

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

Как мне найти (или установить) местоположение файла .coverage в TFS2012 или TFSService?

Альтернативно, есть ли другой способ, которым я могу сбой сборки, если покрытие кода ниже порога?

4b9b3361

Ответ 1

Для этого потребуется несколько шагов:

  • Создание пользовательской операции сборки
  • Добавить операцию в контроллер сборки
  • Вызов этой пользовательской операции сборки в процессе новой сборки
  • Использовать новый процесс сборки

1. Создайте пользовательскую операцию сборки.

Создайте новый проект в VS2012 (я назвал свою CodeCoverageLibrary). Сопоставьте следующие сборки:

  • Microsoft.TeamFoundation.Build.Client
  • Microsoft.TeamFoundation.Client
  • Microsoft.TeamFoundation.TestManagement.Client
  • Microsoft.TeamFoundation.WorkItemTracking.Client
  • Система
  • System.Activities
  • System.Core
  • System.Xaml

Вы можете использовать следующий код:

using System;
using System.Activities;
using System.Collections.Generic;
using Microsoft.TeamFoundation.Build.Client;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.TestManagement.Client;

namespace CodeCoverageLibrary
{
    [BuildActivity(HostEnvironmentOption.All)]
    public sealed class GetCodeCoverage : CodeActivity<double>
    {
        public InArgument<IBuildDetail> BuildDetail { get; set; }

        protected override double Execute(CodeActivityContext context)
        {
            var buildDetail = BuildDetail.Get(context);
            var buildCoverages = GetBuildCoverages(buildDetail.BuildServer.TeamProjectCollection.Uri,
                                                   buildDetail.TeamProject, buildDetail.Uri);
            return GetTotalCoverage(buildCoverages);
        }

        private static IEnumerable<IBuildCoverage> GetBuildCoverages(Uri uri, string projectName, Uri buildUri)
        {
            return TfsTeamProjectCollectionFactory.GetTeamProjectCollection(uri)
                                                  .GetService<ITestManagementService>()
                                                  .GetTeamProject(projectName)
                                                  .CoverageAnalysisManager.QueryBuildCoverage(buildUri.ToString(),
                                                                                              CoverageQueryFlags.Modules);
        }

        private static double GetTotalCoverage(IEnumerable<IBuildCoverage> buildCoverages)
        {
            int totalCoveredBlocks = 0, totalUncoveredBlocks = 0;
            foreach (var buildCoverage in buildCoverages)
            {
                foreach (var module in buildCoverage.Modules)
                {
                    totalCoveredBlocks += module.Statistics.BlocksCovered;
                    totalUncoveredBlocks += module.Statistics.BlocksNotCovered;
                }
            }

            return (totalCoveredBlocks == 0 && totalUncoveredBlocks == 0)
                                      ? 0.0
                                      : ((double) totalCoveredBlocks) /
                                        ((double) (totalCoveredBlocks + totalUncoveredBlocks));
        }
    }
}

Скомпилируйте проект и добавьте его в управляемый версией путь к TFS.

2. Добавьте активность в контроллер сборки

В Team Explorer перейдите в Сборка > Действия > Управление контроллерами сборки.... Затем нажмите Свойства... для контроллера сборки. В разделе Путь управления версиями к пользовательским сборкам введите путь, который вы использовали выше.

3. Вызов этой пользовательской сборки в процессе сборки

Скопируйте BuildProcessTemplates\DefaultTemplate.11.1.xaml в новый файл.

Обновите начало нового файла XAML, чтобы включить следующее:

<Activity ...
          xmlns:ccl="clr-namespace:CodeCoverageLibrary;assembly=CodeCoverageLibrary"
          ...
          >
  <x:Members>
    ...
    <x:Property Name="CodeCoverageTolerance" Type="InArgument(x:Double)" />
  </x:Members>
  ...
  <this:Process.Metadata>
    <mtbw:ProcessParameterMetadataCollection>
      ...
      <mtbw:ProcessParameterMetadata BrowsableWhen="EditingDefinition" Category="#900 Misc" DisplayName="CodeCoverageTolerance" Description="If the overall code coverage drops below this threshold, then the build will fail. This is a number between 0 and 1." ParameterName="CodeCoverageTolerance" />
    </mtbw:ProcessParameterMetadataCollection>
  </this:Process.Metadata>

Обновите конец файла XAML, чтобы включить следующее:

      <Sequence DisplayName="Code Coverage Check" mtbwt:BuildTrackingParticipant.Importance="None">
        <Sequence.Variables>
          <Variable x:TypeArguments="x:Double" Name="CodeCovered" />
        </Sequence.Variables>
        <ccl:GetCodeCoverage DisplayName="Getting Code Coverage" BuildDetail="[BuildDetail]" Result="[CodeCovered]" />
        <If Condition="[CodeCovered &lt; CodeCoverageTolerance]">
          <If.Then>
            <Sequence DisplayName="Comparing Code Coverage Against Tolerance">
              <mtbwa:SetBuildProperties DisplayName="Set TestStatus to Failed" mtbwt:BuildTrackingParticipant.Importance="Low" PropertiesToSet="TestStatus" TestStatus="[Microsoft.TeamFoundation.Build.Client.BuildPhaseStatus.Failed]" />
              <mtbwa:WriteBuildError Message="[&quot;Code Coverage of &quot; + CodeCovered.ToString(&quot;P&quot;) + &quot; is less than required &quot; + CodeCoverageTolerance.ToString(&quot;P&quot;)]" />
            </Sequence>
          </If.Then>
        </If>
      </Sequence>
    </mtbwa:AgentScope>
    <mtbwa:InvokeForReason DisplayName="Check In Gated Changes for CheckInShelveset Builds" Reason="CheckInShelveset">
      <mtbwa:CheckInGatedChanges DisplayName="Check In Gated Changes" />
    </mtbwa:InvokeForReason>
  </Sequence>
</Activity>

Проверьте это на TFS.

4. Используйте новый процесс сборки

В Team Explorer перейдите в Сборка и щелкните правой кнопкой мыши по определению вашей сборки. Перейдите в Изменить определение сборки... > Процесс. Разверните шаблон процесса сборки и нажмите Создать.... Нажмите Выбрать существующий файл XAML и поместите путь к новому файлу XAML. Нажмите ОК. Теперь вы можете увидеть CodeCoverageTolerance под 4. Разное. Вы можете ввести число от 0 до 1, чтобы указать желаемый процент.

Ответ 3

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

return (totalCoveredBlocks == 0 && totalUncoveredBlocks == 0)
                                  ? 0.0
                                  : Math.Round(((double)totalCoveredBlocks) /
                                    ((double)(totalCoveredBlocks + totalUncoveredBlocks)) * 100, 2);