コード例 #1
0
        /// <summary>
        /// Creates the summary report.
        /// </summary>
        /// <param name="reportRenderer">The report renderer.</param>
        /// <param name="summaryResult">The summary result.</param>
        public virtual void CreateSummaryReport(IReportRenderer reportRenderer, SummaryResult summaryResult)
        {
            if (reportRenderer == null)
            {
                throw new ArgumentNullException(nameof(reportRenderer));
            }

            if (summaryResult == null)
            {
                throw new ArgumentNullException(nameof(summaryResult));
            }

            string title = this.ReportContext.ReportConfiguration.Title != null ? $"{ReportResources.Summary} - {this.ReportContext.ReportConfiguration.Title}" : ReportResources.Summary;

            reportRenderer.BeginSummaryReport(this.ReportContext.ReportConfiguration.TargetDirectory, null, title);
            // reportRenderer.HeaderWithGithubLinks(title);

            reportRenderer.BeginKeyValueTable();
            reportRenderer.KeyValueRow(ReportResources.GeneratedOn, DateTime.Now.ToShortDateString() + " - " + DateTime.Now.ToLongTimeString());
            reportRenderer.KeyValueRow(ReportResources.Parser, summaryResult.UsedParser);
            reportRenderer.KeyValueRow(ReportResources.Assemblies2, summaryResult.Assemblies.Count().ToString(CultureInfo.InvariantCulture));
            reportRenderer.KeyValueRow(ReportResources.Classes, summaryResult.Assemblies.SelectMany(a => a.Classes).Count().ToString(CultureInfo.InvariantCulture));
            reportRenderer.KeyValueRow(ReportResources.Files2, summaryResult.Assemblies.SelectMany(a => a.Classes).SelectMany(a => a.Files).Distinct().Count().ToString(CultureInfo.InvariantCulture));
            reportRenderer.KeyValueRow(ReportResources.CoveredLines, summaryResult.CoveredLines.ToString(CultureInfo.InvariantCulture));
            reportRenderer.KeyValueRow(ReportResources.UncoveredLines, (summaryResult.CoverableLines - summaryResult.CoveredLines).ToString(CultureInfo.InvariantCulture));
            reportRenderer.KeyValueRow(ReportResources.CoverableLines, summaryResult.CoverableLines.ToString(CultureInfo.InvariantCulture));
            reportRenderer.KeyValueRow(ReportResources.TotalLines, summaryResult.TotalLines.GetValueOrDefault().ToString(CultureInfo.InvariantCulture));
            reportRenderer.KeyValueRow(ReportResources.Coverage2, summaryResult.CoverageQuota.HasValue ? $"{summaryResult.CoverageQuota.Value.ToString(CultureInfo.InvariantCulture)}% ({summaryResult.CoveredLines.ToString(CultureInfo.InvariantCulture)} {ReportResources.Of} {summaryResult.CoverableLines.ToString(CultureInfo.InvariantCulture)})" : string.Empty);

            if (summaryResult.CoveredBranches.HasValue && summaryResult.TotalBranches.HasValue)
            {
                reportRenderer.KeyValueRow(ReportResources.CoveredBranches2, summaryResult.CoveredBranches.GetValueOrDefault().ToString(CultureInfo.InvariantCulture));
                reportRenderer.KeyValueRow(ReportResources.TotalBranches, summaryResult.TotalBranches.GetValueOrDefault().ToString(CultureInfo.InvariantCulture));

                decimal?branchCoverage = summaryResult.BranchCoverageQuota;

                if (branchCoverage.HasValue)
                {
                    reportRenderer.KeyValueRow(ReportResources.BranchCoverage2, $"{branchCoverage.Value.ToString(CultureInfo.InvariantCulture)}% ({summaryResult.CoveredBranches.GetValueOrDefault().ToString(CultureInfo.InvariantCulture)} {ReportResources.Of} {summaryResult.TotalBranches.GetValueOrDefault().ToString(CultureInfo.InvariantCulture)})");
                }
            }

            if (this.ReportContext.ReportConfiguration.Tag != null)
            {
                reportRenderer.KeyValueRow(ReportResources.Tag, this.ReportContext.ReportConfiguration.Tag);
            }

            reportRenderer.FinishTable();

            if (reportRenderer.SupportsCharts)
            {
                var historicCoverages = this.GetOverallHistoricCoverages(this.ReportContext.OverallHistoricCoverages);
                if (historicCoverages.Any(h => h.CoverageQuota.HasValue || h.BranchCoverageQuota.HasValue))
                {
                    reportRenderer.Header(ReportResources.History);
                    reportRenderer.Chart(historicCoverages, this.ReportContext.Settings.RenderPngFallBackImagesForHistoryCharts);
                }
            }

            var sumableMetrics = summaryResult.SumableMetrics;

            if (sumableMetrics.Count > 0)
            {
                reportRenderer.Header(ReportResources.Metrics);

                var methodMetric = new MethodMetric(ReportResources.Total, ReportResources.Total, sumableMetrics);
                reportRenderer.MetricsTable(new[] { methodMetric });
            }

            if (this.ReportContext.RiskHotspotAnalysisResult != null &&
                this.ReportContext.RiskHotspotAnalysisResult.CodeCodeQualityMetricsAvailable)
            {
                reportRenderer.Header(ReportResources.RiskHotspots);

                if (this.ReportContext.RiskHotspotAnalysisResult.RiskHotspots.Count > 0)
                {
                    reportRenderer.BeginRiskHotspots();
                    reportRenderer.RiskHotspots(this.ReportContext.RiskHotspotAnalysisResult.RiskHotspots);
                    reportRenderer.FinishRiskHotspots();
                }
                else
                {
                    // Angular element has to be present
                    reportRenderer.BeginRiskHotspots();
                    reportRenderer.FinishRiskHotspots();

                    reportRenderer.Paragraph(ReportResources.NoRiskHotspots);
                }
            }
            else
            {
                // Angular element has to be present
                reportRenderer.BeginRiskHotspots();
                reportRenderer.FinishRiskHotspots();
            }

            reportRenderer.Header(ReportResources.Coverage3);

            if (summaryResult.Assemblies.Any())
            {
                reportRenderer.BeginSummaryTable();
                reportRenderer.BeginSummaryTable(summaryResult.SupportsBranchCoverage);

                foreach (var assembly in summaryResult.Assemblies)
                {
                    reportRenderer.SummaryAssembly(assembly, summaryResult.SupportsBranchCoverage);

                    foreach (var @class in assembly.Classes)
                    {
                        reportRenderer.SummaryClass(@class, summaryResult.SupportsBranchCoverage);
                    }
                }

                reportRenderer.FinishTable();
                reportRenderer.FinishSummaryTable();
            }
            else
            {
                // Angular element has to be present
                reportRenderer.BeginSummaryTable();
                reportRenderer.FinishSummaryTable();

                reportRenderer.Paragraph(ReportResources.NoCoveredAssemblies);
            }

            reportRenderer.CustomSummary(summaryResult.Assemblies, this.ReportContext.RiskHotspotAnalysisResult.RiskHotspots, summaryResult.SupportsBranchCoverage);

            reportRenderer.AddFooter();
            reportRenderer.SaveSummaryReport(this.ReportContext.ReportConfiguration.TargetDirectory);
        }
コード例 #2
0
        /// <summary>
        /// Extracts the metrics from the given <see cref="XElement">XElements</see>.
        /// </summary>
        /// <param name="codeFile">The code file.</param>
        /// <param name="methodsOfFile">The methods of the file.</param>
        private static void SetMethodMetrics(CodeFile codeFile, IEnumerable <XElement> methodsOfFile)
        {
            foreach (var method in methodsOfFile)
            {
                string fullName = method.Attribute("name").Value + method.Attribute("signature").Value;
                fullName = ExtractMethodName(fullName, method.Parent.Parent.Attribute("name").Value);

                if (lambdaMethodNameRegex.IsMatch(fullName))
                {
                    continue;
                }

                string shortName = methodRegex.Replace(fullName, m => string.Format(CultureInfo.InvariantCulture, "{0}({1})", m.Groups["MethodName"].Value, m.Groups["Arguments"].Value.Length > 0 ? "..." : string.Empty));

                var metrics = new List <Metric>();

                var lineRate = method.Attribute("line-rate");

                if (lineRate != null)
                {
                    decimal?value = null;

                    if (!"NaN".Equals(lineRate.Value, StringComparison.OrdinalIgnoreCase))
                    {
                        value = Math.Round(100 * decimal.Parse(lineRate.Value, CultureInfo.InvariantCulture), 2, MidpointRounding.AwayFromZero);
                    }

                    metrics.Add(new Metric(
                                    ReportResources.Coverage,
                                    ParserBase.CodeCoverageUri,
                                    MetricType.CoveragePercentual,
                                    value));
                }

                var branchRate = method.Attribute("branch-rate");

                if (branchRate != null)
                {
                    decimal?value = null;

                    if (!"NaN".Equals(branchRate.Value, StringComparison.OrdinalIgnoreCase))
                    {
                        value = Math.Round(100 * decimal.Parse(branchRate.Value, CultureInfo.InvariantCulture), 2, MidpointRounding.AwayFromZero);
                    }

                    metrics.Add(new Metric(
                                    ReportResources.BranchCoverage,
                                    ParserBase.CodeCoverageUri,
                                    MetricType.CoveragePercentual,
                                    value));
                }

                var cyclomaticComplexityAttribute = method.Attribute("complexity");

                if (cyclomaticComplexityAttribute != null)
                {
                    decimal?value = null;

                    if (!"NaN".Equals(cyclomaticComplexityAttribute.Value, StringComparison.OrdinalIgnoreCase))
                    {
                        value = Math.Round(decimal.Parse(cyclomaticComplexityAttribute.Value, CultureInfo.InvariantCulture), 2, MidpointRounding.AwayFromZero);
                    }

                    metrics.Insert(
                        0,
                        new Metric(
                            ReportResources.CyclomaticComplexity,
                            ParserBase.CyclomaticComplexityUri,
                            MetricType.CodeQuality,
                            value,
                            MetricMergeOrder.LowerIsBetter));
                }

                var methodMetric = new MethodMetric(fullName, shortName, metrics);

                var line = method
                           .Elements("lines")
                           .Elements("line")
                           .FirstOrDefault();

                if (line != null)
                {
                    methodMetric.Line = int.Parse(line.Attribute("number").Value, CultureInfo.InvariantCulture);
                }

                /* If cobertura file is merged from different files, a class and therefore method can exist several times.
                 * The first result is used. */
                if (codeFile.MethodMetrics.Any(m => m.Equals(methodMetric)))
                {
                    continue;
                }

                codeFile.AddMethodMetric(methodMetric);
            }
        }
コード例 #3
0
        /// <summary>
        /// Extracts the metrics from the given <see cref="XElement">XElements</see>.
        /// </summary>
        /// <param name="codeFile">The code file.</param>
        /// <param name="methodsOfFile">The methods of the file.</param>
        private static void SetMethodMetrics(CodeFile codeFile, IEnumerable <XElement> methodsOfFile)
        {
            foreach (var methodGroup in methodsOfFile.GroupBy(m => m.Element("Name").Value))
            {
                var method = methodGroup.First();

                // Exclude properties and lambda expressions
                if (method.Attribute("skippedDueTo") != null ||
                    method.HasAttributeWithValue("isGetter", "true") ||
                    method.HasAttributeWithValue("isSetter", "true") ||
                    lambdaMethodNameRegex.IsMatch(methodGroup.Key))
                {
                    continue;
                }

                var metrics = new List <Metric>()
                {
                    new Metric(
                        ReportResources.CyclomaticComplexity,
                        ParserBase.CyclomaticComplexityUri,
                        MetricType.CodeQuality,
                        methodGroup.Max(m => int.Parse(m.Attribute("cyclomaticComplexity").Value, CultureInfo.InvariantCulture)),
                        MetricMergeOrder.LowerIsBetter),
                    new Metric(
                        ReportResources.SequenceCoverage,
                        ParserBase.CodeCoverageUri,
                        MetricType.CoveragePercentual,
                        methodGroup.Max(m => decimal.Parse(m.Attribute("sequenceCoverage").Value, CultureInfo.InvariantCulture))),
                    new Metric(
                        ReportResources.BranchCoverage,
                        ParserBase.CodeCoverageUri,
                        MetricType.CoveragePercentual,
                        methodGroup.Max(m => decimal.Parse(m.Attribute("branchCoverage").Value, CultureInfo.InvariantCulture)))
                };

                var npathComplexityAttributes = methodGroup.Select(m => m.Attribute("nPathComplexity")).Where(a => a != null).ToArray();

                if (npathComplexityAttributes.Length > 0)
                {
                    metrics.Insert(
                        1,
                        new Metric(
                            ReportResources.NPathComplexity,
                            ParserBase.NPathComplexityUri,
                            MetricType.CodeQuality,
                            npathComplexityAttributes
                            .Select(a => int.Parse(a.Value, CultureInfo.InvariantCulture))
                            .Max(a => a < 0 ? int.MaxValue : a),
                            MetricMergeOrder.LowerIsBetter));
                }

                var crapScoreAttributes = methodGroup.Select(m => m.Attribute("crapScore")).Where(a => a != null).ToArray();
                if (crapScoreAttributes.Length > 0)
                {
                    metrics.Add(new Metric(
                                    ReportResources.CrapScore,
                                    ParserBase.CrapScoreUri,
                                    MetricType.CodeQuality,
                                    crapScoreAttributes.Max(a => decimal.Parse(a.Value, CultureInfo.InvariantCulture)),
                                    MetricMergeOrder.LowerIsBetter));
                }

                string fullName  = ExtractMethodName(methodGroup.Key);
                string shortName = methodRegex.Replace(fullName, m => string.Format(CultureInfo.InvariantCulture, "{0}({1})", m.Groups["MethodName"].Value, m.Groups["Arguments"].Value.Length > 0 ? "..." : string.Empty));

                var methodMetric = new MethodMetric(fullName, shortName, metrics);

                var seqpnt = method
                             .Elements("SequencePoints")
                             .Elements("SequencePoint")
                             .FirstOrDefault();

                if (seqpnt != null)
                {
                    methodMetric.Line = int.Parse(seqpnt.Attribute("sl").Value, CultureInfo.InvariantCulture);
                }

                codeFile.AddMethodMetric(methodMetric);
            }
        }
コード例 #4
0
 /// <summary>
 /// Adds a metrics table to the report.
 /// </summary>
 /// <param name="metric">The metric.</param>
 public void BeginMetricsTable(MethodMetric metric)
 {
 }
コード例 #5
0
        /// <summary>
        /// Extracts the metrics from the given <see cref="XElement">XElements</see>.
        /// </summary>
        /// <param name="codeFile">The code file.</param>
        /// <param name="methodsOfFile">The methods of the file.</param>
        private static void SetMethodMetrics(CodeFile codeFile, IEnumerable <XElement> methodsOfFile)
        {
            foreach (var method in methodsOfFile)
            {
                string fullName = method.Attribute("name").Value + method.Attribute("desc").Value;

                if (fullName.StartsWith("lambda$"))
                {
                    continue;
                }

                string shortName = methodRegex.Replace(fullName, m => string.Format(CultureInfo.InvariantCulture, "{0}({1})", m.Groups["MethodName"].Value, m.Groups["Arguments"].Value.Length > 0 ? "..." : string.Empty));

                var metrics = new List <Metric>();

                var lineRate = method.Elements("counter")
                               .Where(e => e.Attribute("type") != null && e.Attribute("type").Value == "LINE")
                               .FirstOrDefault();

                if (lineRate != null)
                {
                    decimal missed  = decimal.Parse(lineRate.Attribute("missed").Value, CultureInfo.InvariantCulture);
                    decimal covered = decimal.Parse(lineRate.Attribute("covered").Value, CultureInfo.InvariantCulture);
                    decimal total   = missed + covered;

                    metrics.Add(new Metric(
                                    ReportResources.Coverage,
                                    ParserBase.CodeCoverageUri,
                                    MetricType.CoveragePercentual,
                                    total == 0 ? (decimal?)null : Math.Round((100 * covered) / total, 2, MidpointRounding.AwayFromZero)));
                }
                else
                {
                    // If no line rate available, do not add branch coverage too
                    continue;
                }

                var branchRate = method.Elements("counter")
                                 .Where(e => e.Attribute("type") != null && e.Attribute("type").Value == "BRANCH")
                                 .FirstOrDefault();

                if (branchRate != null)
                {
                    decimal missed  = decimal.Parse(branchRate.Attribute("missed").Value, CultureInfo.InvariantCulture);
                    decimal covered = decimal.Parse(branchRate.Attribute("covered").Value, CultureInfo.InvariantCulture);
                    decimal total   = missed + covered;

                    metrics.Add(new Metric(
                                    ReportResources.BranchCoverage,
                                    ParserBase.CodeCoverageUri,
                                    MetricType.CoveragePercentual,
                                    total == 0 ? (decimal?)null : Math.Round((100 * covered) / total, 2, MidpointRounding.AwayFromZero)));
                }
                else
                {
                    // If no branch coverage is available, add default to avoid empty columns
                    metrics.Add(new Metric(
                                    ReportResources.BranchCoverage,
                                    ParserBase.CodeCoverageUri,
                                    MetricType.CoveragePercentual,
                                    null));
                }

                var methodMetric = new MethodMetric(fullName, shortName, metrics);
                methodMetric.Line = method.Attribute("line") != null?int.Parse(method.Attribute("line").Value, CultureInfo.InvariantCulture) : default(int?);

                codeFile.AddMethodMetric(methodMetric);
            }
        }