Win32-Autogui

A Win32 GUI testing framework packaged as a RubyGem.

Overview

Win32-autogui provides a framework to enable GUI application testing with Ruby. This facilitates integration testing of Windows binaries using Ruby based tools like RSpec and Cucumber. Examples of using both these tools are provided with this gem.

Quick Start

See examples/skeleton/README.markdown for a template of the file structure needed for jump-starting GUI testing with the Win32-autogui RubyGem.

Read our introduction blog posting here: http://www.gearheadforhire.com/articles/ruby/win32-autogui/using-ruby-to-drive-windows-applications

Example Usage: Driving Calc.exe

Using RSpec to test drive the stock Window's calculator application. This example is used as Win32-autogui's internal spec. See spec/auto_gui/application_spec.rb.

A more complete example of testing a Window's Delphi program is presented with source and binaries in examples/quicknote/.

Wrap the application to be tested

The first step is to subclass Win32-autogui's application class.

require 'win32/autogui'

class Calculator < Autogui::Application

  # initialize with the binary name 'calc' and the window title
  # 'Calculator' used along with the application pid to find the 
  # main application window
  def initialize(options = {})
    defaults = {
                 :name => "calc",
                 :title => "Calculator"
               }
    super defaults.merge(options)
  end

  # the calculator's results window 
  def edit_window
    main_window.children.find {|w| w.window_class == 'Edit'}
  end

  # About dialog, hotkey (VK_MENU, VK_H, VK_A)
  def dialog_about
    Autogui::EnumerateDesktopWindows.new.find do |w| 
      w.title.match(/About Calculator/) && (w.pid == pid)
    end
  end

  # the 'CE' button
  def clear_entry
    keystroke(VK_DELETE)
  end

end

Write specs

The following RSpec code describes driving the Windows calculator for testing. Multiple instances running simultaneously are supported. See "should control focus with set_focus."

require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')

include Autogui::Input

describe Autogui::Application do

  describe "driving calc.exe" do

    before(:all) do
      @calculator = Calculator.new
    end

    after(:all) do
      @calculator.close(:wait_for_close => true) if @calculator.running?
      @calculator.should_not be_running
    end

    it "should start when initialized" do
      @calculator.should be_running
    end

    it "should have the title 'Calculator' that matches the main_window title" do
      @calculator.main_window.title.should == 'Calculator'
      @calculator.main_window.title.should == @calculator.title
    end

    it "should have an inspect method showing child window information" do
      @calculator.inspect.should match(/children=</)
    end

    it "should calculate '2+2=4' using the keystroke method" do
      @calculator.set_focus
      keystroke(VK_2, VK_ADD, VK_2, VK_RETURN) 
      @calculator.edit_window.text.strip.should == "4."
    end

    it "should calculate '2+12=14' using the type_in method" do
      @calculator.set_focus
      type_in("2+12=")
      @calculator.edit_window.text.strip.should == "14."
    end

    it "should control the focus with 'set_focus'" do
      @calculator.set_focus
      keystroke(VK_9)
      @calculator.edit_window.text.strip.should == "9."

      calculator2 = Calculator.new
      calculator2.pid.should_not == @calculator.pid
      calculator2.set_focus
      keystroke(VK_1, VK_0) 
      calculator2.edit_window.text.strip.should == "10."

      @calculator.set_focus
      @calculator.edit_window.text.strip.should == "9."

      calculator2.close(:wait_for_close => true)
    end

    it "should open and close the 'About Calculator' dialog via (VK_MENU, VK_H, VK_A)" do
      @calculator.set_focus
      dialog_about = @calculator.dialog_about
      dialog_about.should be_nil
      keystroke(VK_MENU, VK_H, VK_A) 
      dialog_about = @calculator.dialog_about
      dialog_about.title.should == "About Calculator"
      dialog_about.combined_text.should match(/Microsoft . Calculator/)
      dialog_about.close
      @calculator.dialog_about.should be_nil
    end

    describe "clipboard" do
      before(:each) do
        @calculator.clear_entry
        @calculator.clipboard.text = ""
        @calculator.clipboard.text.should == ""
      end

      describe "copy (VK_CONTROL, VK_C)" do
        it "should copy the edit window" do
          @calculator.set_focus
          type_in("3002")
          @calculator.edit_window.text.strip.should == "3,002."
          @calculator.edit_window.set_focus
          keystroke(VK_CONTROL, VK_C) 
          @calculator.clipboard.text.should == "3002"
        end
      end

      describe "paste (VK_CONTROL, VK_V)" do
        it "should paste into the edit window" do
          @calculator.edit_window.set_focus
          @calculator.clipboard.text = "12345"
          @calculator.edit_window.text.strip.should == "0."
          keystroke(VK_CONTROL, VK_V) 
          @calculator.edit_window.text.strip.should == "12,345."
        end
      end

    end

  end
end

System Requirements

Windows OS, version 2000 or higher, testing was done via Cygwin http://www.cygwin.com/

Dependencies

Win32-autogui depends on the following RubyGems

Installation

Win32-autogui is available on RubyGems.org

gem install win32-autogui

References and Alternative Libraries

Development

Win32-autogui development was jump-started by cloning BasicGem.

Dependencies

Rake tasks

rake -T

rake build         # Build win32-autogui-0.0.1.gem into the pkg directory
rake doc:clean     # Remove generated documenation
rake doc:generate  # Generate YARD Documentation
rake features      # Run Cucumber features
rake install       # Build and install win32-autogui-0.0.1.gem into system gems
rake release       # Create tag v0.0.1 and build and push win32-autogui-0.0.1.gem to Rubygems
rake spec          # Run specs
rake test          # Run specs and features

Autotesting with Watchr

Watchr provides a flexible alternative to Autotest. A jump start script is provided in spec/watchr.rb.

Install watchr

gem install watchr

Run watchr

watchr spec/watchr.rb

outputs a menu

Ctrl-\ for menu, Ctrl-C to quit

Watchr will now watch the files defined in 'spec/watchr.rb' and run RSpec or Cucumber, as appropriate. The watchr script provides a simple menu.

Ctrl-\

MENU: a = all , f = features  s = specs, l = last feature (none), q = quit

Copyright (c) 2010 GearheadForHire, LLC. See LICENSE for details.