public static CoverageResult GetCoverageResult(string filePath) { using (var result = new FileStream(filePath, FileMode.Open)) { CoveragePrepareResult coveragePrepareResultLoaded = CoveragePrepareResult.Deserialize(result); Coverage coverage = new Coverage(coveragePrepareResultLoaded, new Mock <ILogger>().Object); return(coverage.GetCoverageResult()); } }
public static CoverageResult GetCoverageResult(string filePath) { SetTestContainer(); using var result = new FileStream(filePath, FileMode.Open); var logger = new Mock <ILogger>(); logger.Setup(l => l.LogVerbose(It.IsAny <string>())).Callback((string message) => { Assert.DoesNotContain("not found for module: ", message); }); _processWideContainer.GetRequiredService <IInstrumentationHelper>().SetLogger(logger.Object); CoveragePrepareResult coveragePrepareResultLoaded = CoveragePrepareResult.Deserialize(result); Coverage coverage = new Coverage(coveragePrepareResultLoaded, logger.Object, _processWideContainer.GetService <IInstrumentationHelper>(), new FileSystem(), new SourceRootTranslator(new Mock <ILogger>().Object, new FileSystem())); return(coverage.GetCoverageResult()); }
public override bool Execute() { try { Console.WriteLine("\nCalculating coverage result..."); if (InstrumenterState is null || !File.Exists(InstrumenterState.ItemSpec)) { _logger.LogError("Result of instrumentation task not found"); return(false); } var coverage = new Coverage(CoveragePrepareResult.Deserialize(new FileStream(InstrumenterState.ItemSpec, FileMode.Open)), this._logger); var result = coverage.GetCoverageResult(); var directory = Path.GetDirectoryName(_output); if (directory == string.Empty) { directory = Directory.GetCurrentDirectory(); } else if (!Directory.Exists(directory)) { Directory.CreateDirectory(directory); } var formats = _format.Split(','); foreach (var format in formats) { var reporter = new ReporterFactory(format).CreateReporter(); if (reporter == null) { throw new Exception($"Specified output format '{format}' is not supported"); } if (reporter.OutputType == ReporterOutputType.Console) { // Output to console Console.WriteLine(" Outputting results to console"); Console.WriteLine(reporter.Report(result)); } else { // Output to file var filename = Path.GetFileName(_output); filename = (filename == string.Empty) ? $"coverage.{reporter.Extension}" : filename; filename = Path.HasExtension(filename) ? filename : $"{filename}.{reporter.Extension}"; var report = Path.Combine(directory, filename); Console.WriteLine($" Generating report '{report}'"); File.WriteAllText(report, reporter.Report(result)); } } var thresholdTypeFlags = ThresholdTypeFlags.None; var thresholdStat = ThresholdStatistic.Minimum; foreach (var thresholdType in _thresholdType.Split(',').Select(t => t.Trim())) { if (thresholdType.Equals("line", StringComparison.OrdinalIgnoreCase)) { thresholdTypeFlags |= ThresholdTypeFlags.Line; } else if (thresholdType.Equals("branch", StringComparison.OrdinalIgnoreCase)) { thresholdTypeFlags |= ThresholdTypeFlags.Branch; } else if (thresholdType.Equals("method", StringComparison.OrdinalIgnoreCase)) { thresholdTypeFlags |= ThresholdTypeFlags.Method; } } if (_thresholdStat.Equals("average", StringComparison.OrdinalIgnoreCase)) { thresholdStat = ThresholdStatistic.Average; } else if (_thresholdStat.Equals("total", StringComparison.OrdinalIgnoreCase)) { thresholdStat = ThresholdStatistic.Total; } var coverageTable = new ConsoleTable("Module", "Line", "Branch", "Method"); var summary = new CoverageSummary(); int numModules = result.Modules.Count; var linePercentCalculation = summary.CalculateLineCoverage(result.Modules); var branchPercentCalculation = summary.CalculateBranchCoverage(result.Modules); var methodPercentCalculation = summary.CalculateMethodCoverage(result.Modules); var totalLinePercent = linePercentCalculation.Percent; var totalBranchPercent = branchPercentCalculation.Percent; var totalMethodPercent = methodPercentCalculation.Percent; var averageLinePercent = linePercentCalculation.AverageModulePercent; var averageBranchPercent = branchPercentCalculation.AverageModulePercent; var averageMethodPercent = methodPercentCalculation.AverageModulePercent; foreach (var module in result.Modules) { var linePercent = summary.CalculateLineCoverage(module.Value).Percent; var branchPercent = summary.CalculateBranchCoverage(module.Value).Percent; var methodPercent = summary.CalculateMethodCoverage(module.Value).Percent; coverageTable.AddRow(Path.GetFileNameWithoutExtension(module.Key), $"{linePercent}%", $"{branchPercent}%", $"{methodPercent}%"); } Console.WriteLine(); Console.WriteLine(coverageTable.ToStringAlternative()); coverageTable.Columns.Clear(); coverageTable.Rows.Clear(); coverageTable.AddColumn(new[] { "", "Line", "Branch", "Method" }); coverageTable.AddRow("Total", $"{totalLinePercent}%", $"{totalBranchPercent}%", $"{totalMethodPercent}%"); coverageTable.AddRow("Average", $"{averageLinePercent}%", $"{averageBranchPercent}%", $"{averageMethodPercent}%"); Console.WriteLine(coverageTable.ToStringAlternative()); thresholdTypeFlags = result.GetThresholdTypesBelowThreshold(summary, _threshold, thresholdTypeFlags, thresholdStat); if (thresholdTypeFlags != ThresholdTypeFlags.None) { var exceptionMessageBuilder = new StringBuilder(); if ((thresholdTypeFlags & ThresholdTypeFlags.Line) != ThresholdTypeFlags.None) { exceptionMessageBuilder.AppendLine($"The {thresholdStat.ToString().ToLower()} line coverage is below the specified {_threshold}"); } if ((thresholdTypeFlags & ThresholdTypeFlags.Branch) != ThresholdTypeFlags.None) { exceptionMessageBuilder.AppendLine($"The {thresholdStat.ToString().ToLower()} branch coverage is below the specified {_threshold}"); } if ((thresholdTypeFlags & ThresholdTypeFlags.Method) != ThresholdTypeFlags.None) { exceptionMessageBuilder.AppendLine($"The {thresholdStat.ToString().ToLower()} method coverage is below the specified {_threshold}"); } throw new Exception(exceptionMessageBuilder.ToString()); } } catch (Exception ex) { _logger.LogError(ex); return(false); } return(true); }
public void CoveragePrepareResult_SerializationRoundTrip() { CoveragePrepareResult cpr = new CoveragePrepareResult(); cpr.Identifier = "Identifier"; cpr.MergeWith = "MergeWith"; cpr.ModuleOrDirectory = "Module"; cpr.UseSourceLink = true; InstrumenterResult ir = new InstrumenterResult(); ir.HitsFilePath = "HitsFilePath"; ir.Module = "Module"; ir.ModulePath = "ModulePath"; ir.SourceLink = "SourceLink"; ir.HitCandidates.Add(new HitCandidate(true, 1, 2, 3)); ir.HitCandidates.Add(new HitCandidate(false, 4, 5, 6)); var doc = new Document() { Index = 0, Path = "Path0" }; doc.Lines.Add(0, new Line() { Class = "Class0", Hits = 0, Method = "Method0", Number = 0 }); doc.Branches.Add(new BranchKey(0, 0), new Branch() { Class = "Class0", EndOffset = 0, Hits = 0, Method = "Method", Number = 0, Offset = 0, Ordinal = 0, Path = 0 }); var doc2 = new Document() { Index = 1, Path = "Path1" }; doc2.Lines.Add(1, new Line() { Class = "Class1", Hits = 1, Method = "Method1", Number = 1 }); doc2.Branches.Add(new BranchKey(1, 1), new Branch() { Class = "Class1", EndOffset = 1, Hits = 1, Method = "Method1", Number = 1, Offset = 1, Ordinal = 1, Path = 1 }); ir.Documents.Add("key", doc); ir.Documents.Add("key2", doc2); cpr.Results = new InstrumenterResult[] { ir }; CoveragePrepareResult roundTrip = CoveragePrepareResult.Deserialize(CoveragePrepareResult.Serialize(cpr)); Assert.Equal(cpr.Identifier, roundTrip.Identifier); Assert.Equal(cpr.MergeWith, roundTrip.MergeWith); Assert.Equal(cpr.ModuleOrDirectory, roundTrip.ModuleOrDirectory); Assert.Equal(cpr.UseSourceLink, roundTrip.UseSourceLink); for (int i = 0; i < cpr.Results.Length; i++) { Assert.Equal(cpr.Results[i].HitsFilePath, roundTrip.Results[i].HitsFilePath); Assert.Equal(cpr.Results[i].Module, roundTrip.Results[i].Module); Assert.Equal(cpr.Results[i].ModulePath, roundTrip.Results[i].ModulePath); Assert.Equal(cpr.Results[i].SourceLink, roundTrip.Results[i].SourceLink); for (int k = 0; k < cpr.Results[i].HitCandidates.Count; k++) { Assert.Equal(cpr.Results[i].HitCandidates[k].start, roundTrip.Results[i].HitCandidates[k].start); Assert.Equal(cpr.Results[i].HitCandidates[k].isBranch, roundTrip.Results[i].HitCandidates[k].isBranch); Assert.Equal(cpr.Results[i].HitCandidates[k].end, roundTrip.Results[i].HitCandidates[k].end); Assert.Equal(cpr.Results[i].HitCandidates[k].docIndex, roundTrip.Results[i].HitCandidates[k].docIndex); } for (int k = 0; k < cpr.Results[i].Documents.Count; k++) { var documents = cpr.Results[i].Documents.ToArray(); var documentsRoundTrip = roundTrip.Results[i].Documents.ToArray(); for (int j = 0; j < documents.Length; j++) { Assert.Equal(documents[j].Key, documentsRoundTrip[j].Key); Assert.Equal(documents[j].Value.Index, documentsRoundTrip[j].Value.Index); Assert.Equal(documents[j].Value.Path, documentsRoundTrip[j].Value.Path); for (int v = 0; v < documents[j].Value.Lines.Count; v++) { var lines = documents[j].Value.Lines.ToArray(); var linesRoundTrip = documentsRoundTrip[j].Value.Lines.ToArray(); Assert.Equal(lines[v].Key, linesRoundTrip[v].Key); Assert.Equal(lines[v].Value.Class, lines[v].Value.Class); Assert.Equal(lines[v].Value.Hits, lines[v].Value.Hits); Assert.Equal(lines[v].Value.Method, lines[v].Value.Method); Assert.Equal(lines[v].Value.Number, lines[v].Value.Number); } for (int v = 0; v < documents[j].Value.Branches.Count; v++) { var branches = documents[j].Value.Branches.ToArray(); var branchesRoundTrip = documentsRoundTrip[j].Value.Branches.ToArray(); Assert.Equal(branches[v].Key, branchesRoundTrip[v].Key); Assert.Equal(branches[v].Value.Class, branchesRoundTrip[v].Value.Class); Assert.Equal(branches[v].Value.EndOffset, branchesRoundTrip[v].Value.EndOffset); Assert.Equal(branches[v].Value.Hits, branchesRoundTrip[v].Value.Hits); Assert.Equal(branches[v].Value.Method, branchesRoundTrip[v].Value.Method); Assert.Equal(branches[v].Value.Number, branchesRoundTrip[v].Value.Number); Assert.Equal(branches[v].Value.Offset, branchesRoundTrip[v].Value.Offset); Assert.Equal(branches[v].Value.Ordinal, branchesRoundTrip[v].Value.Ordinal); Assert.Equal(branches[v].Value.Path, branchesRoundTrip[v].Value.Path); } } } } }
public override bool Execute() { try { Console.WriteLine("\nCalculating coverage result..."); IFileSystem fileSystem = ServiceProvider.GetService <IFileSystem>(); if (InstrumenterState is null || !fileSystem.Exists(InstrumenterState.ItemSpec)) { _logger.LogError("Result of instrumentation task not found"); return(false); } Coverage coverage = null; using (Stream instrumenterStateStream = fileSystem.NewFileStream(InstrumenterState.ItemSpec, FileMode.Open)) { IInstrumentationHelper instrumentationHelper = ServiceProvider.GetService <IInstrumentationHelper>(); // Task.Log is teared down after a task and thus the new MSBuildLogger must be passed to the InstrumentationHelper // https://github.com/microsoft/msbuild/issues/5153 instrumentationHelper.SetLogger(_logger); coverage = new Coverage(CoveragePrepareResult.Deserialize(instrumenterStateStream), _logger, ServiceProvider.GetService <IInstrumentationHelper>(), fileSystem, ServiceProvider.GetService <ISourceRootTranslator>()); } try { fileSystem.Delete(InstrumenterState.ItemSpec); } catch (Exception ex) { // We don't want to block coverage for I/O errors _logger.LogWarning($"Exception during instrument state deletion, file name '{InstrumenterState.ItemSpec}' exception message '{ex.Message}'"); } CoverageResult result = coverage.GetCoverageResult(); string directory = Path.GetDirectoryName(Output); if (directory == string.Empty) { directory = Directory.GetCurrentDirectory(); } else if (!Directory.Exists(directory)) { Directory.CreateDirectory(directory); } string[] formats = OutputFormat.Split(','); var coverageReportPaths = new List <ITaskItem>(formats.Length); ISourceRootTranslator sourceRootTranslator = ServiceProvider.GetService <ISourceRootTranslator>(); foreach (string format in formats) { IReporter reporter = new ReporterFactory(format).CreateReporter(); if (reporter == null) { throw new Exception($"Specified output format '{format}' is not supported"); } if (reporter.OutputType == ReporterOutputType.Console) { // Output to console Console.WriteLine(" Outputting results to console"); Console.WriteLine(reporter.Report(result, sourceRootTranslator)); } else { ReportWriter writer = new(CoverletMultiTargetFrameworksCurrentTFM, directory, Output, reporter, fileSystem, ServiceProvider.GetService <IConsole>(), result, sourceRootTranslator); string path = writer.WriteReport(); var metadata = new Dictionary <string, string> { ["Format"] = format }; coverageReportPaths.Add(new TaskItem(path, metadata)); } } ReportItems = coverageReportPaths.ToArray(); var thresholdTypeFlagQueue = new Queue <ThresholdTypeFlags>(); foreach (string thresholdType in ThresholdType.Split(',').Select(t => t.Trim())) { if (thresholdType.Equals("line", StringComparison.OrdinalIgnoreCase)) { thresholdTypeFlagQueue.Enqueue(ThresholdTypeFlags.Line); } else if (thresholdType.Equals("branch", StringComparison.OrdinalIgnoreCase)) { thresholdTypeFlagQueue.Enqueue(ThresholdTypeFlags.Branch); } else if (thresholdType.Equals("method", StringComparison.OrdinalIgnoreCase)) { thresholdTypeFlagQueue.Enqueue(ThresholdTypeFlags.Method); } } var thresholdTypeFlagValues = new Dictionary <ThresholdTypeFlags, double>(); if (Threshold.Contains(',')) { IEnumerable <string> thresholdValues = Threshold.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(t => t.Trim()); if (thresholdValues.Count() != thresholdTypeFlagQueue.Count) { throw new Exception($"Threshold type flag count ({thresholdTypeFlagQueue.Count}) and values count ({thresholdValues.Count()}) doesn't match"); } foreach (string threshold in thresholdValues) { if (double.TryParse(threshold, out double value)) { thresholdTypeFlagValues[thresholdTypeFlagQueue.Dequeue()] = value; } else { throw new Exception($"Invalid threshold value must be numeric"); } } } else { double thresholdValue = double.Parse(Threshold); while (thresholdTypeFlagQueue.Any()) { thresholdTypeFlagValues[thresholdTypeFlagQueue.Dequeue()] = thresholdValue; } } ThresholdStatistic thresholdStat = ThresholdStatistic.Minimum; if (ThresholdStat.Equals("average", StringComparison.OrdinalIgnoreCase)) { thresholdStat = ThresholdStatistic.Average; } else if (ThresholdStat.Equals("total", StringComparison.OrdinalIgnoreCase)) { thresholdStat = ThresholdStatistic.Total; } var coverageTable = new ConsoleTable("Module", "Line", "Branch", "Method"); var summary = new CoverageSummary(); CoverageDetails linePercentCalculation = summary.CalculateLineCoverage(result.Modules); CoverageDetails branchPercentCalculation = summary.CalculateBranchCoverage(result.Modules); CoverageDetails methodPercentCalculation = summary.CalculateMethodCoverage(result.Modules); double totalLinePercent = linePercentCalculation.Percent; double totalBranchPercent = branchPercentCalculation.Percent; double totalMethodPercent = methodPercentCalculation.Percent; double averageLinePercent = linePercentCalculation.AverageModulePercent; double averageBranchPercent = branchPercentCalculation.AverageModulePercent; double averageMethodPercent = methodPercentCalculation.AverageModulePercent; foreach (KeyValuePair <string, Documents> module in result.Modules) { double linePercent = summary.CalculateLineCoverage(module.Value).Percent; double branchPercent = summary.CalculateBranchCoverage(module.Value).Percent; double methodPercent = summary.CalculateMethodCoverage(module.Value).Percent; coverageTable.AddRow(Path.GetFileNameWithoutExtension(module.Key), $"{InvariantFormat(linePercent)}%", $"{InvariantFormat(branchPercent)}%", $"{InvariantFormat(methodPercent)}%"); } Console.WriteLine(); Console.WriteLine(coverageTable.ToStringAlternative()); coverageTable.Columns.Clear(); coverageTable.Rows.Clear(); coverageTable.AddColumn(new[] { "", "Line", "Branch", "Method" }); coverageTable.AddRow("Total", $"{InvariantFormat(totalLinePercent)}%", $"{InvariantFormat(totalBranchPercent)}%", $"{InvariantFormat(totalMethodPercent)}%"); coverageTable.AddRow("Average", $"{InvariantFormat(averageLinePercent)}%", $"{InvariantFormat(averageBranchPercent)}%", $"{InvariantFormat(averageMethodPercent)}%"); Console.WriteLine(coverageTable.ToStringAlternative()); ThresholdTypeFlags thresholdTypeFlags = result.GetThresholdTypesBelowThreshold(summary, thresholdTypeFlagValues, thresholdStat); if (thresholdTypeFlags != ThresholdTypeFlags.None) { var exceptionMessageBuilder = new StringBuilder(); if ((thresholdTypeFlags & ThresholdTypeFlags.Line) != ThresholdTypeFlags.None) { exceptionMessageBuilder.AppendLine( $"The {thresholdStat.ToString().ToLower()} line coverage is below the specified {thresholdTypeFlagValues[ThresholdTypeFlags.Line]}"); } if ((thresholdTypeFlags & ThresholdTypeFlags.Branch) != ThresholdTypeFlags.None) { exceptionMessageBuilder.AppendLine( $"The {thresholdStat.ToString().ToLower()} branch coverage is below the specified {thresholdTypeFlagValues[ThresholdTypeFlags.Branch]}"); } if ((thresholdTypeFlags & ThresholdTypeFlags.Method) != ThresholdTypeFlags.None) { exceptionMessageBuilder.AppendLine( $"The {thresholdStat.ToString().ToLower()} method coverage is below the specified {thresholdTypeFlagValues[ThresholdTypeFlags.Method]}"); } throw new Exception(exceptionMessageBuilder.ToString()); } } catch (Exception ex) { _logger.LogError(ex); return(false); } return(true); }
public override bool Execute() { try { Console.WriteLine("\nCalculating coverage result..."); IFileSystem fileSystem = ServiceProvider.GetService <IFileSystem>(); if (InstrumenterState is null || !fileSystem.Exists(InstrumenterState.ItemSpec)) { _logger.LogError("Result of instrumentation task not found"); return(false); } Coverage coverage = null; using (Stream instrumenterStateStream = fileSystem.NewFileStream(InstrumenterState.ItemSpec, FileMode.Open)) { var instrumentationHelper = ServiceProvider.GetService <IInstrumentationHelper>(); // Task.Log is teared down after a task and thus the new MSBuildLogger must be passed to the InstrumentationHelper // https://github.com/microsoft/msbuild/issues/5153 instrumentationHelper.SetLogger(_logger); coverage = new Coverage(CoveragePrepareResult.Deserialize(instrumenterStateStream), this._logger, ServiceProvider.GetService <IInstrumentationHelper>(), fileSystem, ServiceProvider.GetService <ISourceRootTranslator>()); } try { fileSystem.Delete(InstrumenterState.ItemSpec); } catch (Exception ex) { // We don't want to block coverage for I/O errors _logger.LogWarning($"Exception during instrument state deletion, file name '{InstrumenterState.ItemSpec}' exception message '{ex.Message}'"); } CoverageResult result = coverage.GetCoverageResult(); var directory = Path.GetDirectoryName(_output); if (directory == string.Empty) { directory = Directory.GetCurrentDirectory(); } else if (!Directory.Exists(directory)) { Directory.CreateDirectory(directory); } var formats = _format.Split(','); foreach (var format in formats) { var reporter = new ReporterFactory(format).CreateReporter(); if (reporter == null) { throw new Exception($"Specified output format '{format}' is not supported"); } if (reporter.OutputType == ReporterOutputType.Console) { // Output to console Console.WriteLine(" Outputting results to console"); Console.WriteLine(reporter.Report(result)); } else { ReportWriter writer = new ReportWriter(_coverletMultiTargetFrameworksCurrentTFM, directory, _output, reporter, fileSystem, ServiceProvider.GetService <IConsole>(), result); writer.WriteReport(); } } var thresholdTypeFlags = ThresholdTypeFlags.None; var thresholdStat = ThresholdStatistic.Minimum; foreach (var thresholdType in _thresholdType.Split(',').Select(t => t.Trim())) { if (thresholdType.Equals("line", StringComparison.OrdinalIgnoreCase)) { thresholdTypeFlags |= ThresholdTypeFlags.Line; } else if (thresholdType.Equals("branch", StringComparison.OrdinalIgnoreCase)) { thresholdTypeFlags |= ThresholdTypeFlags.Branch; } else if (thresholdType.Equals("method", StringComparison.OrdinalIgnoreCase)) { thresholdTypeFlags |= ThresholdTypeFlags.Method; } } if (_thresholdStat.Equals("average", StringComparison.OrdinalIgnoreCase)) { thresholdStat = ThresholdStatistic.Average; } else if (_thresholdStat.Equals("total", StringComparison.OrdinalIgnoreCase)) { thresholdStat = ThresholdStatistic.Total; } var coverageTable = new ConsoleTable("Module", "Line", "Branch", "Method"); var summary = new CoverageSummary(); int numModules = result.Modules.Count; var linePercentCalculation = summary.CalculateLineCoverage(result.Modules); var branchPercentCalculation = summary.CalculateBranchCoverage(result.Modules); var methodPercentCalculation = summary.CalculateMethodCoverage(result.Modules); var totalLinePercent = linePercentCalculation.Percent; var totalBranchPercent = branchPercentCalculation.Percent; var totalMethodPercent = methodPercentCalculation.Percent; var averageLinePercent = linePercentCalculation.AverageModulePercent; var averageBranchPercent = branchPercentCalculation.AverageModulePercent; var averageMethodPercent = methodPercentCalculation.AverageModulePercent; foreach (var module in result.Modules) { var linePercent = summary.CalculateLineCoverage(module.Value).Percent; var branchPercent = summary.CalculateBranchCoverage(module.Value).Percent; var methodPercent = summary.CalculateMethodCoverage(module.Value).Percent; coverageTable.AddRow(Path.GetFileNameWithoutExtension(module.Key), $"{linePercent}%", $"{branchPercent}%", $"{methodPercent}%"); } Console.WriteLine(); Console.WriteLine(coverageTable.ToStringAlternative()); coverageTable.Columns.Clear(); coverageTable.Rows.Clear(); coverageTable.AddColumn(new[] { "", "Line", "Branch", "Method" }); coverageTable.AddRow("Total", $"{totalLinePercent}%", $"{totalBranchPercent}%", $"{totalMethodPercent}%"); coverageTable.AddRow("Average", $"{averageLinePercent}%", $"{averageBranchPercent}%", $"{averageMethodPercent}%"); Console.WriteLine(coverageTable.ToStringAlternative()); thresholdTypeFlags = result.GetThresholdTypesBelowThreshold(summary, _threshold, thresholdTypeFlags, thresholdStat); if (thresholdTypeFlags != ThresholdTypeFlags.None) { var exceptionMessageBuilder = new StringBuilder(); if ((thresholdTypeFlags & ThresholdTypeFlags.Line) != ThresholdTypeFlags.None) { exceptionMessageBuilder.AppendLine($"The {thresholdStat.ToString().ToLower()} line coverage is below the specified {_threshold}"); } if ((thresholdTypeFlags & ThresholdTypeFlags.Branch) != ThresholdTypeFlags.None) { exceptionMessageBuilder.AppendLine($"The {thresholdStat.ToString().ToLower()} branch coverage is below the specified {_threshold}"); } if ((thresholdTypeFlags & ThresholdTypeFlags.Method) != ThresholdTypeFlags.None) { exceptionMessageBuilder.AppendLine($"The {thresholdStat.ToString().ToLower()} method coverage is below the specified {_threshold}"); } throw new Exception(exceptionMessageBuilder.ToString()); } } catch (Exception ex) { _logger.LogError(ex); return(false); } return(true); }