Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CodedUI: Why is searching for a cell so slow?

I've got a grid (FlexGrid, from ComponentOne) in a Winform application and I'm trying to find a cell in that grid, given the cell's column index and its value.

I've written the extension method below to loop through the grid and find that cell.

I'm testing that method on a grid that has 6 columns and 64 rows. It took 10 minutes for my code to find the correct cell (which was on the last row)

Is there any way I can speed up my algorithm ?

Note: I've also tried setting PlayBack.PlayBackSetting.SmartMatchOption to TopLevelWindow, but it does not seem to change anything...

Thanks!

    public static WinCell FindCellByColumnAndValue(this WinTable table, int colIndex, string strCellValue)
    {

        int count = table.GetChildren().Count;
        for (int rowIndex = 0; rowIndex < count; rowIndex++)
        {
            WinRow row = new WinRow(table);
            WinCell cell = new WinCell(row);
            row.SearchProperties.Add(WinRow.PropertyNames.RowIndex, rowIndex.ToString());
            cell.SearchProperties.Add(WinCell.PropertyNames.ColumnIndex, colIndex.ToString());

            cell.SearchProperties.Add(WinCell.PropertyNames.Value, strCellValue);
            if (cell.Exists)
                return cell;
        }

        return new WinCell();
    }

Edit

I modified my method to be like below(e.g. I don't use winrow anymore), this seems to be around 3x faster. It still needs 7 sec to find a cell in a table with 3 rows and 6 columns though, so it's still quite slow...

I'll mark this answer as accepted later, to leave time to other people to suggest something better

    public static WinCell FindCellByColumnAndValue(this WinTable table, int colIndex, string strCellValue, bool searchHeader = false)
    {
        Playback.PlaybackSettings.SmartMatchOptions = Microsoft.VisualStudio.TestTools.UITest.Extension.SmartMatchOptions.None;   
        int count = table.GetChildren().Count;
        for (int rowIndex = 0; rowIndex < count; rowIndex++)
        {
            WinCell cell = new WinCell(table);

            cell.SearchProperties.Add(WinRow.PropertyNames.RowIndex, rowIndex.ToString());
            cell.SearchProperties.Add(WinCell.PropertyNames.ColumnIndex, colIndex.ToString());


            cell.SearchProperties.Add(WinCell.PropertyNames.Value, strCellValue);
            if (cell.Exists)
                return cell;
        }

        return new WinCell();
    }

Edit #2: I've tried using FindMatchingControls as per @Andrii's suggestion, and I'm nearly there, except that in the code below the cell's column index (c.ColumnIndex) has the wrong value..

    public static WinCell FindCellByColumnAndValue2(this WinTable table, int colIndex, string strCellValue, bool searchHeader = false)
    {

        WinRow row = new WinRow(table);
        //Filter rows containing the wanted value
        row.SearchProperties.Add(new PropertyExpression(WinRow.PropertyNames.Value, strCellValue, PropertyExpressionOperator.Contains));
        var rows = row.FindMatchingControls();
        foreach (var r in rows)
        {
            WinCell cell = new WinCell(r);
            cell.SearchProperties.Add(WinCell.PropertyNames.Value, strCellValue);
            //Filter cells with the wanted value in the current row
            var controls = cell.FindMatchingControls();
            foreach (var ctl in controls)
            {
                var c = ctl as WinCell;
                if (c.ColumnIndex == colIndex)//ERROR: The only cell in my table with the correct value returns a column index of 2, instead of 0 (being in the first cell)
                    return c;
            }
        }
        return new WinCell();
    }
like image 854
David Avatar asked Jan 31 '12 09:01

David


1 Answers

I would suggest to perform direct looping through child controls - according to my experience searching controls with complicated search crieteria in Coded UI often works slow.

Edit:

To improve performance it is better to remove counting table's children and looping through rows. Also to avoid exception when finding control without row number you can use FindMatchingControls method, like in following:

    public static WinCell FindCellByColumnAndValue(this WinTable table, int colIndex, string strCellValue, bool searchHeader = false)
    {
        Playback.PlaybackSettings.SmartMatchOptions = Microsoft.VisualStudio.TestTools.UITest.Extension.SmartMatchOptions.None;

        WinCell cell = new WinCell(table);
        cell.SearchProperties.Add(WinCell.PropertyNames.ColumnIndex, colIndex.ToString());
        cell.SearchProperties.Add(WinCell.PropertyNames.Value, strCellValue);

        UITestControlCollection foundControls = cell.FindMatchingControls();
        if (foundControls.Count > 0)
        {
            cell = foundControls.List[0];
        }
        else
        {
            cell = null;
        }

        return cell;
    }

When table field will be searched directly in the table it will save time for counting child controls in table. Also searching without for loop will save time for search of field for each iteration of row number that does not match.

As row number is iterated through all available values in your extension - it is not essential search criterion in the long run. In same time each iteration through a row number value invokes additional control search request - eventually multiplying method's execution time by the number of rows in grid.

like image 54
Andrii Kalytiiuk Avatar answered Oct 07 '22 00:10

Andrii Kalytiiuk