bewildr icon indicating copy to clipboard operation
bewildr copied to clipboard

Test WPF UI apps with IronRuby

=bewildr Test WPF UI apps with IronRuby!

Written by Nat Ritmeyer (http://www.natontesting.com)

==Intro Documentation is on the way; until then, take a look at the tests or read the API overview below.

==Getting started ===Dependencies

  1. Install .net 3 and 4 (http://www.microsoft.com/downloads/details.aspx?FamilyID=10cc340b-f857-4a14-83f5-25634c3bf043&displaylang=en & http://msdn.microsoft.com/en-us/netframework/aa569263.aspx)
  2. Install the latest ironruby (http://ironruby.codeplex.com/), and for your own sanity install it in c:\\ironruby instead of the default location.
  3. You'll need at least rubygems version 1.3.6: gem update --system

===Installation

gem install bewildr --no-rdoc --no-ri

To use bewildr:

require 'bewildr'

==API Overview ===Application Management Start an app

@app = Bewildr::Application.start('notepad') @app = Bewildr::Application.start('c:/windows/notepad.exe')

Start an app and wait for a particular window:

@app, @window = Bewildr::Application.start_app_and_wait_for_window('notepad', 'Untitled - Notepad')

or (taking a regex for the window title instead of a string - tests become more robust):

@app, @window = Bewildr::Application.start_app_and_wait_for_window('c:/windows/notepad.exe', /.* - Notepad/)

Kill an app

@app.kill @app.running? == false @app.should_not be_running

===Window Management Get application windows:

All windows belonging to an app:

@all_windows_for_my_app = @app.windows

Window with a particular name:

@main_window = @app.window('My App 1.0')

Window with a particular name (find window using regex instead of string):

@main_window = @app.window(/My App .*/)

===Basic Element Interaction

Find an element by its automation id:

my_button = @window.get(:id => 'my_button')

Find an element by its type:

@all_buttons = @window.get(:type => :button)

Find an element by its name:

my_button = @window.get(:name => 'Click Here')

Find an element by a combination of criteria:

@main_window.get(:type => :hyperlink, :name => "Link Text")

Click a button:

@window.get(:id => 'my_button').click

===Element State

Check for existence/enabled state of an element:

@window.get(:id => 'some_element').exists? @window.get(:id => 'some_element').enabled?

...which allows for some nice idiomatic test code if you're using rspec:

@window.get(:id => 'some_element').should_not exist @window.get(:id => 'some_element').should be_enabled

Wait for an element to exist:

@window.wait_for_existence_of(:id => "an_object")

Wait for an element to disappear:

@window.wait_for_non_existence_of(:id => "an_object")

The wait_for_existence_of method can be called recursively:

@window.wait_for_existence_of(:id => "an_object").wait_for_existence_of(:id => "child_object")

The line above will result in waiting for 'an_object', and once it has appeared it'll wait for an object below it in the object hierarchy called 'child_object'.

==Background story I've recently being testing a WPF app. I wrote some classes to wrap the White automation library (http://white.codeplex.com/) using IronRuby to allow the WPF app tests to be written in ruby - the same language as the tests for the other systems. Due to some performance issues and a number of bugs, I ended up rewriting large chunks of the functionality of white by directly talking to the MS Automation API (http://msdn.microsoft.com/en-us/library/ms747327(v=VS.100).aspx). After a while it occured to me... "why not write a library from scratch that tests WPF apps, that's fast and allows for idiomatic tests due to a clean API?"

Enter 'Bewildr'.