/// <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); }
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); }
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); }
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); }
/// <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); } } }
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(); }
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); }
private static int CalculateCoverageValue(CoverageDSPriv.MethodRow methodRow) { return (100 * (int)methodRow.BlocksCovered) / (int)(methodRow.BlocksCovered + methodRow.BlocksNotCovered); }