public string GenerateReport(CoverageResult result) { XDocument xml = new XDocument(); XElement coverage = new XElement("CoverageSession"); XElement coverageSummary = new XElement("Summary"); XElement modules = new XElement("Modules"); int numClasses = 0, numMethods = 0; int visitedClasses = 0, visitedMethods = 0; int i = 1; foreach (var mod in result.Assemblies) { XElement module = new XElement("Module"); module.Add(new XAttribute("hash", Guid.NewGuid().ToString().ToUpper())); XElement path = new XElement("ModulePath", mod.Name); XElement time = new XElement("ModuleTime", DateTime.UtcNow.ToString("yyyy-MM-ddThh:mm:ss")); XElement name = new XElement("ModuleName", Path.GetFileNameWithoutExtension(mod.Name)); module.Add(path); module.Add(time); module.Add(name); XElement files = new XElement("Files"); XElement classes = new XElement("Classes"); var docToTypesMap = mod.GetDocumentToTypesMap(); foreach (var doc in docToTypesMap) { XElement file = new XElement("File"); file.Add(new XAttribute("uid", i.ToString())); file.Add(new XAttribute("fullPath", doc.Key)); files.Add(file); foreach (var cls in doc.Value) { XElement @class = new XElement("Class"); XElement classSummary = new XElement("Summary"); XElement className = new XElement("FullName", cls.FullName); XElement methods = new XElement("Methods"); int j = 0; foreach (var meth in cls.Methods) { if (meth.LinesCount == 0) { continue; } var methLineCoverage = meth.GetLineSummary(); var methBranchCoverage = meth.GetBranchSummary(); int methCyclomaticComplexity = 0; XElement method = new XElement("Method"); method.Add(new XAttribute("cyclomaticComplexity", methCyclomaticComplexity.ToString())); method.Add(new XAttribute("nPathComplexity", "0")); method.Add(new XAttribute("sequenceCoverage", methLineCoverage.Percentage.ToString("G", CultureInfo.InvariantCulture))); method.Add(new XAttribute("branchCoverage", methBranchCoverage.Percentage.ToString("G", CultureInfo.InvariantCulture))); method.Add(new XAttribute("isConstructor", meth.FullName.Contains("ctor").ToString())); method.Add(new XAttribute("isGetter", meth.FullName.Contains("get_").ToString())); method.Add(new XAttribute("isSetter", meth.FullName.Contains("set_").ToString())); method.Add(new XAttribute("isStatic", (!meth.FullName.Contains("get_") || !meth.FullName.Contains("set_")).ToString())); XElement methodName = new XElement("Name", meth.FullName); XElement fileRef = new XElement("FileRef"); fileRef.Add(new XAttribute("uid", i.ToString())); XElement methodPoint = new XElement("MethodPoint"); methodPoint.Add(new XAttribute("vc", methLineCoverage.Covered.ToString())); methodPoint.Add(new XAttribute("uspid", "0")); methodPoint.Add(new XAttribute(XName.Get("type", "xsi"), "SequencePoint")); methodPoint.Add(new XAttribute("ordinal", j.ToString())); methodPoint.Add(new XAttribute("offset", j.ToString())); methodPoint.Add(new XAttribute("sc", "0")); methodPoint.Add(new XAttribute("sl", meth.StartLine.ToString())); methodPoint.Add(new XAttribute("ec", "1")); methodPoint.Add(new XAttribute("el", meth.EndLine.ToString())); methodPoint.Add(new XAttribute("bec", "0")); methodPoint.Add(new XAttribute("bev", "0")); methodPoint.Add(new XAttribute("fileid", i.ToString())); XElement sequencePoints = new XElement("SequencePoints"); XElement branchPoints = new XElement("BranchPoints"); XElement methodSummary = new XElement("Summary"); var branchCoverage = new SummaryResult(0, 0); XElement sequencePoint = new XElement("SequencePoint"); sequencePoint.Add(new XAttribute("vc", meth.VisitCount)); sequencePoint.Add(new XAttribute("uspid", "0")); sequencePoint.Add(new XAttribute("ordinal", "0")); sequencePoint.Add(new XAttribute("sl", meth.StartLine)); sequencePoint.Add(new XAttribute("sc", meth.StartColumn)); sequencePoint.Add(new XAttribute("el", meth.EndLine)); sequencePoint.Add(new XAttribute("ec", meth.EndColumn)); sequencePoint.Add(new XAttribute("bec", branchCoverage.Total)); sequencePoint.Add(new XAttribute("bev", branchCoverage.Covered)); sequencePoint.Add(new XAttribute("fileid", i.ToString())); sequencePoints.Add(sequencePoint); numMethods++; if (meth.IsVisited) { visitedMethods++; } methodSummary.Add(new XAttribute("numSequencePoints", methLineCoverage.Total.ToString())); methodSummary.Add(new XAttribute("visitedSequencePoints", methLineCoverage.Covered.ToString())); methodSummary.Add(new XAttribute("numBranchPoints", methBranchCoverage.Total.ToString())); methodSummary.Add(new XAttribute("visitedBranchPoints", methBranchCoverage.Covered.ToString())); methodSummary.Add(new XAttribute("sequenceCoverage", methLineCoverage.Percentage.ToString("G", CultureInfo.InvariantCulture))); methodSummary.Add(new XAttribute("branchCoverage", methBranchCoverage.Percentage.ToString("G", CultureInfo.InvariantCulture))); methodSummary.Add(new XAttribute("maxCyclomaticComplexity", methCyclomaticComplexity.ToString())); methodSummary.Add(new XAttribute("minCyclomaticComplexity", methCyclomaticComplexity.ToString())); methodSummary.Add(new XAttribute("visitedClasses", "0")); methodSummary.Add(new XAttribute("numClasses", "0")); methodSummary.Add(new XAttribute("visitedMethods", meth.IsVisited ? "1" : "0")); methodSummary.Add(new XAttribute("numMethods", "1")); method.Add(methodSummary); method.Add(new XElement("MetadataToken")); method.Add(methodName); method.Add(fileRef); method.Add(sequencePoints); method.Add(branchPoints); method.Add(methodPoint); methods.Add(method); j++; } numClasses++; if (cls.IsVisited) { visitedClasses++; } var classLineCoverage = cls.GetLineSummary(); var classBranchCoverage = cls.GetBranchSummary(); var classMethodCoverage = cls.GetMethodSummary(); var classMaxCyclomaticComplexity = 0; var classMinCyclomaticComplexity = 0; classSummary.Add(new XAttribute("numSequencePoints", classLineCoverage.Total.ToString())); classSummary.Add(new XAttribute("visitedSequencePoints", classLineCoverage.Covered.ToString())); classSummary.Add(new XAttribute("numBranchPoints", classBranchCoverage.Total.ToString())); classSummary.Add(new XAttribute("visitedBranchPoints", classBranchCoverage.Covered.ToString())); classSummary.Add(new XAttribute("sequenceCoverage", classLineCoverage.Percentage.ToString("G", CultureInfo.InvariantCulture))); classSummary.Add(new XAttribute("branchCoverage", classBranchCoverage.Percentage.ToString("G", CultureInfo.InvariantCulture))); classSummary.Add(new XAttribute("maxCyclomaticComplexity", classMaxCyclomaticComplexity.ToString())); classSummary.Add(new XAttribute("minCyclomaticComplexity", classMinCyclomaticComplexity.ToString())); classSummary.Add(new XAttribute("visitedClasses", cls.IsVisited ? "1" : "0")); classSummary.Add(new XAttribute("numClasses", "1")); classSummary.Add(new XAttribute("visitedMethods", classMethodCoverage.Covered.ToString())); classSummary.Add(new XAttribute("numMethods", classMethodCoverage.Total.ToString())); @class.Add(classSummary); @class.Add(className); @class.Add(methods); classes.Add(@class); } i++; } module.Add(files); module.Add(classes); modules.Add(module); } var moduleLineCoverage = result.GetLineSummary(); var moduleBranchCoverage = result.GetBranchSummary(); var moduleMaxCyclomaticComplexity = 0; var moduleMinCyclomaticComplexity = 0; coverageSummary.Add(new XAttribute("numSequencePoints", moduleLineCoverage.Total.ToString())); coverageSummary.Add(new XAttribute("visitedSequencePoints", moduleLineCoverage.Covered.ToString())); coverageSummary.Add(new XAttribute("numBranchPoints", moduleBranchCoverage.Total.ToString())); coverageSummary.Add(new XAttribute("visitedBranchPoints", moduleBranchCoverage.Covered.ToString())); coverageSummary.Add(new XAttribute("sequenceCoverage", moduleLineCoverage.Percentage.ToString("G", CultureInfo.InvariantCulture))); coverageSummary.Add(new XAttribute("branchCoverage", moduleBranchCoverage.Percentage.ToString("G", CultureInfo.InvariantCulture))); coverageSummary.Add(new XAttribute("maxCyclomaticComplexity", moduleMaxCyclomaticComplexity.ToString())); coverageSummary.Add(new XAttribute("minCyclomaticComplexity", moduleMinCyclomaticComplexity.ToString())); coverageSummary.Add(new XAttribute("visitedClasses", visitedClasses.ToString())); coverageSummary.Add(new XAttribute("numClasses", numClasses.ToString())); coverageSummary.Add(new XAttribute("visitedMethods", visitedMethods.ToString())); coverageSummary.Add(new XAttribute("numMethods", numMethods.ToString())); coverage.Add(coverageSummary); coverage.Add(modules); xml.Add(coverage); var stream = new MemoryStream(); xml.Save(stream); return(Encoding.UTF8.GetString(stream.ToArray())); }
public string GenerateReport(CoverageResult coverageResult) { var lineCoverage = coverageResult.GetLineSummary(); var branchCoverage = coverageResult.GetBranchSummary(); XDocument xml = new XDocument(); XElement coverage = new XElement("coverage"); coverage.Add(new XAttribute("line-rate", (lineCoverage.Percentage / 100).ToString(CultureInfo.InvariantCulture))); coverage.Add(new XAttribute("branch-rate", (branchCoverage.Percentage / 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 absolutePaths = coverageResult.GetSources().ToList(); absolutePaths.ForEach(x => sources.Add(new XElement("source", x))); XElement packages = new XElement("packages"); foreach (var module in coverageResult.Assemblies) { var asmLineSummary = module.GetLineSummary(); var asmBranchSummary = module.GetBranchSummary(); XElement package = new XElement("package"); package.Add(new XAttribute("name", module.Name)); package.Add(new XAttribute("line-rate", (asmLineSummary.Percentage / 100).ToString(CultureInfo.InvariantCulture))); package.Add(new XAttribute("branch-rate", (asmBranchSummary.Percentage / 100).ToString(CultureInfo.InvariantCulture))); package.Add(new XAttribute("complexity", module.CalculateCyclomaticComplexity())); XElement classes = new XElement("classes"); foreach (var document in module.GetDocumentToTypesMap()) { foreach (var cls in document.Value) { var clsLineSummary = cls.GetLineSummary(); var clsBranchSummary = cls.GetBranchSummary(); XElement @class = new XElement("class"); @class.Add(new XAttribute("name", cls.FullName)); @class.Add(new XAttribute("filename", document.Key)); @class.Add(new XAttribute("line-rate", (clsLineSummary.Percentage / 100).ToString(CultureInfo.InvariantCulture))); @class.Add(new XAttribute("branch-rate", (clsBranchSummary.Percentage / 100).ToString(CultureInfo.InvariantCulture))); @class.Add(new XAttribute("complexity", cls.CalculateCyclomaticComplexity())); XElement classLines = new XElement("lines"); XElement methods = new XElement("methods"); foreach (var meth in cls.Methods) { if (meth.LinesCount == 0) { continue; } var methLineSummary = meth.GetLineSummary(); var methBranchSummary = meth.GetBranchSummary(); XElement method = new XElement("method"); method.Add(new XAttribute("name", meth.FullName.Split(':').Last().Split('(').First())); method.Add(new XAttribute("signature", "(" + meth.FullName.Split(':').Last().Split('(').Last())); method.Add(new XAttribute("line-rate", (methLineSummary.Percentage / 100).ToString(CultureInfo.InvariantCulture))); method.Add(new XAttribute("branch-rate", (branchCoverage.Percentage / 100).ToString(CultureInfo.InvariantCulture))); XElement lines = new XElement("lines"); // Add only one line const bool isBranchPoint = false; // TODO: Check if it's really branch point XElement line = new XElement("line"); line.Add(new XAttribute("number", meth.StartLine)); line.Add(new XAttribute("hits", meth.VisitCount)); line.Add(new XAttribute("branch", isBranchPoint.ToString())); 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())); }