using System.Xml.Linq; using Azaion.Missions.E2E.Reporting; using Xunit; namespace Azaion.Missions.E2E.Tests.Reporting; /// /// Regression tests for AC-4 of AZ-576 — the post-processor produces the /// documented CSV header plus one row per executed test, with traits merged /// in from the test assembly when supplied. /// public sealed class TrxToCsvPostProcessorTests { private const string TrxNs = "http://microsoft.com/schemas/VisualStudio/TeamTest/2010"; [Fact] [Trait("Category", "Blackbox")] [Trait("Traces", "AC-4")] public void Csv_header_matches_environment_md_specification() { // Act var header = ResultRow.CsvHeader; // Assert Assert.Equal("TestId,TestName,Category,Traces,ExecutionTimeMs,Result,ErrorMessage", header); } [Fact] [Trait("Category", "Blackbox")] [Trait("Traces", "AC-4")] public void Extracts_one_csv_row_per_unit_test_result() { // Arrange var trx = BuildTrx( (Id: "11111111-1111-1111-1111-111111111111", Name: "Foo.Test1", Outcome: "Passed", Duration: "00:00:00.0500000", ErrorMessage: null), (Id: "22222222-2222-2222-2222-222222222222", Name: "Foo.Test2", Outcome: "Failed", Duration: "00:00:01.2500000", ErrorMessage: "boom\nstack frame")); // Act var rows = TrxToCsvPostProcessor .ExtractRows(trx, new Dictionary(0)) .ToList(); // Assert Assert.Equal(2, rows.Count); Assert.Equal("11111111-1111-1111-1111-111111111111", rows[0].TestId); Assert.Equal("pass", rows[0].Result); Assert.Equal(50, rows[0].ExecutionTimeMs); Assert.Equal("fail", rows[1].Result); Assert.Equal(1250, rows[1].ExecutionTimeMs); } [Fact] [Trait("Category", "Blackbox")] [Trait("Traces", "AC-4")] public void Trait_map_merges_into_csv_columns_when_test_name_matches() { // Arrange var trx = BuildTrx( (Id: "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa", Name: "Foo.Test1", Outcome: "Passed", Duration: "00:00:00.0050000", ErrorMessage: null)); var traits = new Dictionary { ["Foo.Test1"] = new("Sec", "AC-1,AC-2") }; // Act var row = TrxToCsvPostProcessor.ExtractRows(trx, traits).Single(); // Assert Assert.Equal("Sec", row.Category); Assert.Equal("AC-1,AC-2", row.Traces); } [Fact] [Trait("Category", "Blackbox")] [Trait("Traces", "AC-4")] public void Csv_escapes_commas_and_quotes_in_error_message() { // Arrange var row = new ResultRow( TestId: "id", TestName: "Foo.Test, with comma", Category: "Sec", Traces: "AC-1", ExecutionTimeMs: 5, Result: "fail", ErrorMessage: "a \"quoted\" value, with comma"); // Act var csv = row.ToCsv(); // Assert Assert.Contains("\"Foo.Test, with comma\"", csv); Assert.Contains("\"a \"\"quoted\"\" value, with comma\"", csv); } private static XDocument BuildTrx(params (string Id, string Name, string Outcome, string Duration, string? ErrorMessage)[] tests) { XNamespace ns = TrxNs; var results = new XElement(ns + "Results"); var defs = new XElement(ns + "TestDefinitions"); foreach (var t in tests) { var resultEl = new XElement(ns + "UnitTestResult", new XAttribute("testId", t.Id), new XAttribute("testName", t.Name), new XAttribute("outcome", t.Outcome), new XAttribute("duration", t.Duration)); if (t.ErrorMessage is not null) { resultEl.Add(new XElement(ns + "Output", new XElement(ns + "ErrorInfo", new XElement(ns + "Message", t.ErrorMessage)))); } results.Add(resultEl); defs.Add(new XElement(ns + "UnitTest", new XAttribute("name", t.Name), new XAttribute("id", t.Id))); } return new XDocument(new XElement(ns + "TestRun", results, defs)); } }