rformunit 0.2.0-x86-mswin32-60

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG ADDED
@@ -0,0 +1,30 @@
1
+ CHANGELOG
2
+ =========
3
+ == 0.2.0 (2007-12-18)
4
+ - add convenient methods in Driver
5
+ - add a commonly used dialog class: open file dialog, save as file dialog
6
+ - add filtered key to support 'Alt+', 'Ctrl+'
7
+
8
+ == 0.1.3 (2007-04-18)
9
+
10
+ New features:
11
+ - Support window with various titles depends on invoking conditions
12
+
13
+ == 0.1.2 (2007-02-26)
14
+
15
+ New features:
16
+ - Add ListView support
17
+ - Add Label support
18
+
19
+ Others:
20
+ - code reformating
21
+
22
+ == 0.1.1 (2006-11-29)
23
+
24
+ New features:
25
+ - replace keyboard.* with RFormUnit::Keyboard.*
26
+ - replace mouse.* with RFormUnit::Mouse.*
27
+ - replace process.* with RFormUnit::Process.*
28
+
29
+
30
+ == 0.1.0 (2006-11-28) initial release
data/MIT-LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ Copyright (c) 2006 Zhimin Zhan, zhimin@zhimin.com
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
data/README ADDED
@@ -0,0 +1,30 @@
1
+ rFormUnit
2
+ =========
3
+
4
+ rFormUnit is a simple framework for automated testing Windows Form applications.
5
+ It wraps AutoItX COM API to provide an alternative way to write an easy to use,
6
+ readable automated functional tests.
7
+
8
+ Dependencies
9
+ ------------
10
+ * Ruby - http://rubyinstaller.rubyforge.org/wiki/wiki.pl (Version verified: ruby185-21.exe)
11
+ * AutoIt3 - http://www.autoitscript.com/autoit3/ (Version verified v3.2.2.0)
12
+
13
+ Platform: MS Windows (of course)
14
+
15
+ Install
16
+ -------
17
+ > gem install rformunit
18
+
19
+ One minute tutorial
20
+ -------------------
21
+
22
+
23
+
24
+ Copyrights
25
+ ----------
26
+ Free to use for any purposes. The software provided AS IS without any warranty whatsoever.
27
+
28
+ Contact
29
+ -------
30
+ Zhimin Zhan, Agileway Pty Ltd.
data/Rakefile ADDED
@@ -0,0 +1,65 @@
1
+ require 'rubygems'
2
+ require 'rake/testtask'
3
+ require 'rake/rdoctask'
4
+
5
+ Gem::manage_gems
6
+ require 'rake/gempackagetask'
7
+
8
+ $:.unshift(File.dirname(__FILE__) + "/lib")
9
+ require 'rformunit'
10
+
11
+ desc "Default task"
12
+ task :default => [ :clean, :test , :gem]
13
+
14
+ desc "Clean generated files"
15
+ task :clean do
16
+ rm_rf 'pkg'
17
+ rm_rf 'docs/rdoc'
18
+ end
19
+
20
+ # run the unit tests
21
+ Rake::TestTask.new("test") { |t|
22
+ t.test_files = FileList['test/test*.rb']
23
+ t.verbose= true
24
+ }
25
+
26
+ # Generate the RDoc documentation
27
+ Rake::RDocTask.new { |rdoc|
28
+ rdoc.rdoc_dir = 'docs/rdoc'
29
+ rdoc.title = 'rformunit'
30
+ rdoc.template = "#{ENV['template']}.rb" if ENV['template']
31
+ rdoc.rdoc_files.include('README')
32
+ rdoc.rdoc_files.include('lib/rformunit.rb')
33
+ rdoc.rdoc_files.include('lib/rformunit/*.rb')
34
+ }
35
+
36
+ spec = Gem::Specification.new do |s|
37
+ s.platform= Gem::Platform::CURRENT
38
+ s.name = "rformunit"
39
+ s.version = "0.2.0"
40
+ s.summary = "An wrap of AUTOIT3 for functional testing of Windows form applications"
41
+ # s.description = ""
42
+
43
+ s.author = "Zhimin Zhan"
44
+ s.email = "zhimin@zhimin.com"
45
+ s.homepage= "http://www.zhimin.com/software/rformunit/"
46
+ # s.rubyforge_project = ""
47
+
48
+ s.has_rdoc = true
49
+ s.requirements << 'none'
50
+ s.require_path = "lib"
51
+ s.autorequire = "rformunit"
52
+
53
+ s.files = [ "Rakefile", "README", "CHANGELOG", "MIT-LICENSE" ]
54
+ # s.files = s.files + Dir.glob( "bin/**/*" ).delete_if { |item| item.include?( "\.svn" ) }
55
+ s.files = s.files + Dir.glob( "ext/**/*" ).delete_if { |item| item.include?( "\.svn" ) }
56
+ s.files = s.files + Dir.glob( "lib/**/*" ).delete_if { |item| item.include?( "\.svn" ) }
57
+ s.files = s.files + Dir.glob( "test/**/*" ).delete_if { |item| item.include?( "\.svn" ) }
58
+ s.files = s.files + Dir.glob( "sample/**/*" ).delete_if { |item| item.include?( "\.svn" ) }
59
+ s.files = s.files + Dir.glob( "docs/**/*" ).delete_if { |item| item.include?( "\.svn" ) }
60
+
61
+ end
62
+
63
+ Rake::GemPackageTask.new(spec) do |pkg|
64
+ pkg.need_zip = true
65
+ end
data/docs/index.html ADDED
@@ -0,0 +1,185 @@
1
+ <html
2
+ <head>
3
+ <title>rFormUnit </title>
4
+ <meta http-equiv="content-type" content="text/html; charset=utf-8" />
5
+ <link href="../../stylesheets/zhimin.css" media="screen" rel="Stylesheet" type="text/css" />
6
+ <link href="../../stylesheets/local.css" media="screen" rel="Stylesheet" type="text/css" />
7
+
8
+ <style type="text/css" media="screen">
9
+ BODY
10
+ {
11
+ BACKGROUND-COLOR: #fffff0;
12
+ COLOR: #000000;
13
+ FONT-FAMILY: "Times New Roman", Times, serif
14
+ }
15
+
16
+ .green {
17
+ background-color: #ECF3E1;
18
+ border:1px solid #C5DEA1;
19
+ }
20
+
21
+ .orange{
22
+ border:1px solid #E8A400;
23
+ background-color: #FFF4D8;
24
+
25
+ </style>
26
+
27
+ </head>
28
+ <body>
29
+
30
+ <h3>What is rFormUnit?</h3>
31
+ <p>rFormUnit is a simple framework for automated testing <b>Windows Form</b> applications. It wraps <a href="http://www.autoitscript.com/autoit3/">AutoItX</a> COM API to provide an alternative way to write an easy to use, readable automated functional tests.
32
+ </p>
33
+
34
+ <p>Current release: 0.1.1<br/>
35
+ &nbsp; <a href="releases/rformunit-0.1.1-mswin32.gem">rformunit-0.1.1-mswin32.gem</a> or from <a href="http://rubyforge.org/projects/rformunit/">rubyforge.org</a>,
36
+
37
+ <!-- &nbsp; <a href="releases/changelog.txt">Change logs</a> <br/> -->
38
+ &nbsp; Documentation: <a href="rdoc/index.html">RDoc</a>, and Quick start guide below.
39
+ </p>
40
+
41
+ <h3>Installation</h3>
42
+
43
+ <p><b>Dependecies</b><br/>
44
+ &nbsp; &nbsp; Install <a href="http://rubyinstaller.rubyforge.org/wiki/wiki.pl">Ruby for windows</a><br/>
45
+ &nbsp; &nbsp; Install <a href="http://www.autoitscript.com/autoit3/">AutoIt3</a></p>
46
+
47
+ <p>Using RubyGems:
48
+ <pre class="green">$ gem install rformunit</pre>
49
+ or download and install locally:
50
+ <pre class="green">$ gem install rformunit-0.1.0-mswin32.gem</pre>
51
+ </p>
52
+
53
+ <h3>Quick start guide through examples</h3>
54
+ <ul>
55
+ <li><a href="#script">Run as automation scripts</a></li>
56
+ <li><a href="#test">Run as xUnit test cases</a></li>
57
+ <li><a href="#rspec">Run as RSpecs</a></li>
58
+ </ul>
59
+ <p>Check sample/*.rb for more examples.</p>
60
+ <a name="script"></a><h4>Run as automation scripts</h4>
61
+ <table width="100%" cellspacing="0" cellpadding="0">
62
+ <tr bgcolor="#33CC33">
63
+ <th align="left" width="50%">AutoIt3 Script</th>
64
+ <th align="left" width="50%">rFormUnit Script</th>
65
+ </tr>
66
+ <tr>
67
+ <td valign="top" nowrap="nowrap" class="orange" width="50%">
68
+ <pre>
69
+
70
+
71
+
72
+ Run("notepad.exe")
73
+ WinWaitActive("Untitled - Notepad")
74
+
75
+ Send("Hello from Notepad.{ENTER}1 2 3{ENTER}")
76
+ Sleep(500)
77
+ Send("+{UP 2}")
78
+ Sleep(500)
79
+
80
+ Send("!f")
81
+ Send("x")
82
+
83
+ WinWaitActive("Notepad", "No")
84
+ Send("n")
85
+
86
+ </pre>
87
+ </td>
88
+
89
+ <td valign="top" nowrap="nowrap" class="green">
90
+ <pre>require 'rformunit'
91
+
92
+ include RFormUnit::Driver
93
+
94
+ RFormUnit::Process.run("NOTEPAD.EXE")
95
+ notepad_win = RFormUnit::Window.new('Untitled - Notepad')
96
+ RFormUnit::Keyboard.type("Hello from Notepad, {ENTER}1 2 3 4 5 6 7 8 9 10{ENTER}")
97
+ sleep(0.5)
98
+ RFormUnit::Keyboard.press("+{UP 2}")
99
+ sleep(0.5)
100
+ notepad_win.close
101
+
102
+ notepad_confirm_dialog = RFormUnit::Window.new('Notepad', 'No')
103
+ notepad_confirm_dialog.click_button('&No')</pre>
104
+ </td>
105
+ </tr>
106
+ </table>
107
+
108
+ <a name="test"></a>
109
+ <div id="rformunit_test">
110
+ <h4>rFormUnit Testcase</h4>
111
+ <pre class="green">require 'rformunit'
112
+
113
+ class CalcTest &lt; RFormUnit::FormTestCase
114
+ def setup
115
+ RFormUnit::Process.run("calc.exe")
116
+ @calc_win = RFormUnit::Window.new('Calculator')
117
+ end
118
+
119
+ def teardown
120
+ @calc_win.close
121
+ end
122
+
123
+ def test_multiple
124
+ @calc_win.click_button('127') #3
125
+ @calc_win.click_button('91') #*
126
+ @calc_win.click_button('131') #7
127
+ @calc_win.click_button('112') #=
128
+ assert_equal "21. ", @calc_win.get_control_text('403')
129
+ end
130
+
131
+ end</pre>
132
+ </div>
133
+
134
+ <a name="rspec"></a><div id='rformunit_rspec'>
135
+ <h4>rFormUnit <a href="http://rspec.rubyforge.org/">RSpec</a></h4>
136
+
137
+ <p><b>rspec_calc</b>: a spec runner to run rformunit based rspecs</p>
138
+ <pre class="green">
139
+ require File.dirname(__FILE__) + '/calc'
140
+
141
+ class RSpecCalc
142
+ include Calc
143
+
144
+ def setup
145
+ init # initialize
146
+ @calc_win = find_existing_calc_win
147
+ if @calc_win.nil?
148
+ @calc_win = start_calc
149
+ end
150
+ end
151
+ end
152
+
153
+ module Spec
154
+ module Runner
155
+ class Context
156
+ def before_context_eval
157
+ inherit RSpecCalc
158
+ end
159
+ end
160
+ end
161
+ end</pre>
162
+
163
+ <p><b>calc_spec</b>: a rspec</p>
164
+ <pre class="green">
165
+ require File.dirname(__FILE__) + '/rspec_calc'
166
+
167
+ context "Calculator" do
168
+
169
+ setup do
170
+ end
171
+
172
+ specify "Multiple shall work" do
173
+ @calc_win.click_button('127') #3
174
+ @calc_win.click_button('91') #*
175
+ @calc_win.click_button('131') #7
176
+ @calc_win.click_button('112') #=
177
+ @calc_win.get_control_text('403').should == '21. '
178
+ end
179
+
180
+ end</pre>
181
+
182
+ </div>
183
+
184
+ </body>
185
+ </html>
@@ -0,0 +1,46 @@
1
+ class RSpecFormUnit
2
+ include YourModule # change to your module containing common methods used in your specs
3
+
4
+ def setup
5
+ @driver = GUIDriver.new()
6
+
7
+ @driver.AutoItSetOption("CaretCoordMode",0);
8
+ @driver.AutoItSetOption("ColorMode",1);
9
+ @driver.AutoItSetOption("MouseCoordMode",0);
10
+ @driver.AutoItSetOption("PixelCoordMode",0);
11
+ @driver.AutoItSetOption("SendKeyDelay", 20)
12
+
13
+ #Add it yourself
14
+
15
+ end
16
+
17
+ def timeout_check_equal(duration, expected, &block)
18
+ execute_ok = false
19
+ duration.times do
20
+ sleep(1)
21
+ text = instance_eval(&block)
22
+ execute_ok = true and break if (text == expected)
23
+ end
24
+ execute_ok.should == true
25
+ end
26
+
27
+ def timeout_check_include?(duration, expected, &block)
28
+ execute_ok = false
29
+ duration.times do
30
+ sleep(1)
31
+ text = instance_eval(&block)
32
+ execute_ok = true and break if text and text.include?(expected)
33
+ end
34
+ execute_ok.should == true
35
+ end
36
+ end
37
+
38
+ module Spec
39
+ module Runner
40
+ class Context
41
+ def before_context_eval
42
+ inherit RSpecFormUnit
43
+ end
44
+ end
45
+ end
46
+ end
data/lib/rformunit.rb ADDED
@@ -0,0 +1,15 @@
1
+ #***********************************************************
2
+ #* Copyright (c) 2006, Zhimin Zhan.
3
+ #* Distributed open-source, see full license in MIT-LICENSE
4
+ #***********************************************************
5
+
6
+ # Extra full path to load libraries
7
+ require File.dirname(__FILE__) + "/rformunit/driver"
8
+ require File.dirname(__FILE__) + "/rformunit/control"
9
+ require File.dirname(__FILE__) + "/rformunit/mouse"
10
+ require File.dirname(__FILE__) + "/rformunit/keyboard"
11
+ require File.dirname(__FILE__) + "/rformunit/window"
12
+ require File.dirname(__FILE__) + "/rformunit/open_file_dialog"
13
+ require File.dirname(__FILE__) + "/rformunit/saveas_file_dialog"
14
+ require File.dirname(__FILE__) + "/rformunit/process"
15
+ require File.dirname(__FILE__) + "/rformunit/form_testcase"
@@ -0,0 +1,152 @@
1
+ require File.dirname(__FILE__) + "/driver"
2
+
3
+ module RFormUnit
4
+ class BaseControl
5
+ include Driver
6
+
7
+ attr_accessor :parent_win, :control_id
8
+
9
+ def initialize(win, ctrl_id)
10
+ @parent_win = win
11
+ @control_id = ctrl_id
12
+ end
13
+
14
+ def set_text(new_text)
15
+ driver.ControlSetText(@parent_win.title, @parent_win.text, @control_id, new_text)
16
+ end
17
+
18
+ def send_text(text)
19
+ driver.ControlSend(@parent_win.title, @parent_win.text, @control_id, text)
20
+ end
21
+
22
+ def get_text
23
+ driver.ControlGetText(@parent_win.title, @parent_win.text, @control_id)
24
+ end
25
+
26
+ def focus
27
+ driver.ControlFocus(@parent_win.title, @parent_win.text, @control_id)
28
+ end
29
+
30
+ def is_enabled?
31
+ ret = driver.ControlCommand(@parent_win.title, @parent_win.text, @control_id, "IsEnabled" ,"")
32
+ ret == 1 or ret == "1"
33
+ end
34
+
35
+ def is_visible?
36
+ ret = driver.ControlCommand(@parent_win.title, @parent_win.text, @control_id, "IsVisible" ,"")
37
+ ret == 1 or ret == "1"
38
+ end
39
+
40
+ def click
41
+ driver.ControlClick(@parent_win.title, @parent_win.text, @control_id)
42
+ end
43
+
44
+ end
45
+
46
+ class TextBox < BaseControl
47
+
48
+ end
49
+
50
+ class Label < BaseControl
51
+
52
+ end
53
+
54
+ class CheckBox < BaseControl
55
+ def check
56
+ driver.ControlCommand(@parent_win.title, @parent_win.text, @control_id, "Check" ,"")
57
+ end
58
+
59
+ def uncheck
60
+ driver.ControlCommand(@parent_win.title, @parent_win.text, @control_id, "UnCheck" ,"")
61
+ end
62
+
63
+ def is_checked?
64
+ driver.ControlCommand(@parent_win.title, @parent_win.text, @control_id, "IsChecked" ,"") == 1
65
+ end
66
+
67
+ end
68
+
69
+ class RadioButton < BaseControl
70
+ def check
71
+ driver.ControlCommand(@parent_win.title, @parent_win.text, @control_id, "Check" ,"")
72
+ end
73
+
74
+ def uncheck
75
+ driver.ControlCommand(@parent_win.title, @parent_win.text, @control_id, "UnCheck" ,"")
76
+ end
77
+
78
+ def is_checked?
79
+ driver.ControlCommand(@parent_win.title, @parent_win.text, @control_id, "IsChecked" ,"") == 1
80
+ end
81
+
82
+ end
83
+
84
+ class ComboBox < BaseControl
85
+
86
+ def show_dropdown
87
+ driver.ControlCommand(@parent_win.title, @parent_win.text, @control_id, "ShowDropDown" ,"")
88
+ end
89
+
90
+ def hide_dropdown
91
+ driver.ControlCommand(@parent_win.title, @parent_win.text, @control_id, "HideDropDown" ,"")
92
+ end
93
+
94
+ def select_option(option)
95
+ driver.ControlCommand(@parent_win.title, @parent_win.text, @control_id, "SelectString" , option)
96
+ end
97
+
98
+ end
99
+
100
+
101
+ class Button < BaseControl
102
+ end
103
+
104
+ class Tab < BaseControl
105
+
106
+ def current
107
+ driver.ControlCommand(@parent_win.title, @parent_win.text, @control_id, "CurrentTab" , "")
108
+ end
109
+
110
+ end
111
+
112
+ class ListView < BaseControl
113
+
114
+ def item_count
115
+ result = driver.ControlListView(@parent_win.title, @parent_win.text, @control_id, "GetItemCount" , "", "").to_i
116
+ result ? result.to_i : 0
117
+ end
118
+
119
+ # row and column index starts from 0,
120
+ def get_item_text(row, col = 0)
121
+ driver.ControlListView(@parent_win.title, @parent_win.text, @control_id, "GetText" , "#{row}", col)
122
+ end
123
+
124
+ # can't use select, as it is Ruby keyword
125
+ def highlight(row_start, row_end = nil)
126
+ row_end ||= row_start
127
+ driver.ControlListView(@parent_win.title, @parent_win.text, @control_id, "Select" , "#{row_start}", "#{row_end}")
128
+ end
129
+
130
+ def de_highlight(row_start, row_end = nil)
131
+ row_end ||= row_start
132
+ driver.ControlListView(@parent_win.title, @parent_win.text, @control_id, "DeSelect" , "#{row_start}", "#{row_end}")
133
+ end
134
+ alias de_select de_highlight
135
+
136
+ def subitem_count
137
+ result = driver.ControlListView(@parent_win.title, @parent_win.text, @control_id, "GetSubItemCount" , "", "").to_i
138
+ result ? result.to_i : 0
139
+ end
140
+
141
+ def select_all
142
+ driver.ControlListView(@parent_win.title, @parent_win.text, @control_id, "SelectAll" , "", "")
143
+ end
144
+
145
+ def is_selected?(row)
146
+ 1 == driver.ControlListView(@parent_win.title, @parent_win.text, @control_id, "IsSelected" , "#{row}", "")
147
+ end
148
+
149
+ end
150
+
151
+
152
+ end
@@ -0,0 +1,68 @@
1
+ require 'win32ole'
2
+
3
+ module RFormUnit
4
+ module Driver
5
+
6
+ def init
7
+ driver
8
+ end
9
+
10
+ def driver
11
+ return @a3 if @a3
12
+
13
+ @a3 = WIN32OLE.new('AutoItX3.Control')
14
+
15
+ @a3.AutoItSetOption("CaretCoordMode", 0);
16
+ @a3.AutoItSetOption("ColorMode", 1);
17
+ @a3.AutoItSetOption("MouseCoordMode", 0);
18
+ @a3.AutoItSetOption("PixelCoordMode", 0);
19
+ @a3.AutoItSetOption("SendKeyDelay", 15)
20
+ return @a3
21
+ end
22
+
23
+ def set_autoit_option(key, value)
24
+ init if @a3.nil?
25
+ @a3.AutoItSetOption(key, value)
26
+ end
27
+
28
+ def wait_for_window(win, timeout=30)
29
+ driver.WinWait(win.title, win.text, timeout * 1000)
30
+ win
31
+ end
32
+
33
+ def wait_and_focus_window(title, text="", timeout=30)
34
+ driver.WinWaitActive(title, text, timeout * 1000)
35
+ end
36
+
37
+ def window_exists?(title)
38
+ driver.WinExists(title) > 0
39
+ end
40
+
41
+ def focus_window(title)
42
+ driver.WinActivate(title)
43
+ end
44
+
45
+ def close_window(title)
46
+ driver.WinClose(title)
47
+ end
48
+
49
+ # wrapper of keyboard operations
50
+ def key_press(keys)
51
+ filtered_keys = keys.gsub("Alt+", "!+").gsub("Ctrl+", "^+")
52
+ RFormUnit::Keyboard.press(filtered_keys)
53
+ end
54
+ alias press_key key_press
55
+
56
+ # standard open file dialog
57
+ def open_file_dialog(title, filepath)
58
+ wait_and_focus_window(title)
59
+ dialog = RFormUnit::OpenFileDialog.new(title)
60
+ dialog.enter_filepath(filepath)
61
+ sleep 1
62
+ dialog.click_open
63
+ end
64
+
65
+ #TODO: save as file dialog
66
+
67
+ end
68
+ end
@@ -0,0 +1,40 @@
1
+ #***********************************************************
2
+ #* Copyright (c) 2006, Zhimin Zhan.
3
+ #* Distributed open-source, see full license in MIT-LICENSE
4
+ #***********************************************************
5
+
6
+ require 'test/unit'
7
+
8
+ module RFormUnit
9
+ class FormTestCase < Test::Unit::TestCase
10
+ include RFormUnit::Driver
11
+
12
+ def default_test
13
+ super unless(self.class == FormTestCase)
14
+ end
15
+
16
+ # assert the block's return value instance every 1 second until timeout with specifed duration
17
+ def timeout_check_equal(duration, expected, &block)
18
+ execute_ok = false
19
+ duration.times do
20
+ sleep(1)
21
+ text = instance_eval(&block)
22
+ execute_ok = true and break if (text == expected)
23
+ end
24
+ execute_ok.should == true
25
+ end
26
+
27
+ #
28
+ def timeout_check_include?(duration, expected, &block)
29
+ execute_ok = false
30
+ duration.times do
31
+ sleep(1)
32
+ text = instance_eval(&block)
33
+ execute_ok = true and break if text and text.include?(expected)
34
+ end
35
+ execute_ok.should == true
36
+ end
37
+ alias timeout_check_include timeout_check_include?
38
+
39
+ end
40
+ end
@@ -0,0 +1,24 @@
1
+ require File.dirname(__FILE__) + "/driver"
2
+ require 'singleton'
3
+
4
+ module RFormUnit
5
+ class Keyboard
6
+ include Singleton
7
+ include Driver
8
+
9
+ def self.type(keys)
10
+ instance._type(keys)
11
+ end
12
+
13
+ def self.press(key)
14
+ instance._type(key)
15
+ end
16
+
17
+ # instance methods
18
+ def _type(keystrokes)
19
+ driver.Send(keystrokes)
20
+ end
21
+ alias _press _type
22
+
23
+ end
24
+ end
@@ -0,0 +1,55 @@
1
+ require File.dirname(__FILE__) + "/driver"
2
+ require 'singleton'
3
+
4
+ module RFormUnit
5
+
6
+ class Mouse
7
+ include Singleton
8
+ include Driver
9
+
10
+ def self.click(x=nil, y=nil)
11
+ instance._click(x, y)
12
+ end
13
+
14
+ def self.right_click(x=nil, y=nil)
15
+ instance._right_click(x, y)
16
+ end
17
+
18
+ def self.double_click(x, y)
19
+ instance._double_click(x,y)
20
+ end
21
+
22
+ def self.move_to(x, y)
23
+ instance._move_to(x,y)
24
+ end
25
+
26
+
27
+ # intance methods
28
+
29
+ def _click(x=nil, y=nil)
30
+ if (x and y) then
31
+ driver.MouseClick("left", x, y)
32
+ else
33
+ driver.MouseClick("left")
34
+ end
35
+ end
36
+
37
+ def _right_click(x=nil, y=nil)
38
+ if (x and y) then
39
+ driver.MouseClick("right", x, y)
40
+ else
41
+ driver.MouseClick("right")
42
+ end
43
+ end
44
+
45
+ def _double_click(x, y)
46
+ driver.MouseClick("left", x, y, 2)
47
+ end
48
+
49
+ def _move_to(x, y)
50
+ driver.MouseMove(x,y)
51
+ end
52
+
53
+ end
54
+
55
+ end
@@ -0,0 +1,19 @@
1
+ module RFormUnit
2
+ class OpenFileDialog < RFormUnit::Window
3
+
4
+ def initialize(title = "Open File")
5
+ focus_window(title)
6
+ end
7
+
8
+ def enter_filepath(file_path)
9
+ get_text # somehow calling it get it loaded
10
+ set_control_text("Edit1", file_path)
11
+ end
12
+
13
+ def click_open
14
+ click_button("Button2")
15
+ end
16
+
17
+ end
18
+
19
+ end
@@ -0,0 +1,27 @@
1
+ require File.dirname(__FILE__) + "/driver"
2
+ require 'singleton'
3
+
4
+ module RFormUnit
5
+
6
+ class Process
7
+ include Singleton
8
+ include Driver
9
+
10
+ def self.run(prog, work_path = nil)
11
+ instance._run(prog, work_path)
12
+ end
13
+
14
+ def self.execute(prog, work_path = nil)
15
+ instance._run(prog, work_path)
16
+ end
17
+
18
+ # --
19
+ # instance methods
20
+ def _run(program, work_path = nil)
21
+ driver.Run(program, work_path)
22
+ end
23
+
24
+
25
+ end
26
+
27
+ end
@@ -0,0 +1,18 @@
1
+ module RFormUnit
2
+ class SaveasFileDialog < RFormUnit::Window
3
+
4
+ def initialize(title = "Save As")
5
+ focus_window(title)
6
+ end
7
+
8
+ def enter_filepath(file_path)
9
+ set_control_text("Edit1", file_path)
10
+ end
11
+
12
+ def click_save
13
+ click_button("Button2")
14
+ end
15
+
16
+ end
17
+
18
+ end
@@ -0,0 +1,100 @@
1
+ require File.dirname(__FILE__) + "/driver"
2
+ require File.dirname(__FILE__) + "/control"
3
+
4
+ module RFormUnit
5
+
6
+
7
+ class Window < BaseControl
8
+ attr_accessor :title, :text
9
+
10
+ def initialize(title, text = '', timeout = 10)
11
+ # for some windows, the title might change depends when it is invoked
12
+ if title.class == Array
13
+ title.each { |a_title|
14
+ @title = a_title
15
+ @text = text if text
16
+ result = driver.WinWaitActive(@title, @text, timeout)
17
+ return if result != 0
18
+ }
19
+ raise "timeout while waiting for window: #{self.to_s}"
20
+ end
21
+
22
+ @title = title
23
+ @text = text if text
24
+ result = driver.WinWaitActive(@title, @text, timeout)
25
+ raise "timeout while waiting for window: #{self.to_s}" if result == 0
26
+ end
27
+
28
+ def focus
29
+ driver.WinActivate(@title, @text)
30
+ end
31
+
32
+ def close
33
+ driver.WinClose(@title, @text)
34
+ end
35
+
36
+ def exists?
37
+ driver.WinExists(@title, @text)
38
+ end
39
+
40
+ def get_text
41
+ driver.WinGetText(@title, @text)
42
+ end
43
+
44
+ def set_control_text(control_id, new_text)
45
+ BaseControl.new(self, control_id).set_text(new_text)
46
+ end
47
+
48
+ def click_button(btn_id)
49
+ Button.new(self, btn_id).click
50
+ end
51
+
52
+ def show_dropdown(combo_id)
53
+ combo = ComboBox.new(self, combo_id)
54
+ combo.show_dropdown
55
+ combo
56
+ end
57
+
58
+ def hide_dropdown(combo_id)
59
+ combo = ComboBox.new(self, combo_id)
60
+ combo.hide_dropdown
61
+ combo
62
+ end
63
+
64
+ def focus_control(ctrl_id)
65
+ BaseControl.new(self, ctrl_id).focus
66
+ end
67
+
68
+ def send_control_text(ctrl_id, text)
69
+ BaseControl.new(self, ctrl_id).send_text(text)
70
+ end
71
+
72
+ def get_control_text(ctrl_id)
73
+ BaseControl.new(self, ctrl_id).get_text
74
+ end
75
+
76
+ #Not fully verified yet
77
+ def statusbar_text
78
+ driver.StatusbarGetText(@title)
79
+ end
80
+
81
+ def pixel_color(x,y)
82
+ driver.PixelGetColor(x,y)
83
+ end
84
+ alias pixel_colour pixel_color
85
+ alias get_pixel_colour pixel_color
86
+ alias get_pixel_color pixel_color
87
+
88
+
89
+ def to_s
90
+ "Window{title => '#{@title}', text=>'#{@text}'}"
91
+ end
92
+
93
+ # a list
94
+ def button(button_id)
95
+ RFormUnit::Button.new(self, button_id)
96
+ end
97
+
98
+ end
99
+
100
+ end
data/sample/calc.rb ADDED
@@ -0,0 +1,25 @@
1
+ require 'rformunit'
2
+
3
+ module Calc
4
+ include RFormUnit::Driver
5
+
6
+ def start_calc
7
+ RFormUnit::Process.run("calc.exe")
8
+ RFormUnit::Window.new('Calculator')
9
+ end
10
+
11
+ def find_existing_calc_win
12
+ if window_exists?("Calculator")
13
+ focus_window('Calculator')
14
+ RFormUnit::Window.new('Calculator')
15
+ else
16
+ nil
17
+ end
18
+ end
19
+
20
+ def quit_calc
21
+ focus_window('QPRIME')
22
+ RFormUnit::Keyboard.press("!{F4}")
23
+ end
24
+
25
+ end
@@ -0,0 +1,16 @@
1
+ require File.dirname(__FILE__) + '/rspec_calc'
2
+
3
+ context "Calculator" do
4
+
5
+ setup do
6
+ end
7
+
8
+ specify "Multiple works" do
9
+ @calc_win.click_button('127') #3
10
+ @calc_win.click_button('91') #*
11
+ @calc_win.click_button('131') #7
12
+ @calc_win.click_button('112') #=
13
+ @calc_win.get_control_text('403').should == '21. '
14
+ end
15
+
16
+ end
data/sample/notepad.rb ADDED
@@ -0,0 +1,19 @@
1
+ require 'rformunit'
2
+
3
+ include RFormUnit::Driver
4
+
5
+ RFormUnit::Process.run("C:\\WINDOWS\\NOTEPAD.EXE")
6
+ notepad_win = RFormUnit::Window.new('Untitled - Notepad')
7
+ RFormUnit::Keyboard.type("Hello, Missing No. 5.{ENTER}1 2 3 4 6 7 8 9 10{ENTER}")
8
+ RFormUnit::Keyboard.press("+{UP 2}")
9
+
10
+ # move cursor up and insert the missing number
11
+ RFormUnit::Mouse.move_to(70, 65)
12
+ RFormUnit::Mouse.click
13
+ RFormUnit::Keyboard.type("5 ")
14
+
15
+ notepad_win.close
16
+
17
+ notepad_confirm_dialog = RFormUnit::Window.new('Notepad', 'The text')
18
+ notepad_confirm_dialog.focus
19
+ RFormUnit::Button.new(notepad_confirm_dialog, "7").click
@@ -0,0 +1,14 @@
1
+ require 'rformunit'
2
+
3
+ include RFormUnit::Driver
4
+
5
+ RFormUnit::Process.run("C:\\WINDOWS\\NOTEPAD.EXE")
6
+ notepad_win = RFormUnit::Window.new('Untitled - Notepad')
7
+ RFormUnit::Keyboard.type("Hello from Notepad, {ENTER}1 2 3 4 5 6 7 8 9 10{ENTER}")
8
+ sleep(0.5)
9
+ RFormUnit::Keyboard.press("+{UP 2}")
10
+ sleep(0.5)
11
+ notepad_win.close
12
+
13
+ notepad_confirm_dialog = RFormUnit::Window.new('Notepad', 'No')
14
+ notepad_confirm_dialog.click_button('&No')
@@ -0,0 +1,24 @@
1
+ require File.dirname(__FILE__) + '/calc'
2
+
3
+ class RSpecCalc
4
+ include Calc
5
+
6
+ def setup
7
+ init # initialize
8
+ @calc_win = find_existing_calc_win
9
+ if @calc_win.nil?
10
+ @calc_win = start_calc
11
+ end
12
+ end
13
+ end
14
+
15
+ module Spec
16
+ module Runner
17
+ class Context
18
+ def before_context_eval
19
+ #inherit RSpecCalc # inherit not supported after 0.8
20
+ inherit_context_eval_module_from RSpecCalc
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,23 @@
1
+ require 'rformunit'
2
+
3
+ class CalcTest < RFormUnit::FormTestCase
4
+
5
+ def setup
6
+ RFormUnit::Process.run("calc.exe")
7
+ @calc_win = RFormUnit::Window.new('Calculator')
8
+ end
9
+
10
+ def teardown
11
+ @calc_win.close
12
+ end
13
+
14
+ def test_multiple
15
+ @calc_win.click_button('127') #3
16
+ @calc_win.click_button('91') #*
17
+ @calc_win.click_button('131') #7
18
+ @calc_win.click_button('112') #=
19
+ assert_equal "21. ", @calc_win.get_control_text('403')
20
+
21
+ end
22
+
23
+ end
metadata ADDED
@@ -0,0 +1,76 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rformunit
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ platform: x86-mswin32-60
6
+ authors:
7
+ - Zhimin Zhan
8
+ autorequire: rformunit
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-01-06 00:00:00 +00:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description:
17
+ email: zhimin@zhimin.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files: []
23
+
24
+ files:
25
+ - Rakefile
26
+ - README
27
+ - CHANGELOG
28
+ - MIT-LICENSE
29
+ - lib/ext
30
+ - lib/rformunit
31
+ - lib/rformunit.rb
32
+ - lib/ext/rspec_rformunit.rb
33
+ - lib/rformunit/control.rb
34
+ - lib/rformunit/driver.rb
35
+ - lib/rformunit/form_testcase.rb
36
+ - lib/rformunit/keyboard.rb
37
+ - lib/rformunit/mouse.rb
38
+ - lib/rformunit/open_file_dialog.rb
39
+ - lib/rformunit/process.rb
40
+ - lib/rformunit/saveas_file_dialog.rb
41
+ - lib/rformunit/window.rb
42
+ - sample/calc.rb
43
+ - sample/calc_spec.rb
44
+ - sample/notepad.rb
45
+ - sample/notepad1.rb
46
+ - sample/rspec_calc.rb
47
+ - sample/test_calc.rb
48
+ - docs/index.html
49
+ has_rdoc: true
50
+ homepage: http://www.zhimin.com/software/rformunit/
51
+ post_install_message:
52
+ rdoc_options: []
53
+
54
+ require_paths:
55
+ - lib
56
+ required_ruby_version: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: "0"
61
+ version:
62
+ required_rubygems_version: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: "0"
67
+ version:
68
+ requirements:
69
+ - none
70
+ rubyforge_project:
71
+ rubygems_version: 1.0.1
72
+ signing_key:
73
+ specification_version: 2
74
+ summary: An wrap of AUTOIT3 for functional testing of Windows form applications
75
+ test_files: []
76
+