private static string EnvironmentToBugMarkdown(RhinoTestCase testCase) { try { // setup var driverParams = JObject.Parse(System.Text.Json.JsonSerializer.Serialize(testCase.Context[ContextEntry.DriverParams])); // setup conditions var isWebApp = testCase.Steps.First().Command == ActionType.GoToUrl; var isCapabilites = driverParams.ContainsKey("capabilities"); var isMobApp = !isWebApp && isCapabilites && driverParams.SelectToken("capabilities.app") != null; // get application var onTestCase = testCase.Context.ContainsKey("decomposedTestCase") ? (RhinoTestCase)testCase.Context["decomposedTestCase"] : testCase; // get application return(isMobApp ? $"{driverParams.SelectToken("capabilities.app")}" : ((ActionRule)onTestCase.Steps.First(i => i.Command == ActionType.GoToUrl).Context[ContextEntry.StepAction]).Argument.Replace(@"""", @"\""")); } catch (Exception e) when(e != null) { return(string.Empty); } }
/// <summary> /// Set XRay runtime ids on all steps under this RhinoTestCase. /// </summary> /// <param name="testCase">RhinoTestCase on which to update runtime ids.</param> /// <param name="testExecutionKey">Jira test execution key by which to find runtime ids.</param> public static void SetRuntimeKeys(this RhinoTestCase testCase, string testExecutionKey) { // setup var ravenClient = new JiraCommandsExecutor(testCase.GetAuthentication()); var command = RavenCommandsRepository.GetTestRunExecutionDetails(testExecutionKey, testCase.Key); // send var response = ravenClient.SendCommand(command).AsJToken(); // exit conditions if ($"{response["id"]}".Equals("-1")) { return; } // setup var jsonToken = response["steps"]; var stepsToken = JArray.Parse($"{jsonToken}"); var stepsCount = testCase.Steps.Count(); // apply runtime id to test-step context for (int i = 0; i < stepsCount; i++) { testCase.Steps.ElementAt(i).Context["runtimeid"] = stepsToken[i]["id"].ToObject <long>(); testCase.Steps.ElementAt(i).Context["testStep"] = JToken.Parse($"{stepsToken[i]}"); } // apply test run key int.TryParse($"{response["id"]}", out int idOut); testCase.Context["runtimeid"] = idOut; testCase.Context["testRunKey"] = testExecutionKey; }
private static IEnumerable <IDictionary <string, object> > GetSteps(RhinoTestCase testCase) { var steps = new List <IDictionary <string, object> >(); for (int i = 0; i < testCase.Steps.Count(); i++) { // setup conditions var isAction = !string.IsNullOrEmpty(testCase.Steps.ElementAt(i).Action); if (!isAction) { continue; } var onStep = testCase.Steps.ElementAt(i); var step = new Dictionary <string, object> { ["id"] = i + 1, ["index"] = i + 1, ["fields"] = new Dictionary <string, object> { ["Action"] = onStep.Action.Replace("{", "{{").Replace("}", "}}"), ["Expected Result"] = string.IsNullOrEmpty(onStep.Expected) ? string.Empty : onStep.Expected.Replace("{", "{{").Replace("}", "}}") } }; // add to steps list steps.Add(step); } return(steps); }
/// <summary> /// Converts test management test case interface into a RhinoTestCase. /// </summary> /// <param name="testCase">Test case token (from Jira response) to convert.</param> /// <returns>RhinoTestCase object.</returns> public static RhinoTestCase ToRhinoTestCase(this JToken testCase) { // initialize test case instance & fetch issues var onTestCase = new RhinoTestCase(); // apply context onTestCase.Context ??= new Dictionary <string, object>(); onTestCase.Context[nameof(testCase)] = $"{testCase}"; // fields: setup var priority = GetPriority(testCase); // fields: values onTestCase.Priority = string.IsNullOrEmpty(priority) ? onTestCase.Priority : priority; onTestCase.Key = $"{testCase["key"]}"; onTestCase.Scenario = $"{testCase.SelectToken("fields.summary")}"; onTestCase.Link = $"{testCase["self"]}"; // initialize test steps collection var testSteps = testCase.SelectToken("..steps"); var parsedSteps = new List <RhinoTestStep>(); // iterate test steps & normalize action/expected foreach (var testStep in testSteps.Children()) { var parsedStep = ParseStep(testStep); parsedSteps.Add(parsedStep); } // apply to connector test steps onTestCase.Steps = parsedSteps; return(onTestCase); }
/// <summary> /// Converts RhinoTestCase to create test issue request. /// </summary> /// <param name="testCase">Test case to convert.</param> /// <returns>Create test issue request.</returns> public static string ToJiraCreateRequest(this RhinoTestCase testCase) { // exit conditions Validate(testCase, "issuetype-id", "project-key"); // field: steps > description var description = testCase.Context.ContainsKey("description") ? testCase.Context["description"] : string.Empty; // compose json var requestBody = new Dictionary <string, object> { ["summary"] = testCase.Scenario, ["description"] = description, ["issuetype"] = new Dictionary <string, object> { ["id"] = $"{testCase.Context["issuetype-id"]}" }, ["project"] = new Dictionary <string, object> { ["key"] = $"{testCase.Context["project-key"]}" } }; return(JsonConvert.SerializeObject(new Dictionary <string, object> { ["fields"] = requestBody })); }
/// <summary> /// Performed just after each test is called. /// </summary> /// <param name="testCase">The Rhino.Api.Contracts.AutomationProvider.RhinoTestCase which was executed.</param> /// <remarks>Use this method for PostTestExecute customization.</remarks> public override RhinoTestCase OnPostTestExecute(RhinoTestCase testCase) { // exit conditions if (Configuration.ConnectorConfiguration.DryRun) { return(testCase); } // build steps var customSteps = GetCustomSteps(testCase); // save results var defect = GetDefect(testCase); var result = GetResult(testCase, customSteps); // add results var results = resultsClient.AddResultForCase(int.Parse(testCase.TestRunKey), int.Parse(testCase.Key), result); AddAttachments(results.Id, testCase); if (!string.IsNullOrEmpty(defect)) { AddToCaseRefs(testCase, defect); } // get return(testCase); }
private TestRailResult GetResult(RhinoTestCase testCase, IEnumerable <CustomStep> customSteps) { var elapsed = testCase.End - testCase.Start; var test = testsClient.GetTests(int.Parse(testCase.TestRunKey)).FirstOrDefault(i => i.CaseId == int.Parse(testCase.Key)); var isFaild = testCase.Steps.Any(i => !i.Actual); var status = isFaild ? 5 : 1; if (testCase.Inconclusive) { status = 4; } // save results var defect = GetDefect(testCase); var result = new TestRailResult { AssignedTo = test.AssignedTo, Version = $"{DateTime.Now:yyyyMMdd.fff}", Elapsed = $"{elapsed.Hours}h {elapsed.Minutes}m {elapsed.Seconds}s", StatusId = status, CustomStepResults = customSteps.ToArray(), Comment = $"iteration {testCase.Iteration}" }; if (!string.IsNullOrEmpty(defect)) { result.Defects = defect; } // get return(result); }
/// <summary> /// Performed just after each test is called. /// </summary> /// <param name="testCase">The Rhino.Api.Contracts.AutomationProvider.RhinoTestCase which was executed.</param> public override RhinoTestCase OnPostTestExecute(RhinoTestCase testCase) { // constants const string Updated = "runUpdated"; // setup var outcome = testCase.Actual ? "PASSED" : "FAILED"; var alreadyFail = ProviderManager .TestRun .TestCases .Any(i => i.Key == testCase.Key && !i.Actual && i.Context.ContainsKey(Updated) && (bool)i.Context[Updated]); // failed on this run (mark as fail) if (alreadyFail) { outcome = "FAILED"; } // inconclusive on this run (mark as default) if (ProviderManager.TestRun.TestCases.Any(i => i.Key.Equals(testCase.Key) && i.Inconclusive)) { outcome = testCase.GetCapability(AtlassianCapabilities.InconclusiveStatus, "TODO"); } // put testCase.Context["outcome"] = outcome; // update ProviderManager.UpdateTestResult(testCase); // return with results return(testCase); }
/// <summary> /// Upload evidences into an existing test execution. /// </summary> /// <param name="testCase">RhinoTestCase by and into which to upload evidences.</param> public static RhinoTestCase SetEvidences(this RhinoTestCase testCase) { try { // setup var forUploadOutcomes = new[] { "PASSED", "FAILED" }; // exit conditions if (!forUploadOutcomes.Contains($"{testCase.Context["outcome"]}".ToUpper())) { return(testCase); } // setup var testRun = (testCase.Context["testRun"] as JToken).AsJObject(); var id = $"{testRun.SelectToken("id")}"; var key = $"{testRun.SelectToken("key")}"; var options = new ParallelOptions { MaxDegreeOfParallelism = 4 }; // send var client = new XpandClient(testCase.GetAuthentication()); Parallel.ForEach(GetEvidence(testCase), options, evidenceData => { var evidences = evidenceData["evidences"] as List <string>; evidences ??= new List <string>(); Parallel.ForEach(evidences, options, evidence => client.CreateEvidence((id, key), $"{evidenceData["testRun"]}", $"{evidenceData["step"]}", evidence)); }); }
private static void DoSetOutcomeByRun(RhinoTestCase testCase, string outcome) { // setup var executor = new JiraCommandsExecutor(testCase.GetAuthentication()); // send var response = RavenCommandsRepository.GetTestStauses().Send(executor).AsJToken(); // extract status var status = response.FirstOrDefault(i => $"{i.SelectToken("name")}".Equals(outcome, Compare)); // exit conditions if (status == default) { return; } // exit conditions if (!int.TryParse($"{status["id"]}", out int outcomeOut)) { return; } // send RavenCommandsRepository.SetTestExecuteResult(testCase.TestRunKey, testCase.Key, outcomeOut).Send(executor); }
/// <summary> /// Gets a comment text for failed test case which includes meta data information. /// </summary> /// <param name="testCase">RhinoTestCase to get comment for.</param> /// <returns>Jira markdown fail comment.</returns> public static string GetFailComment(this RhinoTestCase testCase) { // setup var failedSteps = testCase.Steps.Where(i => !i.Actual).Select(i => ((JToken)i.Context["testStep"])["index"]); // exit conditions if (!failedSteps.Any()) { return(string.Empty); } // setup var environment = testCase.MarkdownEnvironment(); var platform = testCase.MarkdownPlatform(); var dataSource = testCase.MarkdownDataSource(); // build var header = "----\r\n" + $"*{DateTime.UtcNow} UTC* \r\n" + $"*Failed On Iteration:* {testCase.Iteration}\r\n" + $"*On Steps:* {string.Join(", ", failedSteps)}\r\n" + $"*On Application:* {environment}\r\n"; var body = (platform + dataSource) .Replace("\\r\\n", "\n") .Replace(@"\""", "\"") .Replace("----\r\n", string.Empty); // return return(header + body); }
private static void ValidationXray(RhinoTestCase testCase) { Validate(testCase.Context, "issuetype-id"); Validate(testCase.Context, "project-key"); Validate(testCase.Context, "manual-test-steps-custom-field"); Validate(testCase.Context, "test-sets-custom-field"); }
/// <summary> /// Creates a new test case under the specified automation provider. /// </summary> /// <param name="testCase">Rhino.Api.Contracts.AutomationProvider.RhinoTestCase by which to create automation provider test case.</param> /// <returns>The ID of the newly created entity.</returns> public override string CreateTestCase(RhinoTestCase testCase) { // shortcuts var onProject = Configuration.ConnectorConfiguration.Project; testCase.Context[ContextEntry.Configuration] = Configuration; var testType = $"{testCase.GetCapability(AtlassianCapabilities.TestType, "Test")}"; // setup context testCase.Context["issuetype-id"] = $"{jiraClient.GetIssueTypeFields(idOrKey: testType, path: "id")}"; testCase.Context["project-key"] = onProject; testCase.Context["test-sets-custom-field"] = jiraClient.GetCustomField(schema: TestSetSchema); testCase.Context["manual-test-steps-custom-field"] = jiraClient.GetCustomField(schema: ManualTestStepSchema); testCase.Context["test-plan-custom-field"] = jiraClient.GetCustomField(schema: AssociatedPlanSchema); // setup request body var requestBody = testCase.ToJiraXrayIssue(); var issue = jiraClient.Create(requestBody); // comment var comment = Utilities.GetActionSignature(action: "created"); jiraClient.AddComment(idOrKey: $"{issue.SelectToken("key")}", comment); // success Logger?.InfoFormat($"Create-Test -Project [{onProject}] -Set [{string.Join(",", testCase?.TestSuites)}] = true"); // results return($"{issue}"); }
private static object GetUpdateBugPayload(RhinoTestCase testCase, JToken onBug, JiraClient jiraClient) { // setup var comment = $"{RhinoUtilities.GetActionSignature("updated")} " + $"Bug status on execution [{testCase.TestRunKey}] is *{onBug.SelectToken("fields.status.name")}*."; // verify if bug is already open var template = testCase.BugMarkdown(jiraClient); var description = $"{JToken.Parse(template).SelectToken("fields.description")}"; // setup return(new { Update = new { Comment = new[] { new { Add = new { Body = comment } } } }, Fields = new { Description = description } }); }
private IEnumerable <JToken> DoGetBugs(RhinoTestCase testCase) { // shortcuts var bugType = testCase.GetCapability(AtlassianCapabilities.BugType, "Bug"); const string typePath = "fields.issuetype.name"; const string statusPath = "fields.status.name"; // get test issue var test = client.Get(testCase.Key).AsJObject(); // get bugs var bugsKeys = test .SelectTokens("..inwardIssue") .Where(i => $"{i.SelectToken(typePath)}"?.Equals(bugType) == true && $"{i.SelectToken(statusPath)}"?.Equals("Closed") != true) .Select(i => $"{i["key"]}") .ToArray(); // add to context testCase.Context["bugs"] = bugsKeys; // get issues var bugs = client.Get(bugsKeys); testCase.Context["bugsData"] = bugs; // get return(bugs); }
private IEnumerable <string> DoCloseBugs(RhinoTestCase testCase, string status, string resolution, IEnumerable <string> labels, IEnumerable <string> bugs) { // close bugs var closedBugs = new List <string>(); foreach (var bug in bugs) { var isClosed = testCase.CloseBug(bugIssueKey: bug, status, resolution, labels, client); // logs if (isClosed) { closedBugs.Add($"{Utilities.GetUrl(client.Authentication.Collection)}/browse/{bug}"); continue; } logger?.Info($"Close-Bug -Bug [{bug}] -Test [{testCase.Key}] = false"); } // context if (!testCase.Context.ContainsKey(ContextEntry.BugClosed) || !(testCase.Context[ContextEntry.BugClosed] is IEnumerable <string>)) { testCase.Context[ContextEntry.BugClosed] = new List <string>(); } var onBugsClosed = (testCase.Context[ContextEntry.BugClosed] as IEnumerable <string>).ToList(); onBugsClosed.AddRange(closedBugs); testCase.Context[ContextEntry.BugClosed] = onBugsClosed; // get return(onBugsClosed); }
/// <summary> /// Close all existing bugs. /// </summary> /// <param name="testCase">Rhino.Api.Contracts.AutomationProvider.RhinoTestCase by which to close automation provider bugs.</param> public string OnCloseBug(RhinoTestCase testCase, string status, string resolution) { // get existing bugs var isBugs = testCase.Context.ContainsKey("bugs") && testCase.Context["bugs"] != default; var contextBugs = isBugs ? (IEnumerable <string>)testCase.Context["bugs"] : Array.Empty <string>(); var bugs = client .Get(idsOrKeys: contextBugs) .Where(i => testCase.IsBugMatch(bug: i, assertDataSource: false)); // get conditions (double check for bugs) if (!bugs.Any()) { return(string.Empty); } // close bugs: first var onBug = $"{bugs.FirstOrDefault()?.SelectToken("key")}"; testCase.CloseBug(bugIssueKey: onBug, status, resolution, client); // close bugs: duplicate (if any) foreach (var bug in bugs.Skip(1)) { var labels = new[] { "Duplicate" }; testCase.CloseBug( $"{bug.SelectToken("key")}", status, resolution: !string.IsNullOrEmpty(resolution) ? "Duplicate" : string.Empty, labels, client); } return(onBug); }
private static bool AssertOptions(RhinoTestCase testCase, string onBug) { // setup var driverParams = (IDictionary <string, object>)testCase.Context[ContextEntry.DriverParams]; // extract test capabilities var tstOptions = driverParams.ContainsKey("options") ? System.Text.Json.JsonSerializer.Serialize(driverParams["options"]).ToUpper().Sort() : string.Empty; if (tstOptions.Equals("{}")) { tstOptions = string.Empty; } // extract bug capabilities var onBugOptions = Regex.Match(input: onBug, pattern: @"(?<=Options\W+\\r\\n\{code:json}).*?(?=\{code})").Value; onBugOptions = onBugOptions.Replace("\\r", string.Empty).Replace("\\n", string.Empty).Replace(@"\", string.Empty); var bugOptions = string.IsNullOrEmpty(onBugOptions) ? string.Empty : onBugOptions; // deserialize if (!string.IsNullOrEmpty(bugOptions)) { var bugOptionsObjt = JsonConvert.DeserializeObject <object>(bugOptions); bugOptions = JsonConvert.SerializeObject(bugOptionsObjt, Formatting.None).ToUpper().Sort(); } // assert return(tstOptions.Equals(bugOptions, Compare)); }
/// <summary> /// Set XRay test execution results of test case by setting steps outcome. /// </summary> /// <param name="testCase">RhinoTestCase by which to update XRay results.</param> /// <returns>-1 if failed to update, 0 for success.</returns> /// <remarks>Must contain runtimeid field in the context.</remarks> public static void SetOutcomeBySteps(this RhinoTestCase testCase) { // get steps // add exceptions images - if exists or relevant if (testCase.Context.ContainsKey(ContextEntry.OrbitResponse)) { testCase.AddExceptionsScreenshot(); } // collect steps var steps = new List <object>(); foreach (var testStep in testCase.Steps) { steps.Add(testStep.GetUpdateRequest(outcome: $"{testCase.Context["outcome"]}")); } // setup var executor = new JiraCommandsExecutor(testCase.GetAuthentication()); var command = RavenCommandsRepository.UpdateTestRun( testRun: $"{testCase.Context["runtimeid"]}", data: new { Steps = steps }); // send executor.SendCommand(command); }
/// <summary> /// Close all existing bugs. /// </summary> /// <param name="testCase">Rhino.Api.Contracts.AutomationProvider.RhinoTestCase by which to close automation provider bugs.</param> public IEnumerable <string> OnCloseBugs(RhinoTestCase testCase, string status, string resolution, IEnumerable <string> bugs) { // set existing bugs testCase.Context["bugs"] = bugs; // close bugs return(DoCloseBugs(testCase, status, resolution, Array.Empty <string>(), bugs)); }
/// <summary> /// Close all existing bugs. /// </summary> /// <param name="testCase">Rhino.Api.Contracts.AutomationProvider.RhinoTestCase by which to close automation provider bugs.</param> public IEnumerable <string> OnCloseBugs(RhinoTestCase testCase, string status, string resolution) { // get existing bugs var bugs = DoGetBugs(testCase).Select(i => $"{i.SelectToken("key")}").Where(i => !string.IsNullOrEmpty(i)); // close bugs return(DoCloseBugs(testCase, status, resolution, Array.Empty <string>(), bugs)); }
private static bool AssertCapabilities(RhinoTestCase testCase, string onBug) { // constants const string Capabliites = "capabilities"; try { // setup var driverParams = (IDictionary <string, object>)testCase.Context[ContextEntry.DriverParams]; // extract test capabilities var tstCapabilities = string.Empty; if (driverParams.ContainsKey(Capabliites) && driverParams[Capabliites] != null) { var jsonCapabilities = System.Text.Json.JsonSerializer.Serialize(driverParams[Capabliites]); var objCapabilities = System.Text.Json.JsonSerializer.Deserialize <IDictionary <string, object> >(jsonCapabilities); tstCapabilities = objCapabilities.ToJiraMarkdown(); } // normalize to markdown var onTstCapabilities = Regex.Split(string.IsNullOrEmpty(tstCapabilities) ? string.Empty : tstCapabilities, @"\\r\\n"); tstCapabilities = string.Join(Environment.NewLine, onTstCapabilities); tstCapabilities = tstCapabilities.Substring(0, tstCapabilities.LastIndexOf('|') + 1); // extract bug capabilities var bugCapabilities = Regex.Match( input: onBug, pattern: @"(?<=Capabilities\W+\\r\\n\|\|).*(?=\|.*Local Data Source)|(?<=Capabilities\W+\\r\\n\|\|).*(?=\|)").Value; // normalize to markdown var onBugCapabilities = Regex.Split(string.IsNullOrEmpty(bugCapabilities) ? string.Empty : "||" + bugCapabilities + "|", @"\\r\\n"); bugCapabilities = string.Join(Environment.NewLine, onBugCapabilities); bugCapabilities = bugCapabilities.Substring(0, bugCapabilities.LastIndexOf('|') + 1); // exit conditions var isBugCapabilities = !string.IsNullOrEmpty(bugCapabilities); var isTstCapabilities = !string.IsNullOrEmpty(tstCapabilities); if (isBugCapabilities ^ isTstCapabilities) { return(false); } else if (!isBugCapabilities && !isTstCapabilities) { return(true); } // convert to data table and than to dictionary collection var compareableBugCapabilites = new DataTable().FromMarkDown(bugCapabilities).ToDictionary().ToJson().ToUpper().Sort(); var compareableTstCapabilites = new DataTable().FromMarkDown(tstCapabilities).ToDictionary().ToJson().ToUpper().Sort(); // assert return(compareableBugCapabilites.Equals(compareableTstCapabilites, Compare)); } catch (Exception e) when(e != null) { return(false); } }
private string DoCreateBug(RhinoTestCase testCase) { // get bug response var response = testCase.CreateBug(client); // results return(response == default ? "-1" : $"{Utilities.GetUrl(client.Authentication.Collection)}/browse/{response["key"]}"); }
private string GetExecution(RhinoTestCase testCase) { // exit conditions if (!testCase.Context.ContainsKey("runtimeid")) { return(string.Empty); } // get return($"{testCase.Context["runtimeid"]}"); }
/// <summary> /// Creates a bug based on this RhinoTestCase. /// </summary> /// <param name="testCase">RhinoTestCase by which to create a bug.</param> /// <returns>Bug creation results from Jira.</returns> public static JToken CreateBug(this RhinoTestCase testCase, JiraClient jiraClient) { // setup var issueBody = testCase.BugMarkdown(jiraClient); // post var response = jiraClient.Create(issueBody); if (response == default) { return(default);
/// <summary> /// Creates a new bug under the specified automation provider. /// </summary> /// <param name="testCase">Rhino.Api.Contracts.AutomationProvider.RhinoTestCase by which to create automation provider bug.</param> /// <returns>The ID of the newly created entity.</returns> public string OnCreateBug(RhinoTestCase testCase) { // exit conditions if (testCase.Actual) { return(string.Empty); } // create bug return(DoCreateBug(testCase)); }
/// <summary> /// Performed just before each test is called. /// </summary> /// <param name="testCase">The Rhino.Api.Contracts.AutomationProvider.RhinoTestCase which is being executed.</param> public override RhinoTestCase OnPreTestExecute(RhinoTestCase testCase) { // setup testCase.Context["outcome"] = "EXECUTING"; // update ProviderManager.UpdateTestResult(testCase); // return with results return(testCase); }
/// <summary> /// Updates test results comment. /// </summary> /// <param name="testCase">RhinoTestCase by which to update test results.</param> public static void UpdateResultComment(this RhinoTestCase testCase, string comment) { // setup var executor = new JiraCommandsExecutor(testCase.GetAuthentication()); var command = RavenCommandsRepository.UpdateTestRun( testRun: $"{testCase.Context["runtimeid"]}", data: new { Comment = comment }); // send executor.SendCommand(command); }
private void AddAttachments(int resultId, RhinoTestCase testCase) { // setup var files = testCase.GetScreenshots(); var bucketSize = Configuration.GetCapability(ProviderCapability.BucketSize, 4); var options = new ParallelOptions { MaxDegreeOfParallelism = bucketSize }; // add attachments Parallel.ForEach(files, options, file => attachmentsClient.AddAttachmentToResult(resultId, fileToUpload: file)); }
// UTILITIES private void DoUpdateTestResult(RhinoTestCase testCase, bool inline) { // constants const string Aggregated = "aggregated"; try { // setup var forUploadOutcomes = new[] { "PASS", "FAIL" }; var onTestCase = testCase.AggregateSteps(); onTestCase.Context.AddRange(testCase.Context, exclude: new[] { Aggregated }); // exit conditions var outcome = "TODO"; if (onTestCase.Context.ContainsKey("outcome")) { outcome = $"{testCase.Context["outcome"]}"; } // update if (inline) { testCase.SetOutcomeBySteps(); testCase.SetOutcomeByRun(); return; } testCase.SetOutcomeBySteps(); onTestCase = testCase.AggregateSteps(); // attachments if (forUploadOutcomes.Contains(outcome.ToUpper())) { onTestCase.UploadEvidences(); } // fail message if (outcome.Equals("FAIL", Compare) || testCase.Steps.Any(i => i.Exception != default)) { var comment = testCase.GetFailComment(); testCase.UpdateResultComment(comment); } // put testCase.Context[Aggregated] = onTestCase; } catch (Exception e) when(e != null) { logger?.Error($"Update-TestResult -Test [{testCase.Key}] -Inline [{inline}] = false", e); } }