Это намного сложнее, чем должно быть, но вот как я это сделал.
Первый шаг - использовать этот 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, связывая его как зависимость артефакта отпостроить меня волнует.Затем я запускаю модульные тесты, вызываю инструмент на созданном файле покрытия.Фу, это было легко, не так ли .......