C++ TeamCity中的Visual Studio企业代码覆盖率报告

C++ TeamCity中的Visual Studio企业代码覆盖率报告,c++,visual-studio,teamcity,code-coverage,C++,Visual Studio,Teamcity,Code Coverage,是否有人有将Visual Studio Enterprise 2017代码覆盖率结果(或*.coverage或*.coverage XML)导入TeamCity的经验?我们正在测试一个C++项目,所以我们不能使用TeavCITIs内置的覆盖报告工具。 帮助页面()提示可能支持MSTest/VSTest,但我没有找到任何(在这里或在Google上)给出说明,甚至没有声明可以执行该操作。这比应该的要复杂得多,但我是如何做到的 第一步是使用此dll Microsoft.VisualStudio.Cov

是否有人有将Visual Studio Enterprise 2017代码覆盖率结果(或*.coverage或*.coverage XML)导入TeamCity的经验?我们正在测试一个C++项目,所以我们不能使用TeavCITIs内置的覆盖报告工具。
帮助页面()提示可能支持MSTest/VSTest,但我没有找到任何(在这里或在Google上)给出说明,甚至没有声明可以执行该操作。

这比应该的要复杂得多,但我是如何做到的

第一步是使用此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);

var infoFiles=newlist();
尝试
{
var path=Directory.GetFiles(args[0],“*.coverage”,SearchOption.AllDirectories);
infoFiles.AddRange(path.Select(path=>CoverageInfo.CreateFromFile(path,新字符串[]{path},新字符串[]{}));
}
捕获(例外e)
{
WriteLine(“打开覆盖率数据时出错:{0}”,e.Message);
返回1;
}
var coverageData=新列表(infoFiles.Select(coverageInfo=>coverageInfo.BuildDataSet());
var data=coverageData.Aggregate(新的CoverageDS(),CoverageDS.Join);
这将为您提供一个CoverageDS类型,表示它找到的任何覆盖率文件。然后,您可以手动解析此内容以获取覆盖率信息,并使用Teamcity服务消息写出覆盖率信息。i、 e.在控制台上写下如下内容:

teamcity[buildStatisticValue key='CodeCoverageB'value='x'] 其中x是所覆盖块的百分比

可在此处找到服务器消息的完整列表:

最后,我使用了一个fsharpxml类型提供程序来解析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)
namespace-coverage-xmlparser
打开FSharp.Data
类型coverageXML=XmlProvider
类型coverageStats={coveredLines:int;totalLines:int}
模块解析器=
让TeamcityStatAbsLinesCoveredString=“CodeCoverageAbsLCovered”
让TeamcityStatAbsTotalString=“CodeCoverageAbsLTotal”
让TeamcityStatCoveredBlocksString=“CodeCoverageB”
let(TeamcityServiceMessageString:Printf.textWritePerformat)=“##teamcity[buildStatisticValue键='%s'值='%f']”
let filterXML(xml:string)过滤器=
let coverage=coverage xml.Parse(xml)
让filtered=coverage.Modules |>Array.filter(funx->x.ModuleName.Contains(filter))
coverageXML.CoverageDsPriv(过滤,coverage.SourceFileNames.XElement.ToString())
let getModules(xml:string)=
Parse(xml).Modules
让filterModules(xml:string)过滤=
getmodulesXML |>Array.filter(funx->x.ModuleName.Contains(filter))
设getCoveredBlocks模块=
modules |>Array.fold(fun acc(elem:coverage xml.Module)->acc+elem.blocks覆盖)0
让getUnCoveredBlocks模块=
modules |>Array.fold(fun acc(elem:coverage xml.Module)->acc+elem.BlocksNotCovered)0
让getCoveredLines模块=
modules |>Array.fold(fun acc(elem:coverage xml.Module)->acc+elem.lines覆盖)0
让getUncoveredLines模块=
modules |>Array.fold(fun acc(elem:coverage xml.Module)->acc+elem.LinesNotCovered)0
让getPartialCoveredLines模块=
modules |>Array.fold(fun acc(elem:coverage xml.Module)->acc+elem.LinesPartiallyCovered)0
让我们来看看这些模块=
设totalLines=getCoveredLines模块+getUncoveredLines模块+getPartialCoveredLines模块
{coveredLines=getCoveredLines模块;totalLines=totalLines}
让getCoveredBlocksPercent模块=
let covered=getCoveredBlocks模块
let uncovered=getUnCoveredBlocks模块
let percent=浮动覆盖/浮动(未覆盖+覆盖)
百分比*100.0
让WriteTeamCityOverageMessageFromXML=
让filteredModules=filterModules xml“测试”
打印FN TeamcityServiceMessageString TeamcityStatCoveredBlocksString(getCoveredBlocksPercent filteredModules)
您需要做的就是创建一个新的fsharp项目,安装brilliant nuget包,并在项目目录中提供sample.xml。可以通过调用CoverageInfo上的getXml()方法并写入文件来获取sample.xml。关于这一点,最酷的是我能够使用filterModules函数过滤掉任何外部代码

我通过在teamcity上运行此代码构建的工具来使用它,将其作为工件依赖项链接到我关心的构建。然后我在创建的覆盖率文件上运行单元测试并调用该工具。啊,那很容易,不是吗