rformunit 0.1.0-mswin32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +0 -0
- data/MIT-LICENSE +21 -0
- data/README +29 -0
- data/Rakefile +67 -0
- data/docs/index.html +187 -0
- data/lib/ext/rspec_rformunit.rb +46 -0
- data/lib/rformunit/control.rb +107 -0
- data/lib/rformunit/driver.rb +66 -0
- data/lib/rformunit/form_testcase.rb +39 -0
- data/lib/rformunit/keyboard.rb +13 -0
- data/lib/rformunit/mouse.rb +34 -0
- data/lib/rformunit/process.rb +14 -0
- data/lib/rformunit/window.rb +70 -0
- data/lib/rformunit.rb +13 -0
- data/sample/calc.rb +25 -0
- data/sample/calc_spec.rb +16 -0
- data/sample/notepad.rb +19 -0
- data/sample/notepad1.rb +14 -0
- data/sample/rspec_calc.rb +23 -0
- data/sample/test_calc.rb +22 -0
- metadata +67 -0
data/CHANGELOG
ADDED
File without changes
|
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,29 @@
|
|
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.0.1)
|
12
|
+
|
13
|
+
Platform: MS Windows (of course)
|
14
|
+
|
15
|
+
Install
|
16
|
+
-------
|
17
|
+
> gem install rformunit
|
18
|
+
|
19
|
+
One minute tutorial
|
20
|
+
-------------------
|
21
|
+
|
22
|
+
|
23
|
+
Copyrights
|
24
|
+
----------
|
25
|
+
Free to use for any purposes. The software provided AS IS without any warranty whatsoever.
|
26
|
+
|
27
|
+
Contact
|
28
|
+
-------
|
29
|
+
Zhimin Zhan, Agileway Pty Ltd.
|
data/Rakefile
ADDED
@@ -0,0 +1,67 @@
|
|
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::WIN32
|
38
|
+
s.name = "rformunit"
|
39
|
+
s.version = "0.1.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
|
66
|
+
|
67
|
+
|
data/docs/index.html
ADDED
@@ -0,0 +1,187 @@
|
|
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.0<br/>
|
35
|
+
<a href="releases/rformunit-0.1.0-mswin32.gem">rformunit-0.1.0-mswin32.gem</a> or from <a href="http://rubyforge.org/projects/rformunit/">rubyforge.org</a>,
|
36
|
+
|
37
|
+
<!-- <a href="releases/changelog.txt">Change logs</a> <br/> -->
|
38
|
+
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
|
+
Install <a href="http://rubyinstaller.rubyforge.org/wiki/wiki.pl">Ruby for windows</a><br/>
|
45
|
+
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
|
+
include RFormUnit::Driver
|
92
|
+
|
93
|
+
process.run("C:\\WINDOWS\\NOTEPAD.EXE")
|
94
|
+
notepad_win = RFormUnit::Window.new('Untitled - Notepad')
|
95
|
+
|
96
|
+
keyboard.type("Hello from Notepad, {ENTER}1 2 3{ENTER}")
|
97
|
+
sleep(0.5)
|
98
|
+
keyboard.press("+{UP 2}") # mouse.* for mouse operations
|
99
|
+
sleep(0.5)
|
100
|
+
|
101
|
+
notepad_win.close
|
102
|
+
|
103
|
+
|
104
|
+
notepad_confirm_dialog = RFormUnit::Window.new('Notepad', 'No')
|
105
|
+
notepad_confirm_dialog.click_button('&No')</pre>
|
106
|
+
</td>
|
107
|
+
</tr>
|
108
|
+
</table>
|
109
|
+
|
110
|
+
<a name="test"></a>
|
111
|
+
<div id="rformunit_test">
|
112
|
+
<h4>rFormUnit Testcase</h4>
|
113
|
+
<pre class="green">require 'rformunit'
|
114
|
+
|
115
|
+
class CalcTest < RFormUnit::FormTestCase
|
116
|
+
def setup
|
117
|
+
process.run("calc.exe")
|
118
|
+
@calc_win = RFormUnit::Window.new('Calculator')
|
119
|
+
end
|
120
|
+
|
121
|
+
def teardown
|
122
|
+
@calc_win.close
|
123
|
+
end
|
124
|
+
|
125
|
+
def test_multiple
|
126
|
+
@calc_win.click_button('127') #3
|
127
|
+
@calc_win.click_button('91') #*
|
128
|
+
@calc_win.click_button('131') #7
|
129
|
+
@calc_win.click_button('112') #=
|
130
|
+
assert_equal "21. ", @calc_win.get_control_text('403')
|
131
|
+
end
|
132
|
+
|
133
|
+
end</pre>
|
134
|
+
</div>
|
135
|
+
|
136
|
+
<a name="rspec"></a><div id='rformunit_rspec'>
|
137
|
+
<h4>rFormUnit <a href="http://rspec.rubyforge.org/">RSpec</a></h4>
|
138
|
+
|
139
|
+
<p><b>rspec_calc</b>: a spec runner to run rformunit based rspecs</p>
|
140
|
+
<pre class="green">
|
141
|
+
require File.dirname(__FILE__) + '/calc'
|
142
|
+
|
143
|
+
class RSpecCalc
|
144
|
+
include Calc
|
145
|
+
|
146
|
+
def setup
|
147
|
+
init # initialize
|
148
|
+
@calc_win = find_existing_calc_win
|
149
|
+
if @calc_win.nil?
|
150
|
+
@calc_win = start_calc
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
module Spec
|
156
|
+
module Runner
|
157
|
+
class Context
|
158
|
+
def before_context_eval
|
159
|
+
inherit RSpecCalc
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end</pre>
|
164
|
+
|
165
|
+
<p><b>calc_spec</b>: a rspec</p>
|
166
|
+
<pre class="green">
|
167
|
+
require File.dirname(__FILE__) + '/rspec_calc'
|
168
|
+
|
169
|
+
context "Calculator" do
|
170
|
+
|
171
|
+
setup do
|
172
|
+
end
|
173
|
+
|
174
|
+
specify "Multiple shall work" do
|
175
|
+
@calc_win.click_button('127') #3
|
176
|
+
@calc_win.click_button('91') #*
|
177
|
+
@calc_win.click_button('131') #7
|
178
|
+
@calc_win.click_button('112') #=
|
179
|
+
@calc_win.get_control_text('403').should == '21. '
|
180
|
+
end
|
181
|
+
|
182
|
+
end</pre>
|
183
|
+
|
184
|
+
</div>
|
185
|
+
|
186
|
+
</body>
|
187
|
+
</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
|
@@ -0,0 +1,107 @@
|
|
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 CheckBox < BaseControl
|
51
|
+
def check
|
52
|
+
driver.ControlCommand(@parent_win.title, @parent_win.text, @control_id, "Check" ,"")
|
53
|
+
end
|
54
|
+
|
55
|
+
def uncheck
|
56
|
+
driver.ControlCommand(@parent_win.title, @parent_win.text, @control_id, "UnCheck" ,"")
|
57
|
+
end
|
58
|
+
|
59
|
+
def is_checked?
|
60
|
+
driver.ControlCommand(@parent_win.title, @parent_win.text, @control_id, "IsChecked" ,"") == 1
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
|
65
|
+
class RadioButton < BaseControl
|
66
|
+
def check
|
67
|
+
driver.ControlCommand(@parent_win.title, @parent_win.text, @control_id, "Check" ,"")
|
68
|
+
end
|
69
|
+
|
70
|
+
def uncheck
|
71
|
+
driver.ControlCommand(@parent_win.title, @parent_win.text, @control_id, "UnCheck" ,"")
|
72
|
+
end
|
73
|
+
|
74
|
+
def is_checked?
|
75
|
+
driver.ControlCommand(@parent_win.title, @parent_win.text, @control_id, "IsChecked" ,"") == 1
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
|
80
|
+
class ComboBox < BaseControl
|
81
|
+
|
82
|
+
def show_dropdown
|
83
|
+
driver.ControlCommand(@parent_win.title, @parent_win.text, @control_id, "ShowDropDown" ,"")
|
84
|
+
end
|
85
|
+
|
86
|
+
def hide_dropdown
|
87
|
+
driver.ControlCommand(@parent_win.title, @parent_win.text, @control_id, "HideDropDown" ,"")
|
88
|
+
end
|
89
|
+
|
90
|
+
def select_option(option)
|
91
|
+
driver.ControlCommand(@parent_win.title, @parent_win.text, @control_id, "SelectString" , option)
|
92
|
+
end
|
93
|
+
|
94
|
+
|
95
|
+
end
|
96
|
+
|
97
|
+
class Button < BaseControl
|
98
|
+
end
|
99
|
+
|
100
|
+
class Tab < BaseControl
|
101
|
+
def current
|
102
|
+
driver.ControlCommand(@parent_win.title, @parent_win.text, @control_id, "CurrentTab" , "")
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
|
107
|
+
end
|
@@ -0,0 +1,66 @@
|
|
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", 20)
|
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 keyboard
|
29
|
+
return @keyboard if @keyboard
|
30
|
+
@keyboard = Keyboard.new
|
31
|
+
end
|
32
|
+
|
33
|
+
def mouse
|
34
|
+
return @mouse if @mouse
|
35
|
+
@mouse = Mouse.new
|
36
|
+
end
|
37
|
+
|
38
|
+
def process
|
39
|
+
return @process if @process
|
40
|
+
@process = Process.new
|
41
|
+
end
|
42
|
+
|
43
|
+
def wait_for_window(win, timeout=30)
|
44
|
+
driver.WinWait(win.title, win.text, timeout * 1000)
|
45
|
+
win
|
46
|
+
end
|
47
|
+
|
48
|
+
def wait_and_focus_window(title, text="", timeout=30)
|
49
|
+
driver.WinWaitActive(title, text, timeout * 1000)
|
50
|
+
end
|
51
|
+
|
52
|
+
def window_exists?(title)
|
53
|
+
driver.WinExists(title) > 0
|
54
|
+
end
|
55
|
+
|
56
|
+
def focus_window(title)
|
57
|
+
driver.WinActivate(title)
|
58
|
+
end
|
59
|
+
|
60
|
+
def close_window(title)
|
61
|
+
driver.WinClose(title)
|
62
|
+
end
|
63
|
+
|
64
|
+
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,39 @@
|
|
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
|
+
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/driver"
|
2
|
+
|
3
|
+
module RFormUnit
|
4
|
+
|
5
|
+
class Mouse
|
6
|
+
include Driver
|
7
|
+
|
8
|
+
def click(x=nil, y=nil)
|
9
|
+
if (x and y) then
|
10
|
+
driver.MouseClick("left", x, y)
|
11
|
+
else
|
12
|
+
driver.MouseClick("left")
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def right_click(x=nil, y=nil)
|
17
|
+
if (x and y) then
|
18
|
+
driver.MouseClick("right", x, y)
|
19
|
+
else
|
20
|
+
driver.MouseClick("right")
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def double_click(x, y)
|
25
|
+
driver.MouseClick("left", x, y, 2)
|
26
|
+
end
|
27
|
+
|
28
|
+
def move_to(x, y)
|
29
|
+
driver.MouseMove(x,y)
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/driver"
|
2
|
+
require File.dirname(__FILE__) + "/control"
|
3
|
+
|
4
|
+
module RFormUnit
|
5
|
+
|
6
|
+
class Window < BaseControl
|
7
|
+
attr_accessor :title, :text
|
8
|
+
|
9
|
+
def initialize(title, text = '', timeout = 10)
|
10
|
+
@title = title
|
11
|
+
@text = text if text
|
12
|
+
result = driver.WinWaitActive(@title, @text, timeout)
|
13
|
+
raise "timeout while waiting for window: #{self.to_s}" if result == 0
|
14
|
+
end
|
15
|
+
|
16
|
+
def focus
|
17
|
+
driver.WinActivate(@title)
|
18
|
+
end
|
19
|
+
|
20
|
+
def close
|
21
|
+
driver.WinClose(@title)
|
22
|
+
end
|
23
|
+
|
24
|
+
def exists?
|
25
|
+
driver.WinExists(@title)
|
26
|
+
end
|
27
|
+
|
28
|
+
def get_text
|
29
|
+
driver.WinGetText(@title, @text)
|
30
|
+
end
|
31
|
+
|
32
|
+
def set_control_text(control_id, new_text)
|
33
|
+
TextBox.new(self, control_id).set_text(new_text)
|
34
|
+
end
|
35
|
+
|
36
|
+
def click_button(btn_id)
|
37
|
+
Button.new(self, btn_id).click
|
38
|
+
end
|
39
|
+
|
40
|
+
def show_dropdown(combo_id)
|
41
|
+
combo = ComboBox.new(self, combo_id)
|
42
|
+
combo.show_dropdown
|
43
|
+
combo
|
44
|
+
end
|
45
|
+
|
46
|
+
def hide_dropdown(combo_id)
|
47
|
+
combo = ComboBox.new(self, combo_id)
|
48
|
+
combo.hide_dropdown
|
49
|
+
combo
|
50
|
+
end
|
51
|
+
|
52
|
+
def focus_control(ctrl_id)
|
53
|
+
BaseControl.new(self, ctrl_id).focus
|
54
|
+
end
|
55
|
+
|
56
|
+
def send_control_text(ctrl_id, text)
|
57
|
+
BaseControl.new(self, ctrl_id).send_text(text)
|
58
|
+
end
|
59
|
+
|
60
|
+
def get_control_text(ctrl_id)
|
61
|
+
BaseControl.new(self, ctrl_id).get_text
|
62
|
+
end
|
63
|
+
|
64
|
+
def to_s
|
65
|
+
"Window{ title => '#{@title}', text=>'#{@text}'}"
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
data/lib/rformunit.rb
ADDED
@@ -0,0 +1,13 @@
|
|
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/process"
|
13
|
+
require File.dirname(__FILE__) + "/rformunit/form_testcase"
|
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
|
+
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
|
+
keyboard.press("!{F4}")
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
data/sample/calc_spec.rb
ADDED
@@ -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
|
+
process.run("C:\\WINDOWS\\NOTEPAD.EXE")
|
6
|
+
notepad_win = RFormUnit::Window.new('Untitled - Notepad')
|
7
|
+
keyboard.type("Hello, Missing No. 5.{ENTER}1 2 3 4 6 7 8 9 10{ENTER}")
|
8
|
+
keyboard.press("+{UP 2}")
|
9
|
+
|
10
|
+
# move cursor up and insert the missing number
|
11
|
+
mouse.move_to(70, 65)
|
12
|
+
mouse.click
|
13
|
+
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
|
data/sample/notepad1.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'rformunit'
|
2
|
+
|
3
|
+
include RFormUnit::Driver
|
4
|
+
|
5
|
+
process.run("C:\\WINDOWS\\NOTEPAD.EXE")
|
6
|
+
notepad_win = RFormUnit::Window.new('Untitled - Notepad')
|
7
|
+
keyboard.type("Hello from Notepad, {ENTER}1 2 3 4 5 6 7 8 9 10{ENTER}")
|
8
|
+
sleep(0.5)
|
9
|
+
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,23 @@
|
|
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
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/sample/test_calc.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'rformunit'
|
2
|
+
|
3
|
+
class CalcTest < RFormUnit::FormTestCase
|
4
|
+
def setup
|
5
|
+
process.run("calc.exe")
|
6
|
+
@calc_win = RFormUnit::Window.new('Calculator')
|
7
|
+
end
|
8
|
+
|
9
|
+
def teardown
|
10
|
+
@calc_win.close
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_multiple
|
14
|
+
@calc_win.click_button('127') #3
|
15
|
+
@calc_win.click_button('91') #*
|
16
|
+
@calc_win.click_button('131') #7
|
17
|
+
@calc_win.click_button('112') #=
|
18
|
+
assert_equal "21. ", @calc_win.get_control_text('403')
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
metadata
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.9.0
|
3
|
+
specification_version: 1
|
4
|
+
name: rformunit
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: 0.1.0
|
7
|
+
date: 2006-11-28 00:00:00 +10:00
|
8
|
+
summary: An wrap of AUTOIT3 for functional testing of Windows form applications
|
9
|
+
require_paths:
|
10
|
+
- lib
|
11
|
+
email: zhimin@zhimin.com
|
12
|
+
homepage: http://www.zhimin.com/software/rformunit/
|
13
|
+
rubyforge_project:
|
14
|
+
description:
|
15
|
+
autorequire: rformunit
|
16
|
+
default_executable:
|
17
|
+
bindir: bin
|
18
|
+
has_rdoc: true
|
19
|
+
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">"
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.0.0
|
24
|
+
version:
|
25
|
+
platform: mswin32
|
26
|
+
signing_key:
|
27
|
+
cert_chain:
|
28
|
+
post_install_message:
|
29
|
+
authors:
|
30
|
+
- Zhimin Zhan
|
31
|
+
files:
|
32
|
+
- Rakefile
|
33
|
+
- README
|
34
|
+
- CHANGELOG
|
35
|
+
- MIT-LICENSE
|
36
|
+
- lib/ext
|
37
|
+
- lib/rformunit
|
38
|
+
- lib/rformunit.rb
|
39
|
+
- lib/ext/rspec_rformunit.rb
|
40
|
+
- lib/rformunit/control.rb
|
41
|
+
- lib/rformunit/driver.rb
|
42
|
+
- lib/rformunit/form_testcase.rb
|
43
|
+
- lib/rformunit/keyboard.rb
|
44
|
+
- lib/rformunit/mouse.rb
|
45
|
+
- lib/rformunit/process.rb
|
46
|
+
- lib/rformunit/window.rb
|
47
|
+
- sample/calc.rb
|
48
|
+
- sample/calc_spec.rb
|
49
|
+
- sample/notepad.rb
|
50
|
+
- sample/notepad1.rb
|
51
|
+
- sample/rspec_calc.rb
|
52
|
+
- sample/test_calc.rb
|
53
|
+
- docs/index.html
|
54
|
+
test_files: []
|
55
|
+
|
56
|
+
rdoc_options: []
|
57
|
+
|
58
|
+
extra_rdoc_files: []
|
59
|
+
|
60
|
+
executables: []
|
61
|
+
|
62
|
+
extensions: []
|
63
|
+
|
64
|
+
requirements:
|
65
|
+
- none
|
66
|
+
dependencies: []
|
67
|
+
|