/// <summary> /// Write a Test node under Test, to hold information for the Test: log, test result, duration, Test info, which /// won't show for every Variation in Xml viewer. /// </summary> /// <param name="tableWriter">Writer</param> /// <param name="test">test</param> /// <param name="testInfo">testInfo</param> /// <param name="testLogPath">test log path</param> private static void WriteChildTestNode(XmlTableWriter tableWriter, TestRecord test, TestInfo testInfo, string testLogPath) { bool logTruncated = false; tableWriter.WriteStartElement("Test"); tableWriter.WriteAttributeString("Duration", ReportingUtilities.FormatTimeSpanAsSeconds(ReportingUtilities.GetTestDuration(test))); //Total test execution Time tableWriter.WriteAttributeString("Result", ReportingUtilities.InterpretTestOutcome(test).ToString()); tableWriter.WriteAttributeString("Log", ReportingUtilities.ProcessLongLog(test.Log, testLogPath, ref logTruncated)); if (logTruncated) { tableWriter.WriteAttributeString("LogPath", Path.Combine(ReportingUtilities.TestLogsDir, Path.GetFileName(testLogPath))); } tableWriter.WriteAttributeString("LogDir", ReportingUtilities.ReportPaths(test.LoggedFiles)); int failed = 0; int failedOnBug = 0; bool hasBugs = ReportingUtilities.TestHasBugs(testInfo); foreach (VariationRecord variation in test.Variations) { failed += ReportingUtilities.OneForFail(variation.Result); failedOnBug += ReportingUtilities.OneForFailOnBug(variation.Result, hasBugs); } tableWriter.WriteAttributeString("Failures", string.Format("{0}", failed - failedOnBug)); tableWriter.WriteAttributeString("Total", string.Format("{0}", test.Variations.Count)); tableWriter.WriteEndElement(); }
/// <summary> /// Write one test. /// </summary> /// <param name="tableWriter">Writer</param> /// <param name="areaReportsPath">Area path</param> /// <param name="area">Area name</param> /// <param name="test">TestRecord</param> /// <param name="testIndex">Index of the test</param> private static void WriteTestNode(XmlTableWriter tableWriter, string areaReportsPath, string area, TestRecord test, int testIndex) { TestInfo testInfo = test.TestInfo; string testLogsDirectory = Path.Combine(areaReportsPath, ReportingUtilities.TestLogsDir); string testInfosDirectory = Path.Combine(areaReportsPath, ReportingUtilities.TestInfosDir); //Test Layer with attribute needed for all variation. tableWriter.WriteStartElement("Test"); tableWriter.WriteAttributeString("Name", Escape(testInfo.Name)); tableWriter.WriteAttributeString("KnownBugs", test.TestInfo.Bugs.ToCommaSeparatedList()); tableWriter.WriteAttributeString("Priority", test.TestInfo.Priority.ToString()); tableWriter.WriteAttributeString("Machine", ReportingUtilities.ReportMachine(test.Machine)); string testInfoPath = Path.Combine(testInfosDirectory, String.Format("{0}_{1}.xml", area, testIndex)); if (ReportingUtilities.InterpretTestOutcome(test) == Result.Fail) { ReportingUtilities.SaveTestInfo(testInfoPath, testInfo); tableWriter.WriteAttributeString("TestInfo", Path.Combine(ReportingUtilities.TestInfosDir, Path.GetFileName(testInfoPath))); } for (int variationIndex = 0; variationIndex < test.Variations.Count; variationIndex++) { VariationRecord variation = test.Variations[variationIndex]; string variationLogPath = Path.Combine(testLogsDirectory, String.Format("{0}_{1}_{2}.log", area, testIndex, variationIndex)); WriteVariationNode(tableWriter, variation, variationLogPath); } //SEMI HACK: Create a node to hold information for test, that are not needed for most variation. // This solves three problems: // 1 - Allows us to provide Test level information in tabular form // 2 - Allows us to include Test level execution logs in these reports // Note - To nest these things attribute in parent Test node, while less hacky, would create a different semantic from the perspective of any XML viewer, which would be bad. very bad. string testLogPath = Path.Combine(testLogsDirectory, String.Format("{0}_{1}.log", area, testIndex)); WriteChildTestNode(tableWriter, test, testInfo, testLogPath); tableWriter.WriteEndElement(); }
private static void Generate(TestRecords records, string path) { using (XmlTableWriter tableWriter = new XmlTableWriter(path)) { tableWriter.AddXsl(@"DrtReport.xsl"); tableWriter.WriteStartElement("Variations"); tableWriter.WriteAttributeString("PassRate", ReportingUtilities.CalculatePassRate(records)); foreach (TestRecord test in FilterNonPassingTests(records)) { TestInfo testInfo = test.TestInfo; { tableWriter.WriteStartElement("Variation"); tableWriter.WriteAttributeString("Area", testInfo.Area); tableWriter.WriteAttributeString("TestName", testInfo.Name); tableWriter.WriteAttributeString("Variation", "Test Level Summary"); tableWriter.WriteAttributeString("Duration", ReportingUtilities.FormatTimeSpanAsSeconds(ReportingUtilities.GetTestDuration(test))); //Total test execution Time tableWriter.WriteAttributeString("Result", ReportingUtilities.InterpretTestOutcome(test).ToString()); tableWriter.WriteAttributeString("Log", test.Log); tableWriter.WriteAttributeString("LogDir", ReportingUtilities.ReportPaths(test.LoggedFiles)); tableWriter.WriteEndElement(); } foreach (VariationRecord variation in test.Variations) { tableWriter.WriteStartElement("Variation"); tableWriter.WriteAttributeString("Area", testInfo.Area); tableWriter.WriteAttributeString("TestName", testInfo.Name); tableWriter.WriteAttributeString("Variation", variation.VariationName); tableWriter.WriteAttributeString("Duration", ReportingUtilities.FormatTimeSpanAsSeconds(ReportingUtilities.GetVariationDuration(variation))); tableWriter.WriteAttributeString("Result", variation.Result.ToString()); tableWriter.WriteAttributeString("Log", variation.Log); tableWriter.WriteAttributeString("LogDir", ReportingUtilities.ReportPaths(variation.LoggedFiles)); tableWriter.WriteEndElement(); } } tableWriter.WriteEndElement(); } }
/// <summary> /// Produces a simple console summary report /// </summary> internal static void WriteSummaryToConsole(TestRecords results) { Console.WriteLine(); Console.WriteLine("A total of {0} test Infos were processed, with the following results.", results.TestCollection.Count); if (results.TestCollection.Count > 0) { int Pass = 0; int Fail = 0; int FailWithBugID = 0; int Ignore = 0; #if REPORT_VERSIONS Dictionary <String, Tuple <int, List <TestInfo> > > dict = new Dictionary <String, Tuple <int, List <TestInfo> > >(); #endif foreach (TestRecord test in results.TestCollection) { TestInfo testInfo = test.TestInfo; switch (ReportingUtilities.InterpretTestOutcome(test)) { case Result.Ignore: Ignore++; break; case Result.Pass: Pass++; break; case Result.Fail: Fail++; if (ReportingUtilities.TestHasBugs(testInfo)) { FailWithBugID++; } break; } #if REPORT_VERSIONS String key = (testInfo.Versions == null) ? String.Empty : String.Join(",", ToArray(testInfo.Versions)); if (!dict.ContainsKey(key)) { dict.Add(key, new Tuple <int, List <TestInfo> >(0, new List <TestInfo>())); } Tuple <int, List <TestInfo> > tuple = dict[key]; List <TestInfo> list = tuple.Item2; if (list.Count < 5) { list.Add(testInfo); } dict[key] = new Tuple <int, List <TestInfo> >(tuple.Item1 + 1, list); #endif } Console.WriteLine(" Passed: {0}", Pass); Console.WriteLine(" Failed (need to analyze): {0}", Fail - FailWithBugID); Console.WriteLine(" Failed (with BugIDs): {0}", FailWithBugID); Console.WriteLine(" Ignore: {0}", Ignore); Console.WriteLine(); #if REPORT_VERSIONS foreach (KeyValuePair <string, Tuple <int, List <TestInfo> > > kvp in dict) { Tuple <int, List <TestInfo> > tuple = kvp.Value; Console.WriteLine("{0} tests with versions '{1}'", tuple.Item1, kvp.Key); foreach (TestInfo testInfo in tuple.Item2) { Console.WriteLine(" /Area={0} /SubArea={1} /Name={2}", testInfo.Area, testInfo.SubArea, testInfo.Name); } } #endif } }
internal static TestCollection FilterNonPassingTests(TestRecords tests) { IEnumerable <TestRecord> failingTests = tests.TestCollection.Where(test => (ReportingUtilities.InterpretTestOutcome(test) != Result.Pass)); return(new TestCollection(failingTests)); }