【问题标题】:Visual Studio Enterprise Code Coverage report in TeamCityTeamCity 中的 Visual Studio Enterprise 代码覆盖率报告
【发布时间】:2019-07-06 08:21:57
【问题描述】:

是否有人有将 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】:

    这比应有的复杂得多,但我是这样做的。

    第一步是使用这个 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 类型,表示它找到的任何覆盖率文件。然后,您可以手动解析它以获取覆盖信息并使用 Teamcity 服务消息写出覆盖信息。即在控制台上写这样的东西:

    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 上运行此代码构建的工具来使用它,将其作为工件依赖项链接到我关心的构建。然后我在创建的覆盖文件上运行单元测试调用该工具。呼,这很容易不是吗.......

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-10-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多