public override void Body() { ActualResult = TestCaseResult.Failed; Stopwatch watch = new Stopwatch(); string lastException = string.Empty; watch.Start(); while (watch.ElapsedMilliseconds < timeout + 10) { try { UIControlBase c = UIControlBase.FindControlByPath(control, _logControlSearch); if (c.Exists) { ActualResult = TestCaseResult.Passed; return; } } catch (Exception ex) { lastException = ex.ToString(); } } LogFailedByExpectedResult("Control not found after " + timeout + " milliseconds", control); if (lastException != string.Empty) { Log.Warning("Exception caught", lastException, EntryVerbosity.Debug); } }
public override void Body() { ActualResult = QAliber.RemotingModel.TestCaseResult.Failed; UIControlBase c = UIControlBase.FindControlByPath(control); if (!c.Exists) { ActualResult = QAliber.RemotingModel.TestCaseResult.Failed; Log.Error("Control not found"); return; } IScrollItemPattern pattern = c.GetControlInterface <IScrollItemPattern>(); if (pattern != null && _scrollIntoView) { pattern.ScrollIntoView(); } LowLevelInput.PressKeys(_modifierKeys); c.Click(button, point); LowLevelInput.ReleaseKeys(_modifierKeys); ActualResult = QAliber.RemotingModel.TestCaseResult.Passed; }
private static string GetText(string control, bool logErrors) { UIControlBase c = UIControlBase.FindControlByPath(control); if (c == null || !c.Exists) { if (logErrors) { Log.Error("Control not found"); } return(null); } IText text = c.GetControlInterface <IText>(); if (text == null) { // TODO: Add support for HTML controls (or REALLY do generic implementations on the interfaces) if (logErrors) { Log.Error("Couldn't find an appropriate way to get text from the control."); } return(null); } return(text.Text); }
public override void Body() { ActualResult = QAliber.RemotingModel.TestCaseResult.Failed; _resultTable = null; UIControlBase c = UIControlBase.FindControlByPath(_control); if (c == null || !c.Exists) { Log.Error("Control not found", _control); return; } IGridPattern grid = c.GetControlInterface <IGridPattern>(); if (grid == null) { Log.Error("Couldn't find an appropriate way to get at grid data."); return; } string[] headers; string[][] rows = grid.CaptureGrid(out headers); if (headers != null && headers.Distinct().Count() != headers.Length) { Log.Error("Duplicate column names", "Could not produce an output table because there are two columns with the same name."); return; } DataTable table = new DataTable("Captured grid"); if (headers != null) { foreach (string header in headers) { table.Columns.Add(XPath.EscapeLiteral(header), typeof(string)); } } else { int columnCount = grid.ColumnCount; for (int i = 0; i < columnCount; i++) { table.Columns.Add("Column " + i.ToString(CultureInfo.CurrentUICulture), typeof(string)); } } foreach (string[] row in rows) { table.Rows.Add(row.Select(cell => cell ?? string.Empty).Select(XPath.EscapeLiteral).ToArray()); } _resultTable = table; ActualResult = QAliber.RemotingModel.TestCaseResult.Passed; }
public static string[] CaptureList(string control, bool logErrors) { // Capture the list UIControlBase c = UIControlBase.FindControlByPath(control); if (c == null || !c.Exists) { if (logErrors) { Log.Error("Control not found", control); } return(null); } IListPattern list = c.GetControlInterface <IListPattern>(); if (list != null) { return(list.CaptureList()); } ISelector selector = c.GetControlInterface <ISelector>(); if (selector != null) { return(selector.Items); } // Try one control up; we could be on the combo box's edit or button controls c = c.Parent; if (c != null) { list = c.GetControlInterface <IListPattern>(); if (list != null) { return(list.CaptureList()); } selector = c.GetControlInterface <ISelector>(); if (selector != null) { return(selector.Items); } } if (logErrors) { Log.Error("Couldn't find a way to read the list."); } return(null); }
public override void Body() { ActualResult = QAliber.RemotingModel.TestCaseResult.Passed; UIControlBase c = UIControlBase.FindControlByPath(control); if (!c.Exists) { ActualResult = QAliber.RemotingModel.TestCaseResult.Failed; throw new InvalidOperationException("Control not found"); } IWindowPattern window = c.GetControlInterface <IWindowPattern>(); if (window == null) { ActualResult = QAliber.RemotingModel.TestCaseResult.Failed; throw new InvalidOperationException("Control doesn't appear to be a window"); } switch (opType) { case WindowOperationType.Close: window.Close(); break; case WindowOperationType.Maximize: if (!window.CanMaximize) { Log.Error("Window does not support maximizing.", string.Empty, EntryVerbosity.Internal); return; } window.SetState(WindowVisualState.Maximized); break; case WindowOperationType.Minimize: if (!window.CanMinimize) { Log.Error("Window does not support maximizing.", string.Empty, EntryVerbosity.Internal); return; } window.SetState(WindowVisualState.Minimized); break; case WindowOperationType.Restore: window.SetState(WindowVisualState.Normal); break; case WindowOperationType.SetFocus: window.SetState(WindowVisualState.Normal); c.SetFocus(); break; } }
public override void Body() { ActualResult = QAliber.RemotingModel.TestCaseResult.Passed; UIControlBase c = UIControlBase.FindControlByPath(control); if (!c.Exists) { ActualResult = QAliber.RemotingModel.TestCaseResult.Failed; throw new InvalidOperationException("Control not found"); } c.GetImage().Save(file); }
public override void Body() { ActualResult = TestCaseResult.Failed; Stopwatch watch = new Stopwatch(); string lastException = null; UIControlBase c = null; watch.Start(); while (watch.ElapsedMilliseconds < _timeout + 10) { try { c = UIControlBase.FindControlByPath(_control); if (c.Exists) { break; } } catch (Exception ex) { lastException = ex.ToString(); } } if (c == null || !c.Exists) { Log.Error("Control not found after " + _timeout + " milliseconds", _control); if (lastException != null) { Log.Warning("Exception caught", lastException, EntryVerbosity.Debug); } return; } UIAControl uia = c as UIAControl; if (uia != null && uia.XPathElementName == "titlebar") { // Go with the parent c = uia.Parent; } c.SetFocus(); ActualResult = TestCaseResult.Passed; }
public override void Body() { ActualResult = QAliber.RemotingModel.TestCaseResult.Passed; UIControlBase c = UIControlBase.FindControlByPath(control); if (!c.Exists) { ActualResult = QAliber.RemotingModel.TestCaseResult.Failed; throw new InvalidOperationException("Control not found"); } Bitmap image = c.GetImage(); Log.Image(image, logDescription); }
public override void Body() { try { UIControlBase c = UIControlBase.FindControlByPath(control); if (!c.Exists) { ActualResult = QAliber.RemotingModel.TestCaseResult.Failed; throw new InvalidOperationException("Control not found"); } ISelector selectorPattern = c.GetControlInterface <ISelector>(); if (selectorPattern != null) { listItems = selectorPattern.Items; ActualResult = QAliber.RemotingModel.TestCaseResult.Passed; } else if (c is HTMLSelect) { HTMLOption[] ops = ((HTMLSelect)c).Options; listItems = new string[ops.Length]; for (int idx = 0; idx < ops.Length; idx++) { listItems[idx] = ops[idx].Text; } ActualResult = QAliber.RemotingModel.TestCaseResult.Passed; } else { ActualResult = QAliber.RemotingModel.TestCaseResult.Failed; throw new InvalidOperationException("Control is not list type control"); } } catch (Exception ex) { ActualResult = QAliber.RemotingModel.TestCaseResult.Failed; throw ex; } }
public override void Body() { ActualResult = QAliber.RemotingModel.TestCaseResult.Passed; try { UIControlBase c = UIControlBase.FindControlByPath(control); if (!c.Exists) { ActualResult = QAliber.RemotingModel.TestCaseResult.Failed; throw new InvalidOperationException("Control not found"); } c.MoveMouseTo(point); } catch (System.Reflection.TargetInvocationException) { ActualResult = QAliber.RemotingModel.TestCaseResult.Failed; } }
public override void Body() { ActualResult = TestCaseResult.Failed; UIControlBase c = UIControlBase.FindControlByPath(_control); if (!c.Exists) { Log.Error("Control not found"); return; } if (!c.Enabled) { Log.Error("Control not enabled"); return; } ITogglePattern toggle = c.GetControlInterface <ITogglePattern>(); if (toggle != null) { ToggleState currentState = toggle.ToggleState; if (currentState != _state) { LogFailedByExpectedResult("Did not match", string.Format("The control's state was \"{0}\" instead of \"{1}\".", currentState, _state)); return; } ActualResult = QAliber.RemotingModel.TestCaseResult.Passed; } else { Log.Error("The target control doesn't support toggle operations."); return; } }
public override void Body() { ActualResult = QAliber.RemotingModel.TestCaseResult.Passed; UIControlBase c = UIControlBase.FindControlByPath(control); if (!c.Exists) { ActualResult = QAliber.RemotingModel.TestCaseResult.Failed; throw new InvalidOperationException("Control not found"); } ITransformPattern transform = c.GetControlInterface <ITransformPattern>(); if (transform == null) { ActualResult = QAliber.RemotingModel.TestCaseResult.Failed; throw new InvalidOperationException("Control doesn't appear to be a window"); } transform.Move(point.X, point.Y); }
public override void Body() { ActualResult = QAliber.RemotingModel.TestCaseResult.Passed; text = string.Empty; UIControlBase c = UIControlBase.FindControlByPath(control); if (!c.Exists) { Logger.Log.Error("Couldn't find control", control); ActualResult = RemotingModel.TestCaseResult.Failed; return; } IText textPattern = c.GetControlInterface <IText>(); if (textPattern != null) { text = textPattern.Text; Logger.Log.Info("Found text property", text); return; } if (c is QAliber.Engine.Controls.Web.WebControl) { text = ((QAliber.Engine.Controls.Web.WebControl)c).InnerText; Logger.Log.Info("Found inner text property of web control", text); return; } Logger.Log.Info("Couldn't find a text property, trying to do optical character recognition"); OCRItem ocrItem = new OCRItem(c.GetImage()); text = ocrItem.ProcessImage(); Logger.Log.Info("OCR result = " + text); }
public override void Body() { try { UIControlBase c = UIControlBase.FindControlByPath(control); if (!c.Exists) { ActualResult = QAliber.RemotingModel.TestCaseResult.Failed; throw new InvalidOperationException("Control not found"); } ISelector selectorPattern = c.GetControlInterface <ISelector>(); if (selectorPattern != null) { selectorPattern.Select(index); ActualResult = QAliber.RemotingModel.TestCaseResult.Passed; } else if (c is HTMLSelect) { ((HTMLSelect)c).SelectItem(index); ActualResult = QAliber.RemotingModel.TestCaseResult.Passed; } else { ActualResult = QAliber.RemotingModel.TestCaseResult.Failed; throw new InvalidOperationException("Control is not list type control"); } } catch (Exception ex) { ActualResult = QAliber.RemotingModel.TestCaseResult.Failed; throw ex; } }
public override void Body() { ActualResult = QAliber.RemotingModel.TestCaseResult.Failed; UIControlBase c = UIControlBase.FindControlByPath(control); if (!c.Exists) { Log.Error("Start control not found."); return; } IScrollItemPattern pattern = c.GetControlInterface <IScrollItemPattern>(); if (pattern != null && _scrollIntoView) { pattern.ScrollIntoView(); } if (!c.Visible) { Log.Error("Start control not visible."); return; } Point point2 = _point2; if (!string.IsNullOrEmpty(_endControl)) { UIControlBase endControl = UIControlBase.FindControlByPath(_endControl); if (!endControl.Exists) { Log.Error("End control not found."); return; } pattern = endControl.GetControlInterface <IScrollItemPattern>(); if (pattern != null && _scrollIntoView) { pattern.ScrollIntoView(); } if (!endControl.Visible) { Log.Error("End control not visible."); return; } // Figure out end coordinate relative to begin coord Vector offset = endControl.Layout.TopLeft - c.Layout.TopLeft; point2 += offset; } LowLevelInput.PressKeys(_modifierKeys); c.Drag(button, point1, point2); LowLevelInput.ReleaseKeys(_modifierKeys); ActualResult = TestCaseResult.Passed; }
public override void Body() { ActualResult = QAliber.RemotingModel.TestCaseResult.Passed; UIControlBase c = UIControlBase.FindControlByPath(control); if (!c.Exists) { ActualResult = QAliber.RemotingModel.TestCaseResult.Failed; throw new InvalidOperationException("Control not found"); } List <string> values = new List <string>(); foreach (string item in _list) { switch (item) { case "Layout.X": values.Add(c.Layout.X.ToString()); break; case "Layout.Y": values.Add(c.Layout.Y.ToString()); break; case "Layout.Width": values.Add(c.Layout.Width.ToString()); break; case "Layout.Height": values.Add(c.Layout.Height.ToString()); break; case "Name": values.Add(c.Name); break; case "ClassName": values.Add(c.ClassName); break; case "ID": values.Add(c.ID); break; case "Enabled": values.Add(c.Enabled.ToString()); break; case "Visible": values.Add(c.Visible.ToString()); break; default: values.Add("(unknown property)"); break; } } vals = string.Join(",", values); }
public override void Body() { ActualResult = QAliber.RemotingModel.TestCaseResult.Failed; _foundValue = string.Empty; // Build the regex if we have one Regex regex = null; if (_useRegex) { regex = new Regex(_expectedValue, RegexOptions.Singleline | (_caseSensitive ? RegexOptions.None : RegexOptions.IgnoreCase)); } // Find the control UIControlBase c = UIControlBase.FindControlByPath(_control); if (c == null || !c.Exists) { ActualResult = QAliber.RemotingModel.TestCaseResult.Failed; Log.Error("Control not found", "Could not find control " + _control); return; } // Find the property PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(c); PropertyDescriptor prop = properties.Find(_property, false); Log.Info("Properties found were...", "Properties found were: " + string.Join(", ", properties.Cast <PropertyDescriptor>().Select(p => p.Name))); if (prop == null) { ActualResult = QAliber.RemotingModel.TestCaseResult.Failed; Log.Warning(_property + " property not found", "Could not find property " + _property + " on control " + _control); return; } // Read the value _foundValue = Convert.ToString(prop.GetValue(c), CultureInfo.CurrentCulture); Log.Info("Found value: \"" + _foundValue + "\""); // Verify it if (regex != null) { if (!regex.IsMatch(_foundValue)) { ActualResult = QAliber.RemotingModel.TestCaseResult.Failed; throw new ArgumentException("The property's value didn't match the regular expression."); } } else if (_caseSensitive && _foundValue != _expectedValue) { ActualResult = QAliber.RemotingModel.TestCaseResult.Failed; throw new ArgumentException("The property's value didn't match the specified text."); } else if (!_caseSensitive && StringComparer.CurrentCultureIgnoreCase.Compare(_foundValue, _expectedValue) != 0) { ActualResult = QAliber.RemotingModel.TestCaseResult.Failed; throw new ArgumentException("The property's value didn't match the specified text."); } ActualResult = QAliber.RemotingModel.TestCaseResult.Passed; }
public override void Body() { ActualResult = TestCaseResult.Failed; UIControlBase c = UIControlBase.FindControlByPath(_control); if (!c.Exists) { Log.Error("Control not found"); return; } if (!c.Enabled) { Log.Error("Control not enabled"); return; } ITogglePattern toggle = c.GetControlInterface <ITogglePattern>(); IInvokePattern invoke = c.GetControlInterface <IInvokePattern>(); HTMLInput input = c as HTMLInput; if (toggle != null) { switch (_action) { case ToggleAction.On: for (int i = 0; i < 3; i++) { if (toggle.ToggleState != ToggleState.On) { toggle.Toggle(); } } if (toggle.ToggleState != ToggleState.On) { Log.Error("Tried three times, but couldn't set the checkbox to On."); return; } break; case ToggleAction.Off: for (int i = 0; i < 3; i++) { if (toggle.ToggleState != ToggleState.Off) { toggle.Toggle(); } } if (toggle.ToggleState != ToggleState.Off) { Log.Error("Tried three times, but couldn't set the checkbox to Off."); return; } break; case ToggleAction.Toggle: toggle.Toggle(); break; } ActualResult = QAliber.RemotingModel.TestCaseResult.Passed; } else if (invoke != null) { if (_action != ToggleAction.Toggle) { Log.Error("The target control only supports invoke operations. Try toggle action instead."); return; } switch (_action) { case ToggleAction.On: case ToggleAction.Off: Log.Error("The target control only supports invoke operations. Try toggle action instead."); return; case ToggleAction.Toggle: invoke.Invoke(); break; } ActualResult = TestCaseResult.Passed; } else if (input != null) { switch (_action) { case ToggleAction.Toggle: input.Click(); break; case ToggleAction.On: if (!input.Checked) { input.Click(); } break; case ToggleAction.Off: if (input.Checked) { input.Click(); } break; } ActualResult = TestCaseResult.Passed; } else { Log.Error("Couldn't find an appropriate way to toggle the control."); ActualResult = TestCaseResult.Failed; } }
public override void Body() { ActualResult = QAliber.RemotingModel.TestCaseResult.Failed; _resultTable = null; // Get the variable we're testing against ScenarioVariable <DataTable> testTableVar = Scenario.Tables[_variable]; if (testTableVar == null) { Log.Error("Could not find variable \"" + _variable + "\""); return; } // Filter the test table down to what the user wants us to find DataTable testTable = testTableVar.Value.Clone(); if (_verifyRows.Length == 0) { // Grab all rows testTable.Merge(testTableVar.Value); } else { foreach (int rowIndex in _verifyRows) { if (rowIndex >= testTableVar.Value.Rows.Count) { Log.Error("Verify Rows refers to an invalid row", "The Verify Rows property refers to a row that's not in the source table."); return; } testTable.Rows.Add(testTableVar.Value.Rows[rowIndex].ItemArray); } } if (_verifyColumns.Length != 0) { HashSet <string> verifyColumns = new HashSet <string>(_verifyColumns); string[] verifyColumnsNotFound = verifyColumns.Except(testTable.Columns.Cast <DataColumn>().Select(col => col.ColumnName)).ToArray(); if (verifyColumnsNotFound.Length != 0) { Log.Error("Verify Columns refers to an invalid column", "The Verify Columns property refers to one or more invalid columns: " + string.Join(", ", verifyColumnsNotFound)); return; } foreach (DataColumn column in testTable.Columns.Cast <DataColumn>().ToArray()) { if (!verifyColumns.Contains(column.ColumnName)) { testTable.Columns.Remove(column); } } } // Capture the grid UIControlBase c = UIControlBase.FindControlByPath(_control); if (c == null || !c.Exists) { Log.Error("Control not found", _control); return; } IGridPattern grid = c.GetControlInterface <IGridPattern>(); if (grid == null) { Log.Error("Can't capture grid", "Couldn't find an appropriate way to get at grid data."); return; } string[] headers; string[][] rows = grid.CaptureGrid(out headers); if (_requireHeaders && headers == null) { LogFailedByExpectedResult("No headers in target grid", "Target grid didn't have any headers, and Require Headers was set."); return; } bool columnsUnique = true; if (headers != null && headers.Distinct().Count() != headers.Length) { columnsUnique = false; Log.Warning("Duplicate column names", "Could not produce an output table because there are two columns with the same name."); } // Create the grid result table if (columnsUnique) { DataTable table = new DataTable("Captured grid"); if (headers != null) { headers = Array.ConvertAll(headers, header => XPath.EscapeLiteral(header)); foreach (string header in headers) { table.Columns.Add(header, typeof(string)); } } else { int columnCount = grid.ColumnCount; for (int i = 0; i < columnCount; i++) { table.Columns.Add("Column " + i.ToString(CultureInfo.CurrentUICulture), typeof(string)); } } rows = Array.ConvertAll(rows, row => Array.ConvertAll(row, cell => XPath.EscapeLiteral(cell ?? string.Empty))); foreach (string[] row in rows) { table.Rows.Add(row); } _resultTable = table; } // Go ahead and log the capture string rowText = string.Join("\r\n", rows.Select(row => "[" + string.Join(", ", row) + "]")); if (headers != null) { rowText = "[" + string.Join(", ", headers) + "]\r\n" + rowText; } Log.Info("Captured grid", rowText); // Shortcut out on some special cases if (rows.Length < testTable.Rows.Count) { LogFailedByExpectedResult("Not enough rows in target grid", string.Format("Target grid had {0} rows, expected at least {1}.", rows.Length, testTable.Rows.Count)); return; } if (!_allowExtraRows && rows.Length > testTable.Rows.Count) { LogFailedByExpectedResult("Too many rows in target grid", string.Format("Target grid had {0} rows, expected {1}.", rows.Length, testTable.Rows.Count)); return; } if (rows.Length != 0) { if (rows[0].Length < testTable.Columns.Count) { LogFailedByExpectedResult("Not enough columns in target grid", string.Format("Target grid had {0} columns, expected at least {1}.", rows[0].Length, testTable.Columns.Count)); return; } if (!_allowExtraColumns && rows[0].Length > testTable.Columns.Count) { LogFailedByExpectedResult("Too many columns in target grid", string.Format("Target grid had {0} columns, expected {1}.", rows[0].Length, testTable.Columns.Count)); return; } } // Filter out any columns we don't care about if (headers != null) { // Filter by column name List <string> testColumns = testTable.Columns.Cast <DataColumn>() .Select(col => col.ColumnName).ToList(); int[] keptColumns = new int[testColumns.Count]; for (int index = 0; index < headers.Length; index++) { int foundIndex = testColumns.IndexOf(headers[index]); if (foundIndex != -1) { testColumns[foundIndex] = null; keptColumns[foundIndex] = index; } else if (!_allowExtraColumns) { LogFailedByExpectedResult("Found extra column \"" + headers[index] + "\" in grid", string.Empty); return; } } // keptColumns as created will reorder the columns into the expected order; // if the user wants us to verify the column order as well, we have to re-sort // into the original order as found in the target grid if (_verifyColumnOrder) { Array.Sort <int>(keptColumns); } headers = keptColumns.Select(i => headers[i]).ToArray(); rows = rows.Select(row => keptColumns.Select(i => row[i]).ToArray()).ToArray(); } // Finally, verify rows if (_verifyRowOrder) { List <HashedRow> extraRows = new List <HashedRow>(); HashedRow[] targetRows = rows.Select(row => new HashedRow(row)).ToArray(); var testRows = testTable.Rows.Cast <DataRow>() .Select(row => new HashedRow(row.ItemArray.Cast <string>().ToArray())); int targetRowIndex = 0; foreach (var testRow in testRows) { // We must find this row in the target to proceed bool matched = false; int expectedPosition = targetRowIndex; while (targetRowIndex < targetRows.Length) { if (targetRows[targetRowIndex].Equals(testRow)) { // Row found, stop here targetRowIndex++; matched = true; break; } // Target row which does not match extraRows.Add(targetRows[targetRowIndex]); targetRowIndex++; } if (matched) { continue; } // Made it to the end of the target rows without finding it if (extraRows.Contains(testRow)) { LogFailedByExpectedResult("Row in wrong place", "This row was in the wrong position while \"Verify Row Order\" was on: [" + string.Join(", ", testRow) + "]\r\n\r\nIt was expected at or after row " + (expectedPosition + 1).ToString() + "."); } else { LogFailedByExpectedResult("Expected row missing", "Could not find this row in the target grid: [" + string.Join(", ", testRow) + "]\r\n\r\nIt was expected at or after row " + (expectedPosition + 1).ToString() + "."); if (extraRows.Count != 0 && !_allowExtraRows) { LogFailedByExpectedResult("Found extra row(s)", "Found these rows in the target grid while \"Allow Extra Rows\" was off:\r\n\r\n" + string.Join("\r\n", extraRows.Select(row => "[" + string.Join(", ", row) + "]"))); } } return; } if (extraRows.Count != 0 && !_allowExtraRows) { LogFailedByExpectedResult("Found extra row(s)", "Found these rows in the target grid while \"Allow Extra Rows\" was off:\r\n\r\n" + string.Join("\r\n", extraRows.Select(row => "[" + string.Join(", ", row) + "]"))); return; } } else { // Unordered find; make sure there are the right number of each kind of row List <HashedRow> missingRows = new List <HashedRow>(); List <HashedRow> targetRows = rows.Select(row => new HashedRow(row)).ToList(); var testRows = testTable.Rows.Cast <DataRow>() .Select(row => new HashedRow(row.ItemArray.Cast <string>().ToArray())); foreach (var testRow in testRows) { int index = targetRows.IndexOf(testRow); if (index == -1) { missingRows.Add(testRow); } else { targetRows.RemoveAt(index); } } if (missingRows.Count != 0) { LogFailedByExpectedResult("Expected row(s) missing", "These rows were expected but not found in the target grid:\r\n\r\n" + string.Join("\r\n", missingRows.Select(row => "[" + string.Join(", ", row) + "]"))); return; } // Make sure there are none left if we aren't supposed to allow extra rows if (!_allowExtraRows && targetRows.Count != 0) { LogFailedByExpectedResult("Found extra row(s)", "Found these rows in the target grid while \"Allow Extra Rows\" was off:\r\n\r\n" + string.Join("\r\n", targetRows.Select(row => "[" + string.Join(", ", row) + "]"))); return; } } ActualResult = QAliber.RemotingModel.TestCaseResult.Passed; }