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

问题描述 投票:3回答:1

有没有人有任何将Visual Studio Enterprise 2017代码覆盖率结果(* .coverage或* .coveragexml)导入TeamCity的经验?我们正在测试一个C ++项目,所以我们不能使用TeamCitys内置的覆盖率报告工具。

帮助页面(https://confluence.jetbrains.com/display/TCD10/Code+Coverage)暗示可能支持MSTest / VSTest,但是我没有找到任何提供指令的内容(无论是在这里还是在Google上),甚至没有找到它可以完成的任何内容。

c++ visual-studio teamcity code-coverage
1个回答
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消息写出覆盖信息。即将这样的内容写入控制台:

teamcity [buildStatisticValue key ='CodeCoverageB'value ='x']

其中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文件上的工具。 P,这很容易就不是.......

© www.soinside.com 2019 - 2024. All rights reserved.