当代码覆盖率低于阈值时,我正试图在TFS服务(托管TFS2012)中构建失败。
我一直在寻找http://scrumdod.blogspot.co.uk/2011/04/fail-build-if-code-coverage-is-low.html
的解决方案但是,我正在使用TFS2012,很多东西似乎已经改变了。特别是,测试运行的配置完全不同,似乎没有任何方法可以在构建过程模板或.runsettings文件中获取或设置.coverage文件的位置和名称。
我如何在TFS2012或TFSService中查找(或设置).coverage文件的位置?
另外,如果代码覆盖率低于阈值,还有另一种方法可以使构建失败吗?
答案 0 :(得分:9)
这需要几个步骤:
在VS2012中创建一个新项目(我称之为CodeCoverageLibrary。参考以下程序集:
您可以使用以下代码:
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上的版本控制路径。
在团队资源管理器中,转到构建&gt; 操作&gt; 管理构建控制器...... 。然后单击构建控制器的属性... 。在自定义程序集的版本控制路径下,放置上面使用的路径。
将 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 < 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="["Code Coverage of " + CodeCovered.ToString("P") + " is less than required " + CodeCoverageTolerance.ToString("P")]" />
</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。
在团队资源管理器中,转到构建,然后右键单击构建定义。转到修改构建定义... &gt; <强>过程即可。展开构建流程模板,然后点击新建... 。单击选择现有XAML文件并将路径放入新的XAML文件。点击确定。您现在应该在 4下看到 CodeCoverageTolerance 。其它即可。您可以输入0到1之间的数字来表示您想要的百分比。
答案 1 :(得分:0)
您可以在RunTests活动之后添加您的活动,您可以在其中查询build for code coverage attachments和merge and parse the .coverage files以通过/失败构建。
答案 2 :(得分:0)
上述解决方案中只有一点,您应该将计算修改为这样,以确保将百分比值返回到两位小数
return (totalCoveredBlocks == 0 && totalUncoveredBlocks == 0)
? 0.0
: Math.Round(((double)totalCoveredBlocks) /
((double)(totalCoveredBlocks + totalUncoveredBlocks)) * 100, 2);