in src/Agent.Worker/TestResults/Legacy/JunitResultReader.cs [32:168]
public TestRunData ReadResults(IExecutionContext executionContext, string filePath, TestRunContext runContext = null)
{
// http://windyroad.com.au/dl/Open%20Source/JUnit.xsd
XmlDocument doc = new XmlDocument();
try
{
var settings = new XmlReaderSettings
{
DtdProcessing = DtdProcessing.Ignore
};
using (XmlReader reader = XmlReader.Create(filePath, settings))
{
doc.Load(reader);
}
}
catch (XmlException ex)
{
executionContext.Warning(StringUtil.Loc("FailedToReadFile", filePath, ex.Message));
return null;
}
//init test run summary information - run name, host name, start time
TestSuiteSummary runSummary = new TestSuiteSummary(Name);
IdentityRef runUserIdRef = null;
string runUser = runContext != null ? runContext.Owner : string.Empty;
if (!string.IsNullOrEmpty(runUser))
{
runUserIdRef = new IdentityRef() { DisplayName = runUser };
}
var presentTime = DateTime.UtcNow;
runSummary.TimeStamp = DateTime.MaxValue;
var maxCompletedTime = DateTime.MinValue;
//read data from testsuite nodes
XmlNode testSuitesNode = doc.SelectSingleNode("testsuites");
if (testSuitesNode != null)
{
//found testsuites node - some plugins generate it like karma junit plugin
XmlNodeList testSuiteNodeList = doc.SelectNodes("/testsuites/testsuite");
if (testSuiteNodeList != null)
{
foreach (XmlNode testSuiteNode in testSuiteNodeList)
{
//for each available suites get all suite details
TestSuiteSummary testSuiteSummary = ReadTestSuite(testSuiteNode, runUserIdRef);
// sum up testsuite durations and test case durations, decision on what to use will be taken later
runSummary.TotalTestCaseDuration = runSummary.TotalTestCaseDuration.Add(testSuiteSummary.TotalTestCaseDuration);
runSummary.TestSuiteDuration = runSummary.TestSuiteDuration.Add(testSuiteSummary.TestSuiteDuration);
runSummary.SuiteTimeDataAvailable = runSummary.SuiteTimeDataAvailable && testSuiteSummary.SuiteTimeDataAvailable;
runSummary.SuiteTimeStampAvailable = runSummary.SuiteTimeStampAvailable && testSuiteSummary.SuiteTimeStampAvailable;
runSummary.Host = testSuiteSummary.Host;
runSummary.Name = testSuiteSummary.Name;
//stop calculating timestamp information, if timestamp data is not avilable for even one test suite
if (testSuiteSummary.SuiteTimeStampAvailable)
{
runSummary.TimeStamp = runSummary.TimeStamp > testSuiteSummary.TimeStamp ? testSuiteSummary.TimeStamp : runSummary.TimeStamp;
DateTime completedTime = testSuiteSummary.TimeStamp.AddTicks(testSuiteSummary.TestSuiteDuration.Ticks);
maxCompletedTime = maxCompletedTime < completedTime ? completedTime : maxCompletedTime;
}
runSummary.Results.AddRange(testSuiteSummary.Results);
}
if (testSuiteNodeList.Count > 1)
{
runSummary.Name = Name + "_" + Path.GetFileName(filePath);
}
}
}
else
{
XmlNode testSuiteNode = doc.SelectSingleNode("testsuite");
if (testSuiteNode != null)
{
runSummary = ReadTestSuite(testSuiteNode, runUserIdRef);
//only if start time is available then only we need to calculate completed time
if (runSummary.TimeStamp != DateTime.MaxValue)
{
DateTime completedTime = runSummary.TimeStamp.AddTicks(runSummary.TestSuiteDuration.Ticks);
maxCompletedTime = maxCompletedTime < completedTime ? completedTime : maxCompletedTime;
}
else
{
runSummary.SuiteTimeStampAvailable = false;
}
}
}
if (runContext != null && !string.IsNullOrWhiteSpace(runContext.RunName))
{
runSummary.Name = runContext.RunName;
}
if (!runSummary.SuiteTimeStampAvailable)
{
executionContext.Output("Timestamp is not available for one or more testsuites. Total run duration is being calculated as the sum of time durations of detected testsuites");
if (!runSummary.SuiteTimeDataAvailable)
{
executionContext.Output("Time is not available for one or more testsuites. Total run duration is being calculated as the sum of time durations of detected testcases");
}
}
//if start time is not calculated then it should be initialized as present time
runSummary.TimeStamp = runSummary.TimeStamp == DateTime.MaxValue
? presentTime
: runSummary.TimeStamp;
//if suite timestamp data is not available even for single testsuite, then fallback to testsuite run time
//if testsuite run time is not available even for single testsuite, then fallback to total test case duration
maxCompletedTime = !runSummary.SuiteTimeStampAvailable || maxCompletedTime == DateTime.MinValue
? runSummary.TimeStamp.Add(runSummary.SuiteTimeDataAvailable ? runSummary.TestSuiteDuration
: runSummary.TotalTestCaseDuration) : maxCompletedTime;
//create test run data
var testRunData = new TestRunData(
name: runSummary.Name,
startedDate: runSummary.TimeStamp != DateTime.MinValue ? runSummary.TimeStamp.ToString("o") : null,
completedDate: maxCompletedTime != DateTime.MinValue ? maxCompletedTime.ToString("o") : null,
state: TestRunState.InProgress.ToString(),
isAutomated: true,
buildId: runContext != null ? runContext.BuildId : 0,
buildFlavor: runContext != null ? runContext.Configuration : string.Empty,
buildPlatform: runContext != null ? runContext.Platform : string.Empty,
releaseUri: runContext != null ? runContext.ReleaseUri : null,
releaseEnvironmentUri: runContext != null ? runContext.ReleaseEnvironmentUri : null
)
{
Results = runSummary.Results.ToArray(),
Attachments = AddResultsFileToRunLevelAttachments ? new string[] { filePath } : new string[0]
};
return testRunData;
}