public static TestStats operator +(TestStats a, TestStats b) { var testStats = new TestStats(); a = a ?? new TestStats(); b = b ?? new TestStats(); testStats.Tests = a.Tests + b.Tests; testStats.Errors = a.Errors + b.Errors; testStats.Failures = a.Failures + b.Failures; testStats.NotRun = a.NotRun + b.NotRun; testStats.Inconclusive = a.Inconclusive + b.Inconclusive; testStats.Ignored = a.Ignored + b.Ignored; testStats.Skipped = a.Skipped + b.Skipped; testStats.Invalid = a.Invalid + b.Invalid; testStats.Platform.Append(a.Platform); foreach (var part in b.Platform.ToString().Split(',')) { if (!testStats.Platform.ToString().Contains(part.Trim())) { if (testStats.Platform.Length > 0) { testStats.Platform.Append(", "); } testStats.Platform.Append(part); } } return(testStats); }
private static string AddStatistics(TestStats test, string statClass = "stat", string valClass = "val") { var html = new StringBuilder(); html.AppendLine(AddStatisticsCell("Tests", test.Tests, statClass, valClass + " ignore-val", false)); html.AppendLine(AddStatisticsCell("Failures", test.Failures, statClass, valClass, true)); html.AppendLine(AddStatisticsCell("Errors", test.Errors, statClass, valClass, true)); html.AppendLine(AddStatisticsCell("Not\u00A0Run", test.NotRun, statClass, valClass, true)); html.AppendLine(AddStatisticsCell("Inconclusive", test.Inconclusive, statClass, valClass, true)); html.AppendLine(AddStatisticsCell("Ignored", test.Ignored, statClass, valClass, true)); html.AppendLine(AddStatisticsCell("Skipped", test.Skipped, statClass, valClass, true)); html.AppendLine(AddStatisticsCell("Invalid", test.Invalid, statClass, valClass, true)); if (test.Date.Ticks > 0) { html.AppendLine(AddStatisticsCell("Date", test.Date.ToString("d MMM"), statClass, valClass)); html.AppendLine(AddStatisticsCell("Time", test.Date.ToShortTimeString(), statClass, valClass)); } if (test.Platform.Length > 0) { html.AppendLine(AddStatisticsCell("Platform", test.Platform.ToString(), statClass, valClass)); } html.AppendLine(AddStatisticsCell("Success", string.Format("{0}%", 100 - test.Percentage), statClass, valClass)); return(html.ToString()); }
/// <summary> /// Process the results file. /// </summary> /// <param name="file">The filename of the XML results file to parse.</param> /// <param name = "verbose"><c>true</c> to display status message, otherwise <c>false</c></param> /// <returns> /// HTML page content. /// </returns> private static string ProcessFile(string file, bool verbose) { if (verbose) { Console.WriteLine("Processing {0}", file); } var html = new StringBuilder(); XElement doc = XElement.Load(file); _fileCount++; // Load summary values var test = TestStats.Parse(doc); TotalTest += test; // Summary panel html.AppendLine(string.Format("<div class=\"accordion\" id=\"accordion{0}\">", _fileCount)); html.AppendLine("<div class=\"accordion-heading\">"); html.AppendLine(string.Format("<a class=\"accordion-toggle\" data-toggle=\"collapse\" data-parent=\"#accordion{0}\" href=\"#collapse{0}\">", _fileCount)); html.AppendLine( string.Format("<div class=\"panel-heading\">{0} - Tests: {1} - Failures: <span class=\"{3}\">{2}</span> " + "- Errors: <span class=\"{5}\">{4}</span> - Ignored: <span class=\"{7}\">{6}</span> " + "- Skipped: <span class=\"{9}\">{8}</span></div>", test.Name, test.Tests, test.Failures, test.Failures > 0 ? "text-danger" : string.Empty, test.Errors, test.Errors > 0 ? "text-danger" : string.Empty, test.Ignored, test.Ignored > 0 ? "text-danger" : string.Empty, test.Skipped, test.Skipped > 0 ? "text-danger" : string.Empty)); html.AppendLine("</a></div>"); html.AppendLine(string.Format("<div id=\"collapse{0}\" class=\"accordion-body collapse\">", _fileCount)); html.AppendLine("<div class=\"accordion-inner\">"); html.AppendLine("<div class=\"row\">"); html.AppendLine("<div class=\"col-md-12\">"); html.AppendLine("<div class=\"panel panel-default\">"); html.AppendLine(string.Format("<div class=\"panel-heading\">Summary - <small>{0}</small></div>", test.Name)); html.AppendLine("<div class=\"panel-body\">"); html.Append(AddStatistics(test)); // End summary panel html.AppendLine("</div>"); html.AppendLine("</div>"); html.AppendLine("</div>"); // Process test fixtures html.Append(ProcessFixtures(doc.Descendants("test-suite").Where(x => x.Attribute("type").Value == "TestFixture"))); // End container html.AppendLine("</div>"); html.AppendLine("</div>"); html.AppendLine("</div>"); return(html.ToString()); }
public static TestStats Parse(XElement doc) { var test = new TestStats(); test.Name = doc.Attribute("name").Value; test.Tests = int.Parse(!string.IsNullOrEmpty(doc.Attribute("total").Value) ? doc.Attribute("total").Value : "0"); test.Errors = int.Parse(!string.IsNullOrEmpty(doc.Attribute("errors").Value) ? doc.Attribute("errors").Value : "0"); test.Failures = int.Parse(!string.IsNullOrEmpty(doc.Attribute("failures").Value) ? doc.Attribute("failures").Value : "0"); test.NotRun = int.Parse(!string.IsNullOrEmpty(doc.Attribute("not-run").Value) ? doc.Attribute("not-run").Value : "0"); test.Inconclusive = int.Parse(!string.IsNullOrEmpty(doc.Attribute("inconclusive").Value) ? doc.Attribute("inconclusive").Value : "0"); test.Ignored = int.Parse(!string.IsNullOrEmpty(doc.Attribute("ignored").Value) ? doc.Attribute("ignored").Value : "0"); test.Skipped = int.Parse(!string.IsNullOrEmpty(doc.Attribute("skipped").Value) ? doc.Attribute("skipped").Value : "0"); test.Invalid = int.Parse(!string.IsNullOrEmpty(doc.Attribute("invalid").Value) ? doc.Attribute("invalid").Value : "0"); test.Date = DateTime.Parse(string.Format("{0} {1}", doc.Attribute("date").Value, doc.Attribute("time").Value)); test.Platform.Append(doc.Element("environment").Attribute("platform").Value); return(test); }
public static TestStats CalculateFromFixture(XElement doc) { var test = new TestStats(); test.Name = doc.Attribute("name").Value; var testcases = doc.Descendants("test-case"); test.Tests = testcases.Count(x => x.Attribute("executed").Value.ToLower() == "true"); test.NotRun = testcases.Count(x => x.Attribute("executed").Value.ToLower() == "false"); test.Errors = testcases.Count(x => x.Attribute("result").Value.ToLower() == "error"); test.Failures = testcases.Count(x => x.Attribute("result").Value.ToLower() == "failure"); test.Inconclusive = testcases.Count(x => x.Attribute("result").Value.ToLower() == "inconclusive"); test.Ignored = testcases.Count(x => x.Attribute("result").Value.ToLower() == "ignored"); test.Skipped = testcases.Count(x => x.Attribute("result").Value.ToLower() == "skipped"); test.Invalid = testcases.Count(x => x.Attribute("result").Value.ToLower() == "notrunnable"); return(test); }
/// <summary> /// Process the test fixtures. /// </summary> /// <param name="fixtures">The test-fixture elements.</param> /// <returns> /// Fixtures as HTML. /// </returns> private static string ProcessFixtures(IEnumerable <XElement> fixtures) { StringBuilder html = new StringBuilder(); int index = 0; string fixtureName, fixtureNamespace, fixtureTime, fixtureResult, fixtureReason; // Loop through all of the fixtures foreach (var fixture in fixtures) { // Load fixture details fixtureName = fixture.Attribute("name").Value; fixtureNamespace = GetElementNamespace(fixture); fixtureTime = fixture.Attribute("time") != null?fixture.Attribute("time").Value : string.Empty; fixtureResult = fixture.Attribute("result").Value; fixtureReason = fixture.Element("reason") != null?fixture.Element("reason").Element("message").Value : string.Empty; html.AppendLine("<div class=\"col-md-3\">"); html.AppendLine("<div class=\"panel "); // Colour code panels switch (fixtureResult.ToLower()) { case "success": html.Append("panel-success"); break; case "ignored": html.Append("panel-info"); break; case "failure": case "error": html.Append("panel-danger"); break; default: html.Append("panel-default"); break; } html.Append("\">"); html.AppendLine("<div class=\"panel-heading\">"); html.AppendLine(string.Format("{0} - <br><small>{1}</small><small class=\"pull-right\">{2}s</small>", fixtureName, fixtureNamespace, fixtureTime)); // If the fixture has a reason, display an icon // on the top of the panel with a tooltip containing // the reason if (!string.IsNullOrEmpty(fixtureReason)) { html.AppendLine(string.Format("<span class=\"glyphicon glyphicon-info-sign pull-right info hidden-print\" data-toggle=\"tooltip\" title=\"{0}\"></span>", fixtureReason)); } html.AppendLine("</div>"); html.AppendLine("<div class=\"panel-body\">"); html.AppendLine("<div class=\"row\">"); var test = TestStats.CalculateFromFixture(fixture); html.Append(AddStatistics(test, "smallstat", "")); html.AppendLine("</div><div class=\"row\">"); // Generate a unique id for the modal dialog string modalId = string.Format("modal-{0}-{1}", Regex.Replace(HttpUtility.UrlEncode(fixtureName), string.Empty), index++); html.AppendLine("<div class=\"text-center\" style=\"font-size: 1.5em;\">"); // Add a colour coded link to the modal dialog switch (fixtureResult.ToLower()) { case "success": html.AppendLine(string.Format("<a href=\"#{0}\" role=\"button\" data-toggle=\"modal\" class=\"text-success no-underline\">", modalId)); html.AppendLine("<span class=\"glyphicon glyphicon-ok-sign\"></span>"); html.AppendLine("<span class=\"test-result\">Success</span>"); html.AppendLine("</a>"); break; case "ignored": html.AppendLine(string.Format("<a href=\"#{0}\" role=\"button\" data-toggle=\"modal\" class=\"text-info no-underline\">", modalId)); html.AppendLine("<span class=\"glyphicon glyphicon-info-sign\"></span>"); html.AppendLine("<span class=\"test-result\">Ignored</span>"); html.AppendLine("</a>"); break; case "notrunnable": html.AppendLine(string.Format("<a href=\"#{0}\" role=\"button\" data-toggle=\"modal\" class=\"text-default no-underline\">", modalId)); html.AppendLine("<span class=\"glyphicon glyphicon-remove-sign\"></span>"); html.AppendLine("<span class=\"test-result\">Not Runnable</span>"); html.AppendLine("</a>"); break; case "failure": case "error": html.AppendLine(string.Format("<a href=\"#{0}\" role=\"button\" data-toggle=\"modal\" class=\"text-danger no-underline\">", modalId)); html.AppendLine("<span class=\"glyphicon glyphicon-exclamation-sign\"></span>"); html.AppendLine("<span class=\"test-result\">Failed</span>"); html.AppendLine("</a>"); break; default: break; } html.AppendLine("</div>"); // Generate a printable view of the fixtures html.AppendLine(GeneratePrintableView(fixture, fixtureReason)); // Generate the modal dialog that will be shown // if the user clicks on the test-fixtures html.AppendLine(GenerateFixtureModal(fixture, modalId, fixtureName, fixtureReason)); html.AppendLine("</div>"); html.AppendLine("</div>"); html.AppendLine("</div>"); html.AppendLine("</div>"); } return(html.ToString()); }