public void WillPublishCoverageSummaryToTfs()
        {
            var summary = new CoverageSummary("flavor", "platform");

            summary.AddCoverageStatistics("lines", 10, 5, CoverageSummary.Priority.Line);
            summary.AddCoverageStatistics("blocks", 10, 5, CoverageSummary.Priority.Other);

            var token      = new CancellationToken();
            var publisher  = new AzurePipelinesPublisher(_context, _mockClientFactory.Object, _mockFFHelper.Object, _mockHtmlPublisher.Object, _mockLogStoreHelper.Object, true);
            var mockClient = new Mock <TestManagementHttpClient>(new Uri("http://localhost"), new VssCredentials());

            _mockClientFactory.Setup(x => x.GetClient <TestManagementHttpClient>()).Returns(mockClient.Object);
            _mockFFHelper.Setup(x => x.GetFeatureFlagState(
                                    It.Is <string>(a => a == Constants.FeatureFlags.EnablePublishToTcmServiceDirectlyFromTaskFF),
                                    It.Is <bool>(b => b == false))).Returns(false);

            publisher.PublishCoverageSummary(summary, token).Wait();

            mockClient.Verify(x => x.UpdateCodeCoverageSummaryAsync(
                                  It.Is <CodeCoverageData>(a => a == summary.CodeCoverageData),
                                  It.Is <Guid>(b => b == _context.ProjectId),
                                  It.Is <int>(c => c == _context.BuildId),
                                  It.IsAny <object>(),
                                  It.Is <CancellationToken>(d => d == token)));
        }
Example #2
0
        public CoverageSummary GetCoverageSummary()
        {
            TraceLogger.Debug("ReportGeneratorTool.GetCoverageSummary: Generating coverage summary for the coverage files.");

            var summary = new CoverageSummary();

            if (Configuration.CoverageFiles == null)
            {
                return(summary);
            }

            int totalLines   = 0;
            int coveredLines = 0;

            foreach (var assembly in _parserResult.Assemblies)
            {
                foreach (var @class in assembly.Classes)
                {
                    foreach (var file in @class.Files)
                    {
                        totalLines   += file.CoverableLines;
                        coveredLines += file.CoveredLines;
                    }
                }
            }

            summary.AddCoverageStatistics("line", totalLines, coveredLines, CoverageSummary.Priority.Line);

            return(summary);
        }
        public void TestCalculateSummary()
        {
            CoverageResult result = new CoverageResult();

            result.Identifier = Guid.NewGuid().ToString();
            Lines lines = new Lines();

            lines.Add(1, 1);
            lines.Add(2, 0);
            Methods methods = new Methods();

            methods.Add("System.Void Coverlet.Core.Tests.CoverageSummaryTests.TestCalculateSummary()", lines);
            Classes classes = new Classes();

            classes.Add("Coverlet.Core.Tests.CoverageSummaryTests", methods);
            Documents documents = new Documents();

            documents.Add("doc.cs", classes);
            result.Modules = new Modules();
            result.Modules.Add("module", documents);

            CoverageSummary       summary       = new CoverageSummary(result);
            CoverageSummaryResult summaryResult = summary.CalculateSummary();

            Assert.NotEmpty(summaryResult);
            Assert.True(summaryResult.ContainsKey("module"));
            Assert.Equal(50, summaryResult["module"]);
        }
Example #4
0
        public string Report(CoverageResult result, ISourceRootTranslator sourceRootTranslator)
        {
            if (result.Parameters.DeterministicReport)
            {
                throw new NotSupportedException("Deterministic report not supported by lcov reporter");
            }

            CoverageSummary summary = new CoverageSummary();
            List <string>   lcov    = new List <string>();

            foreach (var module in result.Modules)
            {
                foreach (var doc in module.Value)
                {
                    var docLineCoverage   = summary.CalculateLineCoverage(doc.Value);
                    var docBranchCoverage = summary.CalculateBranchCoverage(doc.Value);
                    var docMethodCoverage = summary.CalculateMethodCoverage(doc.Value);

                    lcov.Add("SF:" + doc.Key);
                    foreach (var @class in doc.Value)
                    {
                        foreach (var method in @class.Value)
                        {
                            // Skip all methods with no lines
                            if (method.Value.Lines.Count == 0)
                            {
                                continue;
                            }

                            lcov.Add($"FN:{method.Value.Lines.First().Key - 1},{method.Key}");
                            lcov.Add($"FNDA:{method.Value.Lines.First().Value},{method.Key}");

                            foreach (var line in method.Value.Lines)
                            {
                                lcov.Add($"DA:{line.Key},{line.Value}");
                            }

                            foreach (var branch in method.Value.Branches)
                            {
                                lcov.Add($"BRDA:{branch.Line},{branch.Offset},{branch.Path},{branch.Hits}");
                            }
                        }
                    }

                    lcov.Add($"LF:{docLineCoverage.Total}");
                    lcov.Add($"LH:{docLineCoverage.Covered}");

                    lcov.Add($"BRF:{docBranchCoverage.Total}");
                    lcov.Add($"BRH:{docBranchCoverage.Covered}");

                    lcov.Add($"FNF:{docMethodCoverage.Total}");
                    lcov.Add($"FNH:{docMethodCoverage.Covered}");

                    lcov.Add("end_of_record");
                }
            }

            return(string.Join(Environment.NewLine, lcov));
        }
Example #5
0
        public string Report(CoverageResult result)
        {
            CoverageSummary summary = new CoverageSummary();
            List <string>   lcov    = new List <string>();

            foreach (var module in result.Modules)
            {
                foreach (var doc in module.Value)
                {
                    var docLineCoverage   = summary.CalculateLineCoverage(doc.Value);
                    var docBranchCoverage = summary.CalculateBranchCoverage(doc.Value);
                    var docMethodCoverage = summary.CalculateMethodCoverage(doc.Value);

                    lcov.Add("SF:" + doc.Key);
                    foreach (var @class in doc.Value)
                    {
                        foreach (var method in @class.Value)
                        {
                            // Skip all methods with no lines
                            if (method.Value.Lines.Count == 0)
                            {
                                continue;
                            }

                            lcov.Add($"FN:{method.Value.Lines.First().Key - 1},{method.Key}");
                            lcov.Add($"FNDA:{method.Value.Lines.First().Value.Hits},{method.Key}");

                            foreach (var line in method.Value.Lines)
                            {
                                lcov.Add($"DA:{line.Key},{line.Value.Hits}");
                            }

                            foreach (var branchs in method.Value.Branches)
                            {
                                foreach (var branch in branchs.Value)
                                {
                                    lcov.Add($"BRDA:{branchs.Key},{branch.Offset},{branch.Path},{branch.Hits}");
                                }
                            }
                        }
                    }

                    lcov.Add($"LF:{docLineCoverage.Total}");
                    lcov.Add($"LH:{docLineCoverage.Covered}");

                    lcov.Add($"BRF:{docBranchCoverage.Total}");
                    lcov.Add($"BRH:{docBranchCoverage.Covered}");

                    lcov.Add($"FNF:{docMethodCoverage.Total}");
                    lcov.Add($"FNH:{docMethodCoverage.Covered}");

                    lcov.Add("end_of_record");
                }
            }

            return(string.Join(Environment.NewLine, lcov));
        }
Example #6
0
        public void TestCalculateBranchCoverage_MultiModule()
        {
            var       summary = new CoverageSummary();
            Documents documentsFirstModule  = _averageCalculationMultiModule["module"];
            Documents documentsSecondModule = _averageCalculationMultiModule["aditionalModule"];

            Assert.Equal(83.33, summary.CalculateBranchCoverage(_averageCalculationMultiModule).AverageModulePercent);
            Assert.Equal(100, summary.CalculateBranchCoverage(documentsFirstModule.First().Value).Percent);
            Assert.Equal(66.66, summary.CalculateBranchCoverage(documentsSecondModule.First().Value).Percent);
        }
        public void TestCalculateMethodCoverage_MultiModule()
        {
            CoverageSummary summary = new CoverageSummary();
            var             documentsFirstModule  = _averageCalculationMultiModule["module"];
            var             documentsSecondModule = _averageCalculationMultiModule["aditionalModule"];

            Assert.Equal(75, summary.CalculateMethodCoverage(_averageCalculationMultiModule).AverageModulePercent);
            Assert.Equal(100, summary.CalculateMethodCoverage(documentsFirstModule.First().Value).Percent);
            Assert.Equal(50, summary.CalculateMethodCoverage(documentsSecondModule.First().Value).Percent);
        }
Example #8
0
        public override bool Execute()
        {
            try
            {
                Console.WriteLine("\nCalculating coverage result...");
                var            coverage = InstrumentationTask.Coverage;
                CoverageResult result   = coverage.GetCoverageResult();

                var directory = Path.GetDirectoryName(_filename);
                if (!Directory.Exists(directory))
                {
                    Directory.CreateDirectory(directory);
                }

                Console.WriteLine($"  Generating report '{_filename}'");

                IReporter reporter = default(IReporter);
                switch (_format)
                {
                case "lcov":
                    reporter = new LcovReporter();
                    break;

                case "opencover":
                    reporter = new OpenCoverReporter();
                    break;

                default:
                    reporter = new JsonReporter();
                    break;
                }

                File.WriteAllText(_filename, result.Format(reporter));

                CoverageSummary coverageSummary = new CoverageSummary(result);
                var             summary         = coverageSummary.CalculateSummary();

                ConsoleTable table = new ConsoleTable("Module", "Coverage");
                foreach (var item in summary)
                {
                    table.AddRow(item.Key, $"{item.Value}%");
                }

                Console.WriteLine();
                table.Write(Format.Alternative);
            }
            catch (Exception ex)
            {
                Log.LogErrorFromException(ex);
                return(false);
            }

            return(true);
        }
        public void TestCalculateLineCoverage_NoModules()
        {
            CoverageSummary summary = new CoverageSummary();
            var             modules = new Modules();

            Assert.Equal(0, summary.CalculateLineCoverage(modules).Percent);
            Assert.Equal(0, summary.CalculateLineCoverage(modules).AverageModulePercent);
            Assert.Equal(0, summary.CalculateBranchCoverage(modules).Percent);
            Assert.Equal(0, summary.CalculateBranchCoverage(modules).AverageModulePercent);
            Assert.Equal(0, summary.CalculateMethodCoverage(modules).Percent);
            Assert.Equal(0, summary.CalculateMethodCoverage(modules).AverageModulePercent);
        }
Example #10
0
        public override bool Execute()
        {
            try
            {
                Console.WriteLine("\nCalculating coverage result...");
                var            coverage = InstrumentationTask.Coverage;
                CoverageResult result   = coverage.GetCoverageResult();

                var directory = Path.GetDirectoryName(_filename);
                if (!Directory.Exists(directory))
                {
                    Directory.CreateDirectory(directory);
                }

                IReporter reporter = new ReporterFactory(_format).CreateReporter();
                if (reporter == null)
                {
                    throw new Exception($"Specified output format '{_format}' is not supported");
                }

                _filename = _filename + "." + reporter.Extension;
                Console.WriteLine($"  Generating report '{_filename}'");
                File.WriteAllText(_filename, reporter.Report(result));

                double          total   = 0;
                CoverageSummary summary = new CoverageSummary();
                ConsoleTable    table   = new ConsoleTable("Module", "Coverage");

                foreach (var module in result.Modules)
                {
                    double percent = summary.CalculateLineCoverage(module.Value) * 100;
                    table.AddRow(System.IO.Path.GetFileNameWithoutExtension(module.Key), $"{percent}%");
                    total += percent;
                }

                Console.WriteLine();
                Console.WriteLine(table.ToMarkDownString());

                double average = total / result.Modules.Count;
                if (average < _threshold)
                {
                    return(false);
                }
            }
            catch (Exception ex)
            {
                Log.LogErrorFromException(ex);
                return(false);
            }

            return(true);
        }
        public void TestCalculateLineCoverage_MultiModule()
        {
            CoverageSummary summary = new CoverageSummary();
            var             documentsFirstModule  = _averageCalculationMultiModule["module"];
            var             documentsSecondModule = _averageCalculationMultiModule["aditionalModule"];

            Assert.Equal(37.5, summary.CalculateLineCoverage(_averageCalculationMultiModule).AverageModulePercent);
            Assert.Equal(50, summary.CalculateLineCoverage(documentsFirstModule.First().Value).Percent);

            Assert.Equal(33.33, summary.CalculateLineCoverage(documentsSecondModule.First().Value.First().Value.ElementAt(0).Value.Lines).Percent); // covered 1 of 3
            Assert.Equal(0, summary.CalculateLineCoverage(documentsSecondModule.First().Value.First().Value.ElementAt(1).Value.Lines).Percent);     // covered 0 of 1
            Assert.Equal(25, summary.CalculateLineCoverage(documentsSecondModule.First().Value).Percent);                                           // covered 1 of 4 lines
        }
        public void TestCalculateMethodCoverage()
        {
            CoverageSummary summary = new CoverageSummary();

            var module   = _modules.First();
            var document = module.Value.First();
            var @class   = document.Value.First();
            var method   = @class.Value.First();

            Assert.Equal(1, summary.CalculateMethodCoverage(module.Value).Percent);
            Assert.Equal(1, summary.CalculateMethodCoverage(document.Value).Percent);
            Assert.Equal(1, summary.CalculateMethodCoverage(@class.Value).Percent);
            Assert.Equal(1, summary.CalculateMethodCoverage(method.Value.Lines).Percent);
        }
Example #13
0
        public void TestCalculateBranchCoveragePercentage_ArithmeticPrecisionCheck()
        {
            CoverageSummary summary = new CoverageSummary();

            var module   = _moduleArithmeticPrecision.First();
            var document = module.Value.First();
            var @class   = document.Value.First();
            var method   = @class.Value.First();

            Assert.Equal(16.66, summary.CalculateBranchCoverage(module.Value).Percent);
            Assert.Equal(16.66, summary.CalculateBranchCoverage(document.Value).Percent);
            Assert.Equal(16.66, summary.CalculateBranchCoverage(@class.Value).Percent);
            Assert.Equal(16.66, summary.CalculateBranchCoverage(method.Value.Branches).Percent);
        }
        void SetModuleCoverage()
        {
            var modulesCoverage = new Dictionary <string, CoverageSummary>();
            var summary         = new CoverletCoverageSummary();

            foreach (var moduleInfo in result.Modules)
            {
                var moduleLineCoverage   = summary.CalculateLineCoverage(moduleInfo.Value);
                var moduleBranchCoverage = summary.CalculateBranchCoverage(moduleInfo.Value);
                var moduleName           = moduleInfo.Key.Replace(".dll", "");
                modulesCoverage[moduleName] = new CoverageSummary(moduleLineCoverage.Percent, moduleBranchCoverage.Percent);
            }

            ModuleCoverage = modulesCoverage;
        }
        public void TestCalculateMethodCoverage_SingleModule()
        {
            CoverageSummary summary = new CoverageSummary();

            var module   = _averageCalculationSingleModule.First();
            var document = module.Value.First();
            var @class   = document.Value.First();
            var method   = @class.Value.First();

            Assert.Equal(100, summary.CalculateMethodCoverage(_averageCalculationSingleModule).AverageModulePercent);
            Assert.Equal(100, summary.CalculateMethodCoverage(module.Value).Percent);
            Assert.Equal(100, summary.CalculateMethodCoverage(document.Value).Percent);
            Assert.Equal(100, summary.CalculateMethodCoverage(@class.Value).Percent);
            Assert.Equal(100, summary.CalculateMethodCoverage(method.Value.Lines).Percent);
        }
Example #16
0
        public void TestCalculateBranchCoveragePercentage_ArithmeticPrecisionCheck()
        {
            var summary = new CoverageSummary();

            System.Collections.Generic.KeyValuePair <string, Documents> module   = _moduleArithmeticPrecision.First();
            System.Collections.Generic.KeyValuePair <string, Classes>   document = module.Value.First();
            System.Collections.Generic.KeyValuePair <string, Methods>   @class   = document.Value.First();
            System.Collections.Generic.KeyValuePair <string, Method>    method   = @class.Value.First();

            Assert.Equal(16.66, summary.CalculateBranchCoverage(_moduleArithmeticPrecision).AverageModulePercent);
            Assert.Equal(16.66, summary.CalculateBranchCoverage(module.Value).Percent);
            Assert.Equal(16.66, summary.CalculateBranchCoverage(document.Value).Percent);
            Assert.Equal(16.66, summary.CalculateBranchCoverage(@class.Value).Percent);
            Assert.Equal(16.66, summary.CalculateBranchCoverage(method.Value.Branches).Percent);
        }
Example #17
0
        public void TestCalculateMethodCoverage_SingleModule()
        {
            var summary = new CoverageSummary();

            System.Collections.Generic.KeyValuePair <string, Documents> module   = _averageCalculationSingleModule.First();
            System.Collections.Generic.KeyValuePair <string, Classes>   document = module.Value.First();
            System.Collections.Generic.KeyValuePair <string, Methods>   @class   = document.Value.First();
            System.Collections.Generic.KeyValuePair <string, Method>    method   = @class.Value.First();

            Assert.Equal(100, summary.CalculateMethodCoverage(_averageCalculationSingleModule).AverageModulePercent);
            Assert.Equal(100, summary.CalculateMethodCoverage(module.Value).Percent);
            Assert.Equal(100, summary.CalculateMethodCoverage(document.Value).Percent);
            Assert.Equal(100, summary.CalculateMethodCoverage(@class.Value).Percent);
            Assert.Equal(100, summary.CalculateMethodCoverage(method.Value.Lines).Percent);
        }
        public void ParseAndPublishCoverageWillPublishSummary()
        {
            var token     = new CancellationToken();
            var processor = new CoverageProcessor(_mockPublisher.Object, _mockTelemetryDataCollector.Object);
            var summary   = new CoverageSummary();

            summary.AddCoverageStatistics("", 0, 0, CoverageSummary.Priority.Class);

            _mockPublisher.Setup(x => x.IsFileCoverageJsonSupported()).Returns(false);
            _mockParser.Setup(x => x.GetCoverageSummary()).Returns(summary);

            processor.ParseAndPublishCoverage(_config, token, _mockParser.Object).Wait();

            _mockPublisher.Verify(x => x.PublishCoverageSummary(
                                      It.Is <CoverageSummary>(a => a == summary),
                                      It.Is <CancellationToken>(b => b == token)));
        }
        public string Report(CoverageResult result)
        {
            // Calculate coverage
            var summary               = new CoverageSummary();
            var overallLineCoverage   = summary.CalculateLineCoverage(result.Modules);
            var overallBranchCoverage = summary.CalculateBranchCoverage(result.Modules);
            var overallMethodCoverage = summary.CalculateMethodCoverage(result.Modules);

            // Report coverage
            var stringBuilder = new StringBuilder();

            OutputLineCoverage(overallLineCoverage, stringBuilder);
            OutputBranchCoverage(overallBranchCoverage, stringBuilder);
            OutputMethodCoverage(overallMethodCoverage, stringBuilder);

            // Return a placeholder
            return(stringBuilder.ToString());
        }
Example #20
0
        public async Task PublishCoverageSummary(CoverageSummary coverageSummary, CancellationToken cancellationToken)
        {
            var coverageData  = coverageSummary.CodeCoverageData;
            var coverageStats = coverageData?.CoverageStats;

            if (coverageData != null && coverageStats != null && coverageStats.Count() > 0)
            {
                // log coverage stats
                TraceLogger.Info(Resources.PublishingCodeCoverageSummary);
                foreach (var coverage in coverageStats)
                {
                    TraceLogger.Info(string.Format(Resources.CoveredStats, coverage.Label, coverage.Covered, coverage.Total));
                }

                try
                {
                    var uploadToTcm = _featureFlagHelper.GetFeatureFlagState(Constants.FeatureFlags.EnablePublishToTcmServiceDirectlyFromTaskFF, false);
                    _executionContext.TelemetryDataCollector.AddOrUpdate("UploadToTcm", uploadToTcm.ToString());

                    // Upload to tcm/tfs based on feature flag
                    if (uploadToTcm)
                    {
                        TestResultsHttpClient tcmClient = _clientFactory.GetClient <TestResultsHttpClient>();
                        using (new SimpleTimer("AzurePipelinesPublisher", "UploadSummary", _executionContext.TelemetryDataCollector))
                        {
                            await tcmClient.UpdateCodeCoverageSummaryAsync(coverageData, _executionContext.ProjectId, _executionContext.BuildId, cancellationToken : cancellationToken);
                        }
                    }
                    else
                    {
                        TestManagementHttpClient tfsClient = _clientFactory.GetClient <TestManagementHttpClient>();
                        using (new SimpleTimer("AzurePipelinesPublisher", "UploadSummary", _executionContext.TelemetryDataCollector))
                        {
                            await tfsClient.UpdateCodeCoverageSummaryAsync(coverageData, _executionContext.ProjectId, _executionContext.BuildId, cancellationToken : cancellationToken);
                        }
                    }
                }
                catch (Exception ex)
                {
                    TraceLogger.Error(string.Format(Resources.FailedtoUploadCoverageSummary, ex.ToString()));
                }
            }
        }
Example #21
0
        public void TestGetThresholdTypesBelowThresholdAllGood()
        {
            var result = new CoverageResult();

            result.Modules = _modules;

            var summary = new CoverageSummary();
            var thresholdTypeFlagValues = new Dictionary <ThresholdTypeFlags, double>()
            {
                { ThresholdTypeFlags.Line, 50 },
                { ThresholdTypeFlags.Method, 50 },
                { ThresholdTypeFlags.Branch, 50 },
            };

            ThresholdStatistic thresholdStatic = ThresholdStatistic.Average;

            ThresholdTypeFlags resThresholdTypeFlags = result.GetThresholdTypesBelowThreshold(summary, thresholdTypeFlagValues, thresholdStatic);

            Assert.Equal(ThresholdTypeFlags.None, resThresholdTypeFlags);
        }
Example #22
0
        public void TestGetThresholdTypesBelowThresholdMethod()
        {
            CoverageResult result = new CoverageResult();

            result.Modules = _modules;

            CoverageSummary summary = new CoverageSummary();
            Dictionary <ThresholdTypeFlags, double> thresholdTypeFlagValues = new Dictionary <ThresholdTypeFlags, double>()
            {
                { ThresholdTypeFlags.Line, 50 },
                { ThresholdTypeFlags.Method, 75 },
                { ThresholdTypeFlags.Branch, 10 },
            };

            ThresholdStatistic thresholdStatic = ThresholdStatistic.Minimum;

            ThresholdTypeFlags resThresholdTypeFlags = result.GetThresholdTypesBelowThreshold(summary, thresholdTypeFlagValues, thresholdStatic);

            Assert.Equal(ThresholdTypeFlags.Method, resThresholdTypeFlags);
        }
Example #23
0
        public void TestGetThresholdTypesBelowThresholdAllFail()
        {
            var result = new CoverageResult();

            result.Modules = _modules;

            var summary = new CoverageSummary();
            var thresholdTypeFlagValues = new Dictionary <ThresholdTypeFlags, double>()
            {
                { ThresholdTypeFlags.Line, 100 },
                { ThresholdTypeFlags.Method, 100 },
                { ThresholdTypeFlags.Branch, 100 },
            };

            ThresholdTypeFlags thresholdTypeFlags = ThresholdTypeFlags.Line | ThresholdTypeFlags.Branch | ThresholdTypeFlags.Method;
            ThresholdStatistic thresholdStatic    = ThresholdStatistic.Minimum;

            ThresholdTypeFlags resThresholdTypeFlags = result.GetThresholdTypesBelowThreshold(summary, thresholdTypeFlagValues, thresholdStatic);

            Assert.Equal(thresholdTypeFlags, resThresholdTypeFlags);
        }
Example #24
0
        public void TestGetThresholdTypesBelowThresholdWhenNoModuleInstrumented()
        {
            CoverageResult result = new CoverageResult();

            result.Modules = new Modules();

            CoverageSummary summary = new CoverageSummary();
            Dictionary <ThresholdTypeFlags, double> thresholdTypeFlagValues = new Dictionary <ThresholdTypeFlags, double>()
            {
                { ThresholdTypeFlags.Line, 80 },
                { ThresholdTypeFlags.Method, 80 },
                { ThresholdTypeFlags.Branch, 80 },
            };

            ThresholdTypeFlags thresholdTypeFlags = ThresholdTypeFlags.Line | ThresholdTypeFlags.Branch | ThresholdTypeFlags.Method;
            ThresholdStatistic thresholdStatic    = ThresholdStatistic.Minimum;

            ThresholdTypeFlags resThresholdTypeFlags = result.GetThresholdTypesBelowThreshold(summary, thresholdTypeFlagValues, thresholdStatic);

            Assert.Equal(thresholdTypeFlags, resThresholdTypeFlags);
        }
Example #25
0
        public string Report(CoverageResult result, ISourceRootTranslator sourceRootTranslator)
        {
            if (result.Parameters.DeterministicReport)
            {
                throw new NotSupportedException("Deterministic report not supported by teamcity reporter");
            }

            // Calculate coverage
            var summary               = new CoverageSummary();
            var overallLineCoverage   = summary.CalculateLineCoverage(result.Modules);
            var overallBranchCoverage = summary.CalculateBranchCoverage(result.Modules);
            var overallMethodCoverage = summary.CalculateMethodCoverage(result.Modules);

            // Report coverage
            var stringBuilder = new StringBuilder();

            OutputLineCoverage(overallLineCoverage, stringBuilder);
            OutputBranchCoverage(overallBranchCoverage, stringBuilder);
            OutputMethodCoverage(overallMethodCoverage, stringBuilder);

            // Return a placeholder
            return(stringBuilder.ToString());
        }
Example #26
0
        public CoverageSummary GetCoverageSummary(List <string> coverageFiles)
        {
            var parseResult = ParseCoverageFiles(coverageFiles);
            var summary     = new CoverageSummary();

            int totalLines   = 0;
            int coveredLines = 0;

            foreach (var assembly in parseResult.Assemblies)
            {
                foreach (var @class in assembly.Classes)
                {
                    foreach (var file in @class.Files)
                    {
                        totalLines   += file.CoverableLines;
                        coveredLines += file.CoveredLines;
                    }
                }
            }

            summary.AddCoverageStatistics("line", totalLines, coveredLines, CoverageSummary.Priority.Line);

            return(summary);
        }
Example #27
0
        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);
        }
Example #28
0
        static int Main(string[] args)
        {
            var logger = new ConsoleLogger();
            var app    = new CommandLineApplication();

            app.Name     = "coverlet";
            app.FullName = "Cross platform .NET Core code coverage tool";
            app.HelpOption("-h|--help");
            app.VersionOption("-v|--version", GetAssemblyVersion());

            CommandArgument module              = app.Argument("<ASSEMBLY>", "Path to the test assembly.");
            CommandOption   target              = app.Option("-t|--target", "Path to the test runner application.", CommandOptionType.SingleValue);
            CommandOption   targs               = app.Option("-a|--targetargs", "Arguments to be passed to the test runner.", CommandOptionType.SingleValue);
            CommandOption   output              = app.Option("-o|--output", "Output of the generated coverage report", CommandOptionType.SingleValue);
            CommandOption   formats             = app.Option("-f|--format", "Format of the generated coverage report.", CommandOptionType.MultipleValue);
            CommandOption   threshold           = app.Option("--threshold", "Exits with error if the coverage % is below value.", CommandOptionType.SingleValue);
            CommandOption   thresholdTypes      = app.Option("--threshold-type", "Coverage type to apply the threshold to.", CommandOptionType.MultipleValue);
            CommandOption   excludeFilters      = app.Option("--exclude", "Filter expressions to exclude specific modules and types.", CommandOptionType.MultipleValue);
            CommandOption   includeFilters      = app.Option("--include", "Filter expressions to include only specific modules and types.", CommandOptionType.MultipleValue);
            CommandOption   excludedSourceFiles = app.Option("--exclude-by-file", "Glob patterns specifying source files to exclude.", CommandOptionType.MultipleValue);
            CommandOption   mergeWith           = app.Option("--merge-with", "Path to existing coverage result to merge.", CommandOptionType.SingleValue);

            app.OnExecute(() =>
            {
                if (string.IsNullOrEmpty(module.Value) || string.IsNullOrWhiteSpace(module.Value))
                {
                    throw new CommandParsingException(app, "No test assembly specified.");
                }

                if (!target.HasValue())
                {
                    throw new CommandParsingException(app, "Target must be specified.");
                }

                Coverage coverage = new Coverage(module.Value, excludeFilters.Values.ToArray(), includeFilters.Values.ToArray(), excludedSourceFiles.Values.ToArray(), mergeWith.Value());
                coverage.PrepareModules();

                Process process                          = new Process();
                process.StartInfo.FileName               = target.Value();
                process.StartInfo.Arguments              = targs.HasValue() ? targs.Value() : string.Empty;
                process.StartInfo.CreateNoWindow         = true;
                process.StartInfo.RedirectStandardOutput = true;
                process.Start();
                logger.LogInformation(process.StandardOutput.ReadToEnd());
                process.WaitForExit();

                var dOutput         = output.HasValue() ? output.Value() : Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar.ToString();
                var dThreshold      = threshold.HasValue() ? int.Parse(threshold.Value()) : 0;
                var dThresholdTypes = thresholdTypes.HasValue() ? thresholdTypes.Values : new List <string>(new string[] { "line", "branch", "method" });

                logger.LogInformation("\nCalculating coverage result...");

                var result    = coverage.GetCoverageResult();
                var directory = Path.GetDirectoryName(dOutput);
                if (!Directory.Exists(directory))
                {
                    Directory.CreateDirectory(directory);
                }

                foreach (var format in (formats.HasValue() ? formats.Values : new List <string>(new string[] { "json" })))
                {
                    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
                        logger.LogInformation("  Outputting results to console");
                        logger.LogInformation(reporter.Report(result));
                    }
                    else
                    {
                        // Output to file
                        var filename = Path.GetFileName(dOutput);
                        filename     = (filename == string.Empty) ? $"coverage.{reporter.Extension}" : filename;
                        filename     = Path.HasExtension(filename) ? filename : $"{filename}.{reporter.Extension}";

                        var report = Path.Combine(directory, filename);
                        logger.LogInformation($"  Generating report '{report}'");
                        File.WriteAllText(report, reporter.Report(result));
                    }
                }

                var summary               = new CoverageSummary();
                var exceptionBuilder      = new StringBuilder();
                var coverageTable         = new ConsoleTable("Module", "Line", "Branch", "Method");
                var thresholdFailed       = false;
                var overallLineCoverage   = summary.CalculateLineCoverage(result.Modules);
                var overallBranchCoverage = summary.CalculateBranchCoverage(result.Modules);
                var overallMethodCoverage = summary.CalculateMethodCoverage(result.Modules);

                foreach (var _module in result.Modules)
                {
                    var linePercent   = summary.CalculateLineCoverage(_module.Value).Percent * 100;
                    var branchPercent = summary.CalculateBranchCoverage(_module.Value).Percent * 100;
                    var methodPercent = summary.CalculateMethodCoverage(_module.Value).Percent * 100;

                    coverageTable.AddRow(Path.GetFileNameWithoutExtension(_module.Key), $"{linePercent}%", $"{branchPercent}%", $"{methodPercent}%");

                    if (dThreshold > 0)
                    {
                        if (linePercent < dThreshold && dThresholdTypes.Contains("line"))
                        {
                            exceptionBuilder.AppendLine($"'{Path.GetFileNameWithoutExtension(_module.Key)}' has a line coverage '{linePercent}%' below specified threshold '{dThreshold}%'");
                            thresholdFailed = true;
                        }

                        if (branchPercent < dThreshold && dThresholdTypes.Contains("branch"))
                        {
                            exceptionBuilder.AppendLine($"'{Path.GetFileNameWithoutExtension(_module.Key)}' has a branch coverage '{branchPercent}%' below specified threshold '{dThreshold}%'");
                            thresholdFailed = true;
                        }

                        if (methodPercent < dThreshold && dThresholdTypes.Contains("method"))
                        {
                            exceptionBuilder.AppendLine($"'{Path.GetFileNameWithoutExtension(_module.Key)}' has a method coverage '{methodPercent}%' below specified threshold '{dThreshold}%'");
                            thresholdFailed = true;
                        }
                    }
                }

                logger.LogInformation(string.Empty);
                logger.LogInformation(coverageTable.ToStringAlternative());
                logger.LogInformation($"Total Line: {overallLineCoverage.Percent * 100}%");
                logger.LogInformation($"Total Branch: {overallBranchCoverage.Percent * 100}%");
                logger.LogInformation($"Total Method: {overallMethodCoverage.Percent * 100}%");

                if (thresholdFailed)
                {
                    throw new Exception(exceptionBuilder.ToString().TrimEnd(Environment.NewLine.ToCharArray()));
                }

                return(process.ExitCode == 0 ? 0 : process.ExitCode);
            });

            try
            {
                return(app.Execute(args));
            }
            catch (CommandParsingException ex)
            {
                logger.LogError(ex.Message);
                app.ShowHelp();
                return(1);
            }
            catch (Exception ex)
            {
                logger.LogError(ex.Message);
                return(1);
            }
        }
Example #29
0
        static int Main(string[] args)
        {
            var logger = new ConsoleLogger();
            var app    = new CommandLineApplication();

            app.Name     = "coverlet";
            app.FullName = "Cross platform .NET Core code coverage tool";
            app.HelpOption("-h|--help");
            app.VersionOption("-v|--version", GetAssemblyVersion());
            int exitCode = (int)CommandExitCodes.Success;

            CommandArgument          module              = app.Argument("<ASSEMBLY>", "Path to the test assembly.");
            CommandOption            target              = app.Option("-t|--target", "Path to the test runner application.", CommandOptionType.SingleValue);
            CommandOption            targs               = app.Option("-a|--targetargs", "Arguments to be passed to the test runner.", CommandOptionType.SingleValue);
            CommandOption            output              = app.Option("-o|--output", "Output of the generated coverage report", CommandOptionType.SingleValue);
            CommandOption <LogLevel> verbosity           = app.Option <LogLevel>("-v|--verbosity", "Sets the verbosity level of the command. Allowed values are quiet, minimal, normal, detailed.", CommandOptionType.SingleValue);
            CommandOption            formats             = app.Option("-f|--format", "Format of the generated coverage report.", CommandOptionType.MultipleValue);
            CommandOption            threshold           = app.Option("--threshold", "Exits with error if the coverage % is below value.", CommandOptionType.SingleValue);
            CommandOption            thresholdTypes      = app.Option("--threshold-type", "Coverage type to apply the threshold to.", CommandOptionType.MultipleValue);
            CommandOption            thresholdStat       = app.Option("--threshold-stat", "Coverage statistic used to enforce the threshold value.", CommandOptionType.SingleValue);
            CommandOption            excludeFilters      = app.Option("--exclude", "Filter expressions to exclude specific modules and types.", CommandOptionType.MultipleValue);
            CommandOption            includeFilters      = app.Option("--include", "Filter expressions to include only specific modules and types.", CommandOptionType.MultipleValue);
            CommandOption            excludedSourceFiles = app.Option("--exclude-by-file", "Glob patterns specifying source files to exclude.", CommandOptionType.MultipleValue);
            CommandOption            includeDirectories  = app.Option("--include-directory", "Include directories containing additional assemblies to be instrumented.", CommandOptionType.MultipleValue);
            CommandOption            excludeAttributes   = app.Option("--exclude-by-attribute", "Attributes to exclude from code coverage.", CommandOptionType.MultipleValue);
            CommandOption            includeTestAssembly = app.Option("--include-test-assembly", "Specifies whether to report code coverage of the test assembly.", CommandOptionType.NoValue);
            CommandOption            singleHit           = app.Option("--single-hit", "Specifies whether to limit code coverage hit reporting to a single hit for each location", CommandOptionType.NoValue);
            CommandOption            mergeWith           = app.Option("--merge-with", "Path to existing coverage result to merge.", CommandOptionType.SingleValue);
            CommandOption            useSourceLink       = app.Option("--use-source-link", "Specifies whether to use SourceLink URIs in place of file system paths.", CommandOptionType.NoValue);

            app.OnExecute(() =>
            {
                if (string.IsNullOrEmpty(module.Value) || string.IsNullOrWhiteSpace(module.Value))
                {
                    throw new CommandParsingException(app, "No test assembly specified.");
                }

                if (!target.HasValue())
                {
                    throw new CommandParsingException(app, "Target must be specified.");
                }

                if (verbosity.HasValue())
                {
                    // Adjust log level based on user input.
                    logger.Level = verbosity.ParsedValue;
                }

                // We add default exclusion filter if no specified
                if (excludeFilters.Values.Count == 0)
                {
                    excludeFilters.Values.Add("[xunit*]*");
                }

                Coverage coverage = new Coverage(module.Value,
                                                 includeFilters.Values.ToArray(),
                                                 includeDirectories.Values.ToArray(),
                                                 excludeFilters.Values.ToArray(),
                                                 excludedSourceFiles.Values.ToArray(),
                                                 excludeAttributes.Values.ToArray(),
                                                 includeTestAssembly.HasValue(),
                                                 singleHit.HasValue(),
                                                 mergeWith.Value(),
                                                 useSourceLink.HasValue(),
                                                 logger);
                coverage.PrepareModules();

                Process process                          = new Process();
                process.StartInfo.FileName               = target.Value();
                process.StartInfo.Arguments              = targs.HasValue() ? targs.Value() : string.Empty;
                process.StartInfo.CreateNoWindow         = true;
                process.StartInfo.RedirectStandardOutput = true;
                process.StartInfo.RedirectStandardError  = true;
                process.OutputDataReceived              += (sender, eventArgs) =>
                {
                    if (!string.IsNullOrEmpty(eventArgs.Data))
                    {
                        logger.LogInformation(eventArgs.Data, important: true);
                    }
                };

                process.ErrorDataReceived += (sender, eventArgs) =>
                {
                    if (!string.IsNullOrEmpty(eventArgs.Data))
                    {
                        logger.LogError(eventArgs.Data);
                    }
                };

                process.Start();

                process.BeginErrorReadLine();
                process.BeginOutputReadLine();

                process.WaitForExit();

                var dOutput         = output.HasValue() ? output.Value() : Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar.ToString();
                var dThreshold      = threshold.HasValue() ? double.Parse(threshold.Value()) : 0;
                var dThresholdTypes = thresholdTypes.HasValue() ? thresholdTypes.Values : new List <string>(new string[] { "line", "branch", "method" });
                var dThresholdStat  = thresholdStat.HasValue() ? Enum.Parse <ThresholdStatistic>(thresholdStat.Value(), true) : Enum.Parse <ThresholdStatistic>("minimum", true);

                logger.LogInformation("\nCalculating coverage result...");

                var result    = coverage.GetCoverageResult();
                var directory = Path.GetDirectoryName(dOutput);
                if (directory == string.Empty)
                {
                    directory = Directory.GetCurrentDirectory();
                }
                else if (!Directory.Exists(directory))
                {
                    Directory.CreateDirectory(directory);
                }

                foreach (var format in (formats.HasValue() ? formats.Values : new List <string>(new string[] { "json" })))
                {
                    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
                        logger.LogInformation("  Outputting results to console", important: true);
                        logger.LogInformation(reporter.Report(result), important: true);
                    }
                    else
                    {
                        // Output to file
                        var filename = Path.GetFileName(dOutput);
                        filename     = (filename == string.Empty) ? $"coverage.{reporter.Extension}" : filename;
                        filename     = Path.HasExtension(filename) ? filename : $"{filename}.{reporter.Extension}";

                        var report = Path.Combine(directory, filename);
                        logger.LogInformation($"  Generating report '{report}'", important: true);
                        File.WriteAllText(report, reporter.Report(result));
                    }
                }

                var thresholdTypeFlags = ThresholdTypeFlags.None;

                foreach (var thresholdType in dThresholdTypes)
                {
                    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;
                    }
                }

                var coverageTable = new ConsoleTable("Module", "Line", "Branch", "Method");
                var summary       = new CoverageSummary();
                int numModules    = result.Modules.Count;

                var totalLinePercent   = summary.CalculateLineCoverage(result.Modules).Percent;
                var totalBranchPercent = summary.CalculateBranchCoverage(result.Modules).Percent;
                var totalMethodPercent = summary.CalculateMethodCoverage(result.Modules).Percent;

                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}%");
                }

                logger.LogInformation(coverageTable.ToStringAlternative());

                coverageTable.Columns.Clear();
                coverageTable.Rows.Clear();

                coverageTable.AddColumn(new[] { "", "Line", "Branch", "Method" });
                coverageTable.AddRow("Total", $"{totalLinePercent}%", $"{totalBranchPercent}%", $"{totalMethodPercent}%");
                coverageTable.AddRow("Average", $"{totalLinePercent / numModules}%", $"{totalBranchPercent / numModules}%", $"{totalMethodPercent / numModules}%");

                logger.LogInformation(coverageTable.ToStringAlternative());
                if (process.ExitCode > 0)
                {
                    exitCode += (int)CommandExitCodes.TestFailed;
                }
                thresholdTypeFlags = result.GetThresholdTypesBelowThreshold(summary, dThreshold, thresholdTypeFlags, dThresholdStat);
                if (thresholdTypeFlags != ThresholdTypeFlags.None)
                {
                    exitCode += (int)CommandExitCodes.CoverageBelowThreshold;
                    var exceptionMessageBuilder = new StringBuilder();
                    if ((thresholdTypeFlags & ThresholdTypeFlags.Line) != ThresholdTypeFlags.None)
                    {
                        exceptionMessageBuilder.AppendLine($"The {dThresholdStat.ToString().ToLower()} line coverage is below the specified {dThreshold}");
                    }

                    if ((thresholdTypeFlags & ThresholdTypeFlags.Branch) != ThresholdTypeFlags.None)
                    {
                        exceptionMessageBuilder.AppendLine($"The {dThresholdStat.ToString().ToLower()} branch coverage is below the specified {dThreshold}");
                    }

                    if ((thresholdTypeFlags & ThresholdTypeFlags.Method) != ThresholdTypeFlags.None)
                    {
                        exceptionMessageBuilder.AppendLine($"The {dThresholdStat.ToString().ToLower()} method coverage is below the specified {dThreshold}");
                    }

                    throw new Exception(exceptionMessageBuilder.ToString());
                }

                return(exitCode);
            });

            try
            {
                return(app.Execute(args));
            }
            catch (CommandParsingException ex)
            {
                logger.LogError(ex.Message);
                app.ShowHelp();
                return((int)CommandExitCodes.CommandParsingException);
            }
            catch (Exception ex)
            {
                logger.LogError(ex.Message);
                return(exitCode > 0 ? exitCode : (int)CommandExitCodes.Exception);
            }
        }
Example #30
0
        public string Report(CoverageResult result)
        {
            CoverageSummary summary = new CoverageSummary();

            var lineCoverage   = summary.CalculateLineCoverage(result.Modules);
            var branchCoverage = summary.CalculateBranchCoverage(result.Modules);

            XDocument xml      = new XDocument();
            XElement  coverage = new XElement("coverage");

            coverage.Add(new XAttribute("line-rate", (summary.CalculateLineCoverage(result.Modules).Percent / 100).ToString(CultureInfo.InvariantCulture)));
            coverage.Add(new XAttribute("branch-rate", (summary.CalculateBranchCoverage(result.Modules).Percent / 100).ToString(CultureInfo.InvariantCulture)));
            coverage.Add(new XAttribute("version", "1.9"));
            coverage.Add(new XAttribute("timestamp", (int)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds));

            XElement sources  = new XElement("sources");
            var      rootDirs = GetRootDirs(result.Modules, result.UseSourceLink).ToList();

            rootDirs.ForEach(x => sources.Add(new XElement("source", x)));

            XElement packages = new XElement("packages");

            foreach (var module in result.Modules)
            {
                XElement package = new XElement("package");
                package.Add(new XAttribute("name", Path.GetFileNameWithoutExtension(module.Key)));
                package.Add(new XAttribute("line-rate", (summary.CalculateLineCoverage(module.Value).Percent / 100).ToString(CultureInfo.InvariantCulture)));
                package.Add(new XAttribute("branch-rate", (summary.CalculateBranchCoverage(module.Value).Percent / 100).ToString(CultureInfo.InvariantCulture)));
                package.Add(new XAttribute("complexity", summary.CalculateCyclomaticComplexity(module.Value)));

                XElement classes = new XElement("classes");
                foreach (var document in module.Value)
                {
                    foreach (var cls in document.Value)
                    {
                        XElement @class = new XElement("class");
                        @class.Add(new XAttribute("name", cls.Key));
                        @class.Add(new XAttribute("filename", GetRelativePathFromBase(rootDirs, document.Key, result.UseSourceLink)));
                        @class.Add(new XAttribute("line-rate", (summary.CalculateLineCoverage(cls.Value).Percent / 100).ToString(CultureInfo.InvariantCulture)));
                        @class.Add(new XAttribute("branch-rate", (summary.CalculateBranchCoverage(cls.Value).Percent / 100).ToString(CultureInfo.InvariantCulture)));
                        @class.Add(new XAttribute("complexity", summary.CalculateCyclomaticComplexity(cls.Value)));

                        XElement classLines = new XElement("lines");
                        XElement methods    = new XElement("methods");

                        foreach (var meth in cls.Value)
                        {
                            // Skip all methods with no lines
                            if (meth.Value.Lines.Count == 0)
                            {
                                continue;
                            }

                            XElement method = new XElement("method");
                            method.Add(new XAttribute("name", meth.Key.Split(':').Last().Split('(').First()));
                            method.Add(new XAttribute("signature", "(" + meth.Key.Split(':').Last().Split('(').Last()));
                            method.Add(new XAttribute("line-rate", (summary.CalculateLineCoverage(meth.Value.Lines).Percent / 100).ToString(CultureInfo.InvariantCulture)));
                            method.Add(new XAttribute("branch-rate", (summary.CalculateBranchCoverage(meth.Value.Branches).Percent / 100).ToString(CultureInfo.InvariantCulture)));

                            XElement lines = new XElement("lines");
                            foreach (var ln in meth.Value.Lines)
                            {
                                bool     isBranchPoint = meth.Value.Branches.Any(b => b.Line == ln.Key);
                                XElement line          = new XElement("line");
                                line.Add(new XAttribute("number", ln.Key.ToString()));
                                line.Add(new XAttribute("hits", ln.Value.ToString()));
                                line.Add(new XAttribute("branch", isBranchPoint.ToString()));

                                if (isBranchPoint)
                                {
                                    var branches           = meth.Value.Branches.Where(b => b.Line == ln.Key).ToList();
                                    var branchInfoCoverage = summary.CalculateBranchCoverage(branches);
                                    line.Add(new XAttribute("condition-coverage", $"{branchInfoCoverage.Percent.ToString(CultureInfo.InvariantCulture)}% ({branchInfoCoverage.Covered.ToString(CultureInfo.InvariantCulture)}/{branchInfoCoverage.Total.ToString(CultureInfo.InvariantCulture)})"));
                                    XElement conditions = new XElement("conditions");
                                    var      byOffset   = branches.GroupBy(b => b.Offset).ToDictionary(b => b.Key, b => b.ToList());
                                    foreach (var entry in byOffset)
                                    {
                                        XElement condition = new XElement("condition");
                                        condition.Add(new XAttribute("number", entry.Key));
                                        condition.Add(new XAttribute("type", entry.Value.Count() > 2 ? "switch" : "jump")); // Just guessing here
                                        condition.Add(new XAttribute("coverage", $"{summary.CalculateBranchCoverage(entry.Value).Percent.ToString(CultureInfo.InvariantCulture)}%"));
                                        conditions.Add(condition);
                                    }

                                    line.Add(conditions);
                                }


                                lines.Add(line);
                                classLines.Add(line);
                            }

                            method.Add(lines);
                            methods.Add(method);
                        }

                        @class.Add(methods);
                        @class.Add(classLines);
                        classes.Add(@class);
                    }
                }

                package.Add(classes);
                packages.Add(package);
            }

            coverage.Add(new XAttribute("lines-covered", lineCoverage.Covered.ToString(CultureInfo.InvariantCulture)));
            coverage.Add(new XAttribute("lines-valid", lineCoverage.Total.ToString(CultureInfo.InvariantCulture)));
            coverage.Add(new XAttribute("branches-covered", branchCoverage.Covered.ToString(CultureInfo.InvariantCulture)));
            coverage.Add(new XAttribute("branches-valid", branchCoverage.Total.ToString(CultureInfo.InvariantCulture)));

            coverage.Add(sources);
            coverage.Add(packages);
            xml.Add(coverage);

            var stream = new MemoryStream();

            xml.Save(stream);

            return(Encoding.UTF8.GetString(stream.ToArray()));
        }