diff --git a/src/JUnit.Xml.TestLogger/JunitXmlSerializer.cs b/src/JUnit.Xml.TestLogger/JunitXmlSerializer.cs index 835049d..4389b3a 100644 --- a/src/JUnit.Xml.TestLogger/JunitXmlSerializer.cs +++ b/src/JUnit.Xml.TestLogger/JunitXmlSerializer.cs @@ -359,6 +359,16 @@ private XElement CreateTestCaseElement(TestResultInfo result) // seconds should be low enough it won't interfere with anyone monitoring test duration. testcaseElement.SetAttributeValue("time", Math.Max(0.0000001f, result.Duration.TotalSeconds).ToString("0.0000000", CultureInfo.InvariantCulture)); + if (!string.IsNullOrEmpty(result.CodeFilePath)) + { + testcaseElement.SetAttributeValue("file", result.CodeFilePath); + } + + if (result.LineNumber > 0) + { + testcaseElement.SetAttributeValue("line", result.LineNumber); + } + if (result.Outcome == TestOutcome.Failed) { var failureBodySB = new StringBuilder(); diff --git a/test/JUnit.Xml.TestLogger.UnitTests/JUnitXmlTestSerializerTests.cs b/test/JUnit.Xml.TestLogger.UnitTests/JUnitXmlTestSerializerTests.cs index c2076b7..9bc6e25 100644 --- a/test/JUnit.Xml.TestLogger.UnitTests/JUnitXmlTestSerializerTests.cs +++ b/test/JUnit.Xml.TestLogger.UnitTests/JUnitXmlTestSerializerTests.cs @@ -224,6 +224,40 @@ public void TestSuiteShouldIncludeSystemErrElementWhenContentExists() Assert.IsTrue(systemErrElement.Value.Contains("Error - Error message")); } + [TestMethod] + public void TestCaseShouldIncludeFileAndLineAttributesWhenSourceIsPresent() + { + var serializer = new JunitXmlSerializer(); + var result = CreateTestResultInfo(); + + var testCase = SerializeAndGetTestCaseElement(serializer, result); + + Assert.AreEqual(TestCsPath, testCase.Attribute("file")?.Value); + Assert.AreEqual("42", testCase.Attribute("line")?.Value); + } + + [TestMethod] + public void TestCaseShouldOmitFileAttributeWhenCodeFilePathIsMissing() + { + var serializer = new JunitXmlSerializer(); + var result = CreateTestResultInfo(codeFilePath: null); + + var testCase = SerializeAndGetTestCaseElement(serializer, result); + + Assert.IsNull(testCase.Attribute("file")); + } + + [TestMethod] + public void TestCaseShouldOmitLineAttributeWhenLineNumberIsMissing() + { + var serializer = new JunitXmlSerializer(); + var result = CreateTestResultInfo(lineNumber: 0); + + var testCase = SerializeAndGetTestCaseElement(serializer, result); + + Assert.IsNull(testCase.Attribute("line")); + } + private static LoggerConfiguration CreateTestLoggerConfiguration() { return new LoggerConfiguration(new Dictionary @@ -237,7 +271,11 @@ private static TestRunConfiguration CreateTestRunConfiguration() return new TestRunConfiguration { StartTime = DateTime.Now }; } - private static TestResultInfo CreateTestResultInfo(TestOutcome outcome = TestOutcome.Passed, List messages = null) + private static TestResultInfo CreateTestResultInfo( + TestOutcome outcome = TestOutcome.Passed, + List messages = null, + string codeFilePath = TestCsPath, + int lineNumber = 42) { return new TestResultInfo( TestNamespace, @@ -248,8 +286,8 @@ private static TestResultInfo CreateTestResultInfo(TestOutcome outcome = TestOut TestDisplayName, TestDisplayName, TestDllPath, - TestCsPath, - 42, + codeFilePath, + lineNumber, DateTime.Now, DateTime.Now.AddSeconds(1), TimeSpan.FromSeconds(1), @@ -262,7 +300,7 @@ private static TestResultInfo CreateTestResultInfo(TestOutcome outcome = TestOut null); } - private static string SerializeAndExtractElementContent(JunitXmlSerializer serializer, TestResultInfo result, string elementName) + private static XElement SerializeAndGetTestCaseElement(JunitXmlSerializer serializer, TestResultInfo result) { var xml = serializer.Serialize( CreateTestLoggerConfiguration(), @@ -272,6 +310,13 @@ private static string SerializeAndExtractElementContent(JunitXmlSerializer seria var doc = XDocument.Parse(xml); var testCaseElement = doc.XPathSelectElement("//testcase"); + Assert.IsNotNull(testCaseElement, "testcase element not found"); + return testCaseElement; + } + + private static string SerializeAndExtractElementContent(JunitXmlSerializer serializer, TestResultInfo result, string elementName) + { + var testCaseElement = SerializeAndGetTestCaseElement(serializer, result); var targetElement = testCaseElement.Element(elementName); Assert.IsNotNull(targetElement, $"Element '{elementName}' not found in testcase"); diff --git a/test/assets/JUnit.xsd b/test/assets/JUnit.xsd index 89c9e0c..ddca757 100644 --- a/test/assets/JUnit.xsd +++ b/test/assets/JUnit.xsd @@ -82,6 +82,8 @@ Modifications to original xsd for this repo: + +