Отчет о покрытии кода Visual Studio Enterprise в TeamCity - PullRequest
0 голосов
/ 12 февраля 2019

У кого-нибудь есть опыт импорта результатов покрытия кода Visual Studio Enterprise 2017 (* .coverage или * .coveragexml) в TeamCity?Мы тестируем проект C ++, поэтому мы не можем использовать встроенные в TeamCitys инструменты отчета о покрытии.

Страница справки (https://confluence.jetbrains.com/display/TCD10/Code+Coverage) подсказывает, что MSTest / VSTest может поддерживаться, но мне не удалось найтивсе (здесь или в Google), которое дает инструкции или даже заявляет, что это может быть сделано.

1 Ответ

0 голосов
/ 18 февраля 2019

Это намного сложнее, чем должно быть, но вот как я это сделал.

Первый шаг - использовать этот 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 Service для записи информации о покрытии.т.е. напишите что-то подобное в консоль:

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

, где x - это процент покрытых блоков

Aполный список сообщений сервера можно найти здесь: пользовательский график

В итоге я использовал провайдера типа fSharp xml, чтобы проанализировать информацию о предоставлении информации для предоставления мне значения покрытия блока.

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 в каталоге проекта.Sample.xml может быть получен путем вызова метода getXml () в CoverageInfo и записи в файл.Крутая вещь в этом заключается в том, что я могу отфильтровать любой внешний код с помощью функции filterModules.

Я использую его, имея инструмент, который запускает этот код на Teamcity, связывая его как зависимость артефакта отпостроить меня волнует.Затем я запускаю модульные тесты, вызываю инструмент на созданном файле покрытия.Фу, это было легко, не так ли .......

...