rformunit 0.2.0-x86-mswin32-60
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 +30 -0
- data/MIT-LICENSE +21 -0
- data/README +30 -0
- data/Rakefile +65 -0
- data/docs/index.html +185 -0
- data/lib/ext/rspec_rformunit.rb +46 -0
- data/lib/rformunit.rb +15 -0
- data/lib/rformunit/control.rb +152 -0
- data/lib/rformunit/driver.rb +68 -0
- data/lib/rformunit/form_testcase.rb +40 -0
- data/lib/rformunit/keyboard.rb +24 -0
- data/lib/rformunit/mouse.rb +55 -0
- data/lib/rformunit/open_file_dialog.rb +19 -0
- data/lib/rformunit/process.rb +27 -0
- data/lib/rformunit/saveas_file_dialog.rb +18 -0
- data/lib/rformunit/window.rb +100 -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 +24 -0
- data/sample/test_calc.rb +23 -0
- metadata +76 -0
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
|
+
<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
|
+
<!-- <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
|
+
|
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 < 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
|
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
|
+
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
|
data/sample/notepad1.rb
ADDED
@@ -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
|
data/sample/test_calc.rb
ADDED
@@ -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
|
+
|