/// <summary>
        /// Returns Errors found during tests. By default only fatal errors are considered
        /// </summary>
        public override IEnumerable <string> GetErrors()
        {
            List <string> AllErrors = new List <string>(base.GetErrors());

            foreach (var Artifact in GetArtifactsWithFailures())
            {
                if (Artifact.SessionRole.RoleType == UnrealTargetRole.Editor)
                {
                    AutomationLogParser Parser = new AutomationLogParser(Artifact.LogParser);
                    AllErrors.AddRange(
                        Parser.GetResults().Where(R => !R.Passed)
                        .SelectMany(R => R.Events
                                    .Where(E => E.ToLower().Contains("error"))
                                    )
                        );
                }
            }

            return(AllErrors);
        }
        /// <summary>
        /// Override the summary report so we can insert a link to our report and the failed tests
        /// </summary>
        /// <returns></returns>
        protected override string GetTestSummaryHeader()
        {
            MarkdownBuilder MB = new MarkdownBuilder(base.GetTestSummaryHeader());

            string ReportLink = GetConfiguration().ReportOutputURL;

            if (string.IsNullOrEmpty(ReportLink) == false)
            {
                MB.Paragraph(string.Format("Report: {0}", ReportLink));
            }

            var EditorArtifacts = SessionArtifacts.Where(A => A.SessionRole.RoleType == UnrealTargetRole.Editor).FirstOrDefault();

            if (EditorArtifacts != null)
            {
                AutomationLogParser Parser = new AutomationLogParser(EditorArtifacts.LogParser);

                IEnumerable <AutomationTestResult> AllTests    = Parser.GetResults();
                IEnumerable <AutomationTestResult> FailedTests = AllTests.Where(R => !R.Passed);

                MB.Paragraph(string.Format("{0} of {1} tests passed", AllTests.Count() - FailedTests.Count(), AllTests.Count()));

                if (FailedTests.Count() > 0)
                {
                    MB.H3("Test Failures");

                    foreach (AutomationTestResult Result in FailedTests)
                    {
                        MB.H4(string.Format("{0} Failed", Result.DisplayName));
                        MB.UnorderedList(Result.Events);
                    }
                }
            }

            return(MB.ToString());
        }
        protected override int GetExitCodeAndReason(UnrealRoleArtifacts InArtifacts, out string ExitReason)
        {
            int ExitCode = base.GetExitCodeAndReason(InArtifacts, out ExitReason);

            if (InArtifacts.SessionRole.RoleType == UnrealTargetRole.Editor)
            {
                // if no fatal errors, check test results
                if (InArtifacts.LogParser.GetFatalError() == null)
                {
                    AutomationLogParser Parser = new AutomationLogParser(InArtifacts.LogParser);

                    IEnumerable <AutomationTestResult> TotalTests  = Parser.GetResults();
                    IEnumerable <AutomationTestResult> FailedTests = TotalTests.Where(R => !R.Passed);

                    if (FailedTests.Any())
                    {
                        ExitReason = string.Format("{0} of {1} tests failed", FailedTests.Count(), TotalTests.Count());
                        ExitCode   = -1;
                    }
                }
            }

            return(ExitCode);
        }