Scripted GUI Testing with Ruby

Scripted GUI Testing with Ruby

I used Winspy++ to explore the control ID of locknote, the ID of the IDOK = 1, IDCANCEL = 2, IDYES = 6, IDNO = 7. But when I used Winspy++ to explore the control ID of Notepad that comes with Windows, with change when close, the confirm dialog box has 3 buttons: Save, Don’t save, and Cancel; all of them have a control ID = 0. How come? How do make click on Don’t save?

UIAVerify (a tool similar to WinSpy++) reveals that those buttons have WPF-style Automation IDs (e.g., @CommandButton_6@) instead of numeric control IDs–even though Notepad and presumably the common dialogs are still native code.

There are a few approaches to finding and clicking this button, including:
* Find the button by caption (“Don’t Save” or “Do&n’t Save”) instead of control ID. This will be fragile in the face of changes to the text of the control.
* Teach Ruby to read the Automation ID of a control; the C APIs available to Ruby will not make this easy.
* Port the test script to IronRuby, and use the Windows UI Automation API to locate the control by its Automation ID.

For quick experimentation, the first option is the path of least resistance.

I don’t have any specific plans to do so. Though capture/replay tools can be useful for one-time scripts needed to replicate a specific error condition, I haven’t had as much luck with them in producing test cases for long-term use.

From the 3 options you gave to finding and clicking a button, I managed to make the second option working, but I am still struggling with the first. However, all 3 options required to know something about the control and use that information to dig further, and that something can be changed in the future. That’s not really bad, because any change without notice means something new breaks the test, either a new bug or an unannounced change in the GUI.

I agree that the more permanent of a control’s properties we can rely on in our tests (control ID, automation ID), the less fragile our tests will be. There are a few times when this is not possible and we have to fall back on potentially-changing properties such as caption, keyboard shortcut, or even position. Fortunately, we can isolate this fragile detail in its own method, so that we need only fix one location in our code when the app changes.

While I am quite comfortable with the guides in your book how to cruise among the main window, the children windows and the dialogs and the control ID of the buttons, I haven’t found any similar tutorials how to deal with the automation ID using the Win32api and Ruby; the Ironruby hasn’t provided any documentation or sample codes. There are some references on C# and UI Automation, but they don’t relate to Ruby.

The UI Automation API comes in a couple of different flavors. The one emphasized by Microsoft is the .NET API, which as you point out is not easy to use from regular (non-Iron) Ruby. But it might be tractable to write a small command-line @.exe@ in C# to find a window by Automation ID, and call this @.exe@ from your Ruby script. If you go this route, the Microsoft article on Using UI Automation for Automated Testing has some information that might be useful. The source code to UIA Verify may have some good examples as well.

The other approach would be to wrap the COM version of the API in Ruby. This would be slightly more difficult, since Ruby’s Win32OLE library only supports @IDispatch@ interfaces–which UI Automation does not implement. It might be doable by calling COM functions like @CoCreateInstance@ just like any other Windows API function.