private static void MapOutputToResult(Testcase test, TestResultDrop drop)
        {
            var messages        = new List <TestResultMessageDrop>();
            var errorMessage    = new StringBuilder();
            var errorStackTrace = new StringBuilder();

            if (test.FailureSpecified)
            {
                foreach (var failure in test.Failure)
                {
                    if (!string.IsNullOrEmpty(failure.Message))
                    {
                        errorMessage.Append(failure.Message);
                        errorStackTrace.Append(string.Join(Environment.NewLine, failure.Text));
                    }
                }
            }

            if (test.System_OutSpecified)
            {
                foreach (var stdOut in test.System_Out)
                {
                    if (!string.IsNullOrEmpty(stdOut))
                    {
                        messages.Add(new TestResultMessageDrop {
                            Text = stdOut, Category = "Standard"
                        });
                    }
                }
            }

            if (test.System_OutSpecified)
            {
                foreach (var stdErr in test.System_Out)
                {
                    if (!string.IsNullOrEmpty(stdErr))
                    {
                        messages.Add(new TestResultMessageDrop {
                            Text = stdErr, Category = "Error"
                        });
                    }
                }
            }

            drop.Messages        = messages;
            drop.ErrorMessage    = errorMessage.ToString();
            drop.ErrorStackTrace = errorStackTrace.ToString();
        }
        /// <summary>
        /// Maps result types from TRX into instance of drop models with configuration
        /// </summary>
        /// <param name="source">Instance of test results from deserialised TRX input</param>
        /// <param name="destination">Instance to map and merge results into</param>
        /// <param name="inputConfiguration">User configured input for current source</param>
        public static void Map(TestRunType source, TestRunDrop destination, ReportInput inputConfiguration = null)
        {
            var times    = source.Times.FirstOrDefault();
            var started  = DateTimeOffset.Parse(times.Start);
            var finished = DateTimeOffset.Parse(times.Finish);

            if (destination.Started is null || destination.Started > started)
            {
                destination.Started = started;
            }
            if (destination.Finished is null || destination.Finished < finished)
            {
                destination.Finished = finished;
            }

            var definitions          = source.TestDefinitions.SelectMany(x => x.UnitTest).ToDictionary(k => k.Id, v => v);
            var unitTestResultsGroup = source.Results
                                       .SelectMany(r => r.UnitTestResult)
                                       .Select(r => (result: r, definition: definitions[r.TestId]))
                                       .GroupBy(t => inputConfiguration?.GroupTitle ?? StringFilters.PathSplit(t.definition.TestMethod.CodeBase).Last()) // Group by codebase if no title is provided
                                       .ToList();

            foreach (var resultGroup in unitTestResultsGroup)
            {
                TestResultSetDrop drop;

                if (destination.ResultSets.TryGetValue(resultGroup.Key, out var existingDrop))
                {
                    drop = existingDrop;
                }
                else
                {
                    drop = new TestResultSetDrop
                    {
                        Source  = resultGroup.Key,
                        Results = new List <TestResultDrop>(),
                    };
                    destination.ResultSets.Add(drop);
                }

                foreach (var(result, definition) in resultGroup)
                {
                    foreach (var unitTestResults in ExtractTestResults(result))
                    {
                        var testCase = new TestCaseDrop
                        {
                            Source             = definition.TestMethod.CodeBase,
                            DisplayName        = string.IsNullOrEmpty(inputConfiguration?.TestSuffix) ? unitTestResults.TestName : $"{unitTestResults.TestName}{inputConfiguration.TestSuffix}",
                            FullyQualifiedName = $"{definition.TestMethod.ClassName}.{definition.TestMethod.Name}",
                            Id          = Guid.Parse(definition.Id),
                            ExecutorUri = definition.TestMethod.AdapterTypeName,
                        };
                        var startTime  = DateTimeOffset.Parse(unitTestResults.StartTime);
                        var endTime    = DateTimeOffset.Parse(unitTestResults.EndTime);
                        var duration   = (endTime - startTime);
                        var outcome    = MapOutcome(unitTestResults.Outcome, drop, destination.TestRunStatistics);
                        var resultDrop = new TestResultDrop
                        {
                            StartTime      = startTime,
                            EndTime        = endTime,
                            Duration       = duration,
                            Outcome        = outcome,
                            TestCase       = testCase,
                            ComputerName   = unitTestResults.ComputerName,
                            AttachmentSets = new List <AttachmentSetDrop>(unitTestResults.CollectorDataEntries.Select(rf => new AttachmentSetDrop
                            {
                                Attachments = new List <AttachmentDrop>(rf.Collector.Select(c => new AttachmentDrop
                                {
                                    Description = c.CollectorDisplayName,
                                    Uri         = c.Uri
                                }))
                            })),
                            DisplayName = definition.TestMethod.Name
                        };
                        MapOutputToResult(unitTestResults.Output, resultDrop);
                        destination.TestRunStatistics.ExecutedTestsCount++;
                        destination.ElapsedTimeInRunningTests += duration;
                        drop.Duration += duration;
                        drop.ExecutedTestsCount++;
                        drop.Results.Add(resultDrop);
                    }
                }
            }
        }
        private static void MapOutputToResult(Collection <OutputType> outputColection, TestResultDrop drop)
        {
            var messages        = new List <TestResultMessageDrop>();
            var errorMessage    = string.Empty;
            var errorStackTrace = string.Empty;

            foreach (var output in outputColection)
            {
                if (output.ErrorInfo?.Message is IEnumerable <XmlNode> errorMessageNodes)
                {
                    foreach (var errorMessageNode in errorMessageNodes)
                    {
                        if (!string.IsNullOrEmpty(errorMessageNode.Value))
                        {
                            errorMessage += $"{errorMessageNode.Value}";
                        }
                    }
                }

                if (output.ErrorInfo?.StackTrace is IEnumerable <XmlNode> stackTraceNodes)
                {
                    foreach (var stackTraceNode in stackTraceNodes)
                    {
                        if (!string.IsNullOrEmpty(stackTraceNode.Value))
                        {
                            errorStackTrace += $"{stackTraceNode.Value}";
                        }
                    }
                }

                if (output.StdOut is IEnumerable <XmlNode> stdOutNodes)
                {
                    foreach (var stdOutNode in stdOutNodes)
                    {
                        if (!string.IsNullOrEmpty(stdOutNode.Value))
                        {
                            messages.Add(new TestResultMessageDrop {
                                Text = stdOutNode.Value, Category = TestResultMessage.StandardOutCategory
                            });
                        }
                    }
                }

                if (output.StdErr is IEnumerable <XmlNode> stdErrNodes)
                {
                    foreach (var stdErrNode in stdErrNodes)
                    {
                        if (!string.IsNullOrEmpty(stdErrNode.Value))
                        {
                            messages.Add(new TestResultMessageDrop {
                                Text = stdErrNode.Value, Category = TestResultMessage.StandardErrorCategory
                            });
                        }
                    }
                }
            }

            drop.Messages        = messages;
            drop.ErrorMessage    = errorMessage;
            drop.ErrorStackTrace = errorStackTrace;
        }
        /// <summary>
        /// Maps result types from JUnit into instance of drop models with configuration
        /// </summary>
        /// <param name="source">Instance of test results from deserialised JUnit input</param>
        /// <param name="destination">Instance to map and merge results into</param>
        /// <param name="inputConfiguration">User configured input for current source</param>
        public static void Map(Testsuites source, TestRunDrop destination, ReportInput inputConfiguration = null)
        {
            foreach (var testsuite in source.Testsuite)
            {
                var started  = DateTimeOffset.Parse(testsuite.Timestamp);
                var finished = started + TimeSpan.FromMilliseconds(double.Parse(testsuite.Time));

                if (destination.Started is null || destination.Started > started)
                {
                    destination.Started = started;
                }
                if (destination.Finished is null || destination.Finished < finished)
                {
                    destination.Finished = finished;
                }

                var key = inputConfiguration?.GroupTitle ?? testsuite.Package;

                foreach (var testCase in testsuite.Testcase)
                {
                    TestResultSetDrop drop;

                    if (destination.ResultSets.TryGetValue(key, out var existingDrop))
                    {
                        drop = existingDrop;
                    }
                    else
                    {
                        drop = new TestResultSetDrop
                        {
                            Source  = key,
                            Results = new List <TestResultDrop>(),
                        };
                        destination.ResultSets.Add(drop);
                    }


                    var testCaseDrop = new TestCaseDrop
                    {
                        Source             = testsuite.Package,
                        DisplayName        = string.IsNullOrEmpty(inputConfiguration?.TestSuffix) ? testCase.Name : $"{testCase.Name}{inputConfiguration.TestSuffix}",
                        FullyQualifiedName = $"{testCase.Classname}.{testCase.Classname}",
                        Id          = null,
                        ExecutorUri = null,
                    };
                    var duration   = TimeSpan.FromMilliseconds(double.Parse(testCase.Time));
                    var outcome    = MapOutcome(testCase, drop, destination.TestRunStatistics);
                    var resultDrop = new TestResultDrop
                    {
                        StartTime      = null,
                        EndTime        = null,
                        Duration       = duration,
                        Outcome        = outcome,
                        TestCase       = testCaseDrop,
                        ComputerName   = testsuite.Hostname,
                        AttachmentSets = null,
                        DisplayName    = testCase.Name
                    };
                    MapOutputToResult(testCase, resultDrop);
                    destination.TestRunStatistics.ExecutedTestsCount++;
                    destination.ElapsedTimeInRunningTests += duration;
                    drop.Duration += duration;
                    drop.ExecutedTestsCount++;
                    drop.Results.Add(resultDrop);
                }
            }
        }