任何人都没有将Visual Studio Enterprise 2017代码覆盖率结果(* .coverage或* .coveragexml)导入TeamCity的经验吗?我们正在测试一个C ++项目,因此我们无法使用内置的覆盖率报告工具中的TeamCity。
帮助页面(https://confluence.jetbrains.com/display/TCD10/Code+Coverage)暗示可能支持MSTest / VSTest,但是(在这里或在Google上)我找不到任何能够提供指示甚至可以完成指示的内容。 / p>
答案 0 :(得分:2)
这比应该的要复杂得多,但这是我的工作方式。
第一步是使用此dll Microsoft.VisualStudio.Coverage.Analysis访问CoverageInfo和CoverageDS类型。然后,您可以执行以下操作:
var infoFiles = new List<CoverageInfo>();
try
{
var paths = Directory.GetFiles(args[0], "*.coverage", SearchOption.AllDirectories);
infoFiles.AddRange(paths.Select(path => CoverageInfo.CreateFromFile(path, new string[] {path}, new string[] { })));
}
catch (Exception e)
{
Console.WriteLine("Error opening coverage data: {0}", e.Message);
return 1;
}
var coverageData = new List<CoverageDS>(infoFiles.Select(coverageInfo => coverageInfo.BuildDataSet()));
var data = coverageData.Aggregate(new CoverageDS(), CoverageDS.Join);
这会给您一个CoverageDS类型,代表它找到的所有coverage文件。然后,您可以手动解析它以获得覆盖率信息,并使用Teamcity Service消息写出覆盖率信息。即将类似以下内容的内容写入控制台:
其中x是覆盖的块的百分比
可以在此处找到服务器消息的完整列表:custom chart
我最终使用了fSharp xml类型的提供程序来解析coverageinfo,以便为我提供块覆盖率值。
namespace CoverageXMLParser
open FSharp.Data
type coverageXML = XmlProvider<"sample.xml">
type coverageStats = {coveredLines : int; totalLines : int}
module Parser =
let TeamcityStatAbsLinesCoveredString = "CodeCoverageAbsLCovered"
let TeamcityStatAbsTotalString = "CodeCoverageAbsLTotal"
let TeamcityStatCoveredBlocksString = "CodeCoverageB"
let (TeamcityServiceMessageString : Printf.TextWriterFormat<_>)= "##teamcity[buildStatisticValue key='%s' value='%f']"
let filterXML (xml: string) filter =
let coverage = coverageXML.Parse(xml)
let filtered = coverage.Modules |> Array.filter(fun x -> x.ModuleName.Contains(filter))
coverageXML.CoverageDsPriv(filtered, coverage.SourceFileNames).XElement.ToString()
let getModules (xml : string) =
coverageXML.Parse(xml).Modules
let filterModules (xml: string) filter =
getModules xml |> Array.filter(fun x -> x.ModuleName.Contains(filter))
let getCoveredBlocks modules =
modules |> Array.fold( fun acc (elem : coverageXML.Module) -> acc + elem.BlocksCovered ) 0
let getUnCoveredBlocks modules =
modules |> Array.fold( fun acc (elem : coverageXML.Module) -> acc + elem.BlocksNotCovered ) 0
let getCoveredLines modules =
modules |> Array.fold( fun acc (elem : coverageXML.Module) -> acc + elem.LinesCovered ) 0
let getUncoveredLines modules=
modules |> Array.fold( fun acc (elem : coverageXML.Module) -> acc + elem.LinesNotCovered) 0
let getPartialCoveredLines modules =
modules |> Array.fold( fun acc (elem : coverageXML.Module) -> acc + elem.LinesPartiallyCovered ) 0
let getCoverageLineStats modules =
let totalLines = getCoveredLines modules + getUncoveredLines modules + getPartialCoveredLines modules
{coveredLines = getCoveredLines modules; totalLines = totalLines}
let getCoveredBlocksPercent modules =
let covered = getCoveredBlocks modules
let uncovered = getUnCoveredBlocks modules
let percent = float covered / float (uncovered + covered)
percent * 100.0
let writeTeamcityCoverageMessageFromXml xml =
let filteredModules = filterModules xml "test"
printfn TeamcityServiceMessageString TeamcityStatCoveredBlocksString (getCoveredBlocksPercent filteredModules)
您需要做的就是创建一个新的fsharp项目,安装出色的fSharp.Data nuget软件包,并在项目目录中提供sample.xml。可以通过在CoverageInfo上调用getXml()方法并写入文件来获取sample.xml。酷的是,我可以使用filterModules函数过滤掉所有外部代码。
我通过在teamcity上构建运行此代码的工具来使用它,并将其作为工件依赖项链接到我关心的构建。然后,我运行单元测试,在创建的coverage文件上调用该工具。哎呀,那很容易,不是吗……。