예제 #1
0
        /// <summary>
        /// Writes a coverage report in the configured format.
        /// </summary>
        /// <param name="models">The models to include in the coverage file.</param>
        /// <param name="configuration">The report configuration,</param>
        public void WriteReport(IEnumerable <CoverageNodeModel> models, ReportConfigurationModel configuration)
        {
            Contract.RequiresNotNull(models, nameof(models));
            Contract.Requires(models.Any(), "No coverage data to create a report for.", nameof(models));
            Contract.RequiresNotNull(configuration, nameof(configuration));

            ReportWriter writer;

            switch (configuration.ReportFormat)
            {
            case ReportFormat.HtmlSingleFile:
                writer = new HtmlSingleFileReportWriter();
                break;

            case ReportFormat.HtmlMultiFile:
                writer = new HtmlMultiFileReportWriter();
                break;

            default:
                throw Utility.UnreachableCode("Unexpected report type.");
            }

            CoverageDSPriv merged      = ConcatenateFiles(models.Select(CreateSerializable));
            var            reportModel = new CoverageExport(configuration.ProjectName, merged);

            writer.WriteReport(reportModel, configuration);
        }
예제 #2
0
        private static CoverageDSPriv CreateSerializable(CoverageNodeModel model)
        {
            var file = new CoverageDSPriv();

            file.Modules         = model.Children.Select(CreateSerializableModule).ToArray();
            file.SourceFileNames = (SourceFileInfo[])(model.AdditionalData["SourceFileNames"]);

            return(file);
        }
예제 #3
0
        internal void Load()
        {
            XmlSerializer xmlSerializer = new XmlSerializer(typeof(CoverageDSPriv));

            using var fs     = new FileStream(FilePath, FileMode.Open);
            using var reader = XmlDictionaryReader.CreateTextReader(fs, new XmlDictionaryReaderQuotas());
            CoverageDSPriv coverage = (CoverageDSPriv)xmlSerializer.Deserialize(reader);

            Modules = coverage.Items.Where(i => i is CoverageDSPrivModule).Select(i => i as CoverageDSPrivModule);
            Files   = coverage.Items.Where(i => i is CoverageDSPrivSourceFileNames).Select(i => i as CoverageDSPrivSourceFileNames);
        }
예제 #4
0
        private static CoverageNodeModel ReadFile(CoverageDSPriv file)
        {
            var model = new CoverageNodeModel(CoverageNodeType.CoverageFile);

            foreach (var mod in file.Modules)
            {
                model.Children.Add(ReadModule(mod));
            }

            model.AdditionalData[nameof(file.SourceFileNames)] = file.SourceFileNames;

            return(model);
        }
예제 #5
0
        /// <summary>
        /// Writes a coverage XML file in the same format as Visual Studio.
        /// </summary>
        /// <param name="models">The models to include in the coverage file.</param>
        /// <param name="path">The path to write to.</param>
        public void WriteCoverageXml(IEnumerable <CoverageNodeModel> models, string path)
        {
            // Here be a bit of ugly: I needed to jump through a couple hoops to get
            // this to be in a binary-same format as Visual Studio outputs.
            //
            //  1) Because XmlSerializer cannot write out a schema like the CoverageDSPriv files have
            //     the coverage XML is first written to a temp buffer.
            //
            //  2) Had to add the Namespaces\NamespacesInternal properties to CoverageDSPriv to
            //     make XmlSerializer _not_ write out the xsi and xsd namespaces.

            var ser = new XmlSerializer(typeof(CoverageDSPriv));

            var settings = new XmlWriterSettings
            {
                Indent             = true,
                IndentChars        = "    ",
                OmitXmlDeclaration = true,
                Encoding           = Encoding.Unicode,
            };


            CoverageDSPriv merged = ConcatenateFiles(models.Select(CreateSerializable));

            using (var tempFile = new TempFile())
            {
                using (var writer = XmlWriter.Create(tempFile.Stream, settings))
                {
                    ser.Serialize(writer, merged, CoverageDSPriv.NamespacesInternal);
                }

                tempFile.ResetPosition();

                var itemDoc = new XmlDocument();
                itemDoc.Load(tempFile.Stream);
                itemDoc.DocumentElement.PrependChild(
                    itemDoc.ImportNode(_schemaDoc.DocumentElement, true)
                    );

                using (var writer = XmlWriter.Create(path, settings))
                {
                    itemDoc.Save(writer);
                }
            }
        }
예제 #6
0
        internal CoverageExport(string name, CoverageDSPriv exportData)
        {
            Name = name;

            var modules = new List <ModuleExport>();

            foreach (ModuleCoverageInfo mod in exportData.Modules)
            {
                modules.Add(new ModuleExport(mod));

                LinesCovered          += mod.LinesCovered;
                LinesPartiallyCovered += mod.LinesPartiallyCovered;
                LinesNotCovered       += mod.LinesNotCovered;
                BlocksCovered         += mod.BlocksCovered;
                BlocksNotCovered      += mod.BlocksNotCovered;
            }

            Modules = modules.ToArray();
        }
예제 #7
0
        private static IList <ClassCoverage> FindExternalCoveredClasses(SourceClassDetail source, CoverageDSPriv codeCoverage)
        {
            var data           = new List <ClassCoverage>();
            var thirdPartyLibs = source.TestClaz.ClassProject
                                 .GetProjectThirdPartyLibraries()
                                 .Select(x => x
                                         .Split('\\')
                                         .Last()).ToList();

            thirdPartyLibs.Add("nunit");
            thirdPartyLibs.Add("microsoft.");
            if (codeCoverage != null)
            {
                var parentClassNameList = $"{source.Claz.Syntax.NameSpace()}.{string.Join(".", source.Claz.Syntax.Ancestors<ClassDeclarationSyntax>().Select(x => x.ClassNameWithoutGeneric()))}".TrimEnd('.');
                var nestedClassNameList = $"{parentClassNameList}.{source.Claz.Syntax.ClassNameWithoutGeneric()}.{string.Join(".", source.Claz.Syntax.DescendantNodes<ClassDeclarationSyntax>().Select(x => x.ClassNameWithoutGeneric()))}".TrimEnd('.');
                if (parentClassNameList == source.Claz.Syntax.NameSpace())
                {
                    parentClassNameList = $"{parentClassNameList}.{source.Claz.Syntax.ClassNameWithoutGeneric()}";
                }

                foreach (CoverageDSPriv.ClassRow claz in codeCoverage.Class)
                {
                    if (claz.LinesCovered > 0 && thirdPartyLibs.All(x => !claz.NamespaceTableRow.ModuleRow.ModuleName.StartsWith(x, StringComparison.InvariantCultureIgnoreCase)))
                    {
                        var className            = claz.ClassName;
                        var genericIndexLocation = claz.ClassName.IndexOf(GenericMethodStart, StringComparison.Ordinal);
                        if (genericIndexLocation != -1)
                        {
                            className = className.Substring(0, genericIndexLocation).TrimEnd('.');
                        }

                        var fullName = $"{claz.NamespaceTableRow.NamespaceName}.{className}";
                        if (data.All(x => x.ClassName != fullName) &&
                            !fullName.Contains(parentClassNameList) &&
                            !fullName.Contains(nestedClassNameList))
                        {
                            var coverages = codeCoverage
                                            .Class
                                            .Where(x => x.ClassName == className ||
                                                   x.ClassName.StartsWith($"{className}.{GenericMethodStart}") ||
                                                   x.ClassName.StartsWith($"{className}{GenericMethodStart}")).ToList();

                            coverages = coverages.Where(x => x.NamespaceTableRow.NamespaceKeyName == claz.NamespaceKeyName).ToList();

                            if (coverages.Any())
                            {
                                var methods         = codeCoverage.Method.Where(x => x.ClassKeyName == claz.ClassKeyName).ToList();
                                var method          = methods.FirstOrDefault();
                                var numberOfMutants = 0;
                                var excluded        = false;
                                var mutantsLines    = new List <int>();

                                uint autogeneratedLineCovered     = 0;
                                uint autogeneratedLineNonCovered  = 0;
                                uint autogeneratedBlockCovered    = 0;
                                uint autogeneratedBlockNonCovered = 0;

                                var file = string.Empty;
                                if (method != null)
                                {
                                    file = codeCoverage.SourceFileNames.FirstOrDefault(x => x.SourceFileID == method.GetLinesRows().FirstOrDefault()?.SourceFileID)?.SourceFileName;
                                    if (!string.IsNullOrWhiteSpace(file) && File.Exists(file))
                                    {
                                        var root             = file.GetCodeFileContent().RootNode().ClassNode(className.Split('.').Last());
                                        var classDeclaration = new ClassDeclaration(root);
                                        var classDetail      = new SourceClassDetail
                                        {
                                            Claz     = classDeclaration,
                                            TestClaz = new TestClassDetail()
                                        };

                                        if (root != null)
                                        {
                                            new MethodsInitializer().FindMethods(classDetail).Wait();
                                            var mutants = classDetail.MethodDetails
                                                          .Where(x => !x.IsProperty && !x.IsConstructor && !x.IsOverrideMethod)
                                                          .SelectMany(x => MutantOrchestrator.GetDefaultMutants(x.Method, classDetail.Claz));
                                            var coveredLines = claz.GetMethodRows().SelectMany(x => x.GetLinesRows()).Where(x => x.Coverage == 0).ToList();
                                            mutants         = mutants.Where(x => coveredLines.Any(y => y.LnStart == x.Mutation.Location)).ToList();
                                            mutantsLines    = mutants.Select(x => x.Mutation.Location ?? 0).ToList();
                                            numberOfMutants = mutants.Count();

                                            excluded = root.ExcludeFromExternalCoverage();

                                            var autogeneratedMethods = root.GetGeneratedCodeMethods();
                                            foreach (var methodSyntax in autogeneratedMethods)
                                            {
                                                var autoGeneratedCoverage = methods.FirstOrDefault(x => x.MethodFullName.Equals($"{methodSyntax.MethodName()}()") ||
                                                                                                   x.MethodName.Equals($"{methodSyntax.MethodName()}()"));
                                                if (autoGeneratedCoverage != null)
                                                {
                                                    autogeneratedLineCovered     += autoGeneratedCoverage.LinesCovered;
                                                    autogeneratedLineNonCovered  += autoGeneratedCoverage.LinesNotCovered;
                                                    autogeneratedBlockCovered    += autoGeneratedCoverage.BlocksCovered;
                                                    autogeneratedBlockNonCovered += autoGeneratedCoverage.BlocksNotCovered;
                                                }
                                            }

                                            if (methods.Any(x => x.MethodFullName.Equals($"{InitializecomponentMethod}()")) &&
                                                !autogeneratedMethods.Any() &&
                                                !classDetail.MethodDetails.Any(x => x.Method.MethodName().Equals(InitializecomponentMethod)))
                                            {
                                                var autoGeneratedCoverage = methods.First(x => x.MethodFullName.Equals($"{InitializecomponentMethod}()"));

                                                autogeneratedLineCovered     += autoGeneratedCoverage.LinesCovered;
                                                autogeneratedLineNonCovered  += autoGeneratedCoverage.LinesNotCovered;
                                                autogeneratedBlockCovered    += autoGeneratedCoverage.BlocksCovered;
                                                autogeneratedBlockNonCovered += autoGeneratedCoverage.BlocksNotCovered;
                                            }
                                        }
                                        else
                                        {
                                            excluded = true;
                                        }
                                    }
                                }

                                var classCoverage = new ClassCoverage
                                {
                                    ClassName = fullName,
                                    ClassPath = file,
                                    Coverage  = new Coverage {
                                        LinesCovered     = (uint)coverages.Sum(x => x.LinesCovered) - autogeneratedLineCovered,
                                        LinesNotCovered  = (uint)coverages.Sum(x => x.LinesNotCovered) - autogeneratedLineNonCovered,
                                        BlocksCovered    = (uint)coverages.Sum(x => x.BlocksCovered) - autogeneratedBlockCovered,
                                        BlocksNotCovered = (uint)coverages.Sum(x => x.BlocksNotCovered) - autogeneratedBlockNonCovered
                                    },
                                    NumberOfMutants = numberOfMutants,
                                    Excluded        = excluded
                                };

                                classCoverage.MutantsLines.AddRange(mutantsLines);
                                data.Add(classCoverage);
                            }
                        }
                    }
                }
            }

            return(data);
        }
예제 #8
0
 private static int CalculateCoverageValue(CoverageDSPriv.MethodRow methodRow)
 {
     return (100 * (int)methodRow.BlocksCovered) / (int)(methodRow.BlocksCovered + methodRow.BlocksNotCovered);
 }