rformspec 0.3.2-x86-mingw32

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG ADDED
@@ -0,0 +1,42 @@
1
+ CHANGELOG
2
+ =========
3
+ 0.3.2
4
+
5
+ Add option in Window class to wait to focus window (default)
6
+
7
+ 0.3.1 (2010-08)
8
+ =====
9
+ Activate window not currently in focus
10
+
11
+ == 0.3 (2009-10-27)
12
+
13
+ Renamed to RFormSpec
14
+
15
+ == 0.2.0 (2007-12-18)
16
+ - add convenient methods in Driver
17
+ - add a commonly used dialog class: open file dialog, save as file dialog
18
+ - add filtered key to support 'Alt+', 'Ctrl+'
19
+
20
+ == 0.1.3 (2007-04-18)
21
+
22
+ New features:
23
+ - Support window with various titles depends on invoking conditions
24
+
25
+ == 0.1.2 (2007-02-26)
26
+
27
+ New features:
28
+ - Add ListView support
29
+ - Add Label support
30
+
31
+ Others:
32
+ - code reformating
33
+
34
+ == 0.1.1 (2006-11-29)
35
+
36
+ New features:
37
+ - replace keyboard.* with RFormUnit::Keyboard.*
38
+ - replace mouse.* with RFormUnit::Mouse.*
39
+ - replace process.* with RFormUnit::Process.*
40
+
41
+
42
+ == 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,24 @@
1
+ RFormSpec
2
+ =========
3
+
4
+ RFormSpec 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
+ Quick Start: Download iTest2 IDE, open samples\form_calculator.tpr project, run it.
16
+
17
+
18
+ Copyrights
19
+ ----------
20
+ Free to use for any purposes. The software provided AS IS without any warranty whatsoever.
21
+
22
+ Contact
23
+ -------
24
+ Zhimin Zhan, Agileway Pty Ltd.
data/Rakefile ADDED
@@ -0,0 +1,63 @@
1
+ require 'rubygems'
2
+ require 'rake/testtask'
3
+ require 'rake/rdoctask'
4
+ require 'rake/gempackagetask'
5
+
6
+ $:.unshift(File.dirname(__FILE__) + "/lib")
7
+ require 'rformspec'
8
+
9
+ desc "Default task"
10
+ task :default => [ :clean, :test , :gem]
11
+
12
+ desc "Clean generated files"
13
+ task :clean do
14
+ rm_rf 'pkg'
15
+ rm_rf 'docs/rdoc'
16
+ end
17
+
18
+ # run the unit tests
19
+ Rake::TestTask.new("test") { |t|
20
+ t.test_files = FileList['test/test*.rb']
21
+ t.verbose= true
22
+ }
23
+
24
+ # Generate the RDoc documentation
25
+ Rake::RDocTask.new { |rdoc|
26
+ rdoc.rdoc_dir = 'docs/rdoc'
27
+ rdoc.title = 'rformspec'
28
+ rdoc.template = "#{ENV['template']}.rb" if ENV['template']
29
+ rdoc.rdoc_files.include('README')
30
+ rdoc.rdoc_files.include('lib/rformspec.rb')
31
+ rdoc.rdoc_files.include('lib/rformspec/*.rb')
32
+ }
33
+
34
+ spec = Gem::Specification.new do |s|
35
+ s.platform= Gem::Platform::CURRENT
36
+ s.name = "rformspec"
37
+ s.version = "0.3.2"
38
+ s.summary = "An wrap of AUTOIT3 for functional testing of Windows form applications"
39
+ # s.description = ""
40
+
41
+ s.author = "Zhimin Zhan"
42
+ s.email = "zhimin@agileway.com.au"
43
+ s.homepage= "http://github.com/zhimin/rformspec"
44
+ # s.rubyforge_project = ""
45
+
46
+ s.has_rdoc = true
47
+ s.requirements << 'none'
48
+ s.require_path = "lib"
49
+ s.autorequire = "rformspec"
50
+
51
+ s.files = [ "Rakefile", "README", "CHANGELOG", "MIT-LICENSE" ]
52
+ # s.files = s.files + Dir.glob( "bin/**/*" ).delete_if { |item| item.include?( "\.svn" ) }
53
+ s.files = s.files + Dir.glob( "ext/**/*" ).delete_if { |item| item.include?( "\.svn" ) }
54
+ s.files = s.files + Dir.glob( "lib/**/*" ).delete_if { |item| item.include?( "\.svn" ) }
55
+ s.files = s.files + Dir.glob( "test/**/*" ).delete_if { |item| item.include?( "\.svn" ) }
56
+ s.files = s.files + Dir.glob( "sample/**/*" ).delete_if { |item| item.include?( "\.svn" ) }
57
+ s.files = s.files + Dir.glob( "docs/**/*" ).delete_if { |item| item.include?( "\.svn" ) }
58
+
59
+ end
60
+
61
+ Rake::GemPackageTask.new(spec) do |pkg|
62
+ pkg.need_zip = true
63
+ end
data/docs/index.html ADDED
@@ -0,0 +1,184 @@
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
+ <p><b>rspec_calc</b>: a spec runner to run rformunit based rspecs</p>
137
+ <pre class="green">
138
+ require File.dirname(__FILE__) + '/calc'
139
+
140
+ class RSpecCalc
141
+ include Calc
142
+
143
+ def setup
144
+ init # initialize
145
+ @calc_win = find_existing_calc_win
146
+ if @calc_win.nil?
147
+ @calc_win = start_calc
148
+ end
149
+ end
150
+ end
151
+
152
+ module Spec
153
+ module Runner
154
+ class Context
155
+ def before_context_eval
156
+ inherit RSpecCalc
157
+ end
158
+ end
159
+ end
160
+ end</pre>
161
+
162
+ <p><b>calc_spec</b>: a rspec</p>
163
+ <pre class="green">
164
+ require File.dirname(__FILE__) + '/rspec_calc'
165
+
166
+ context "Calculator" do
167
+
168
+ setup do
169
+ end
170
+
171
+ specify "Multiple shall work" do
172
+ @calc_win.click_button('127') #3
173
+ @calc_win.click_button('91') #*
174
+ @calc_win.click_button('131') #7
175
+ @calc_win.click_button('112') #=
176
+ @calc_win.get_control_text('403').should == '21. '
177
+ end
178
+
179
+ end</pre>
180
+
181
+ </div>
182
+
183
+ </body>
184
+ </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,153 @@
1
+ require File.dirname(__FILE__) + "/driver"
2
+
3
+ module RFormSpec
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
+ alias send_keys send_text
22
+
23
+ def get_text
24
+ driver.ControlGetText(@parent_win.title, @parent_win.text, @control_id)
25
+ end
26
+
27
+ def focus
28
+ driver.ControlFocus(@parent_win.title, @parent_win.text, @control_id)
29
+ end
30
+
31
+ def is_enabled?
32
+ ret = driver.ControlCommand(@parent_win.title, @parent_win.text, @control_id, "IsEnabled" ,"")
33
+ ret == 1 or ret == "1"
34
+ end
35
+
36
+ def is_visible?
37
+ ret = driver.ControlCommand(@parent_win.title, @parent_win.text, @control_id, "IsVisible" ,"")
38
+ ret == 1 or ret == "1"
39
+ end
40
+
41
+ def click
42
+ driver.ControlClick(@parent_win.title, @parent_win.text, @control_id)
43
+ end
44
+
45
+ end
46
+
47
+ class TextBox < BaseControl
48
+
49
+ end
50
+
51
+ class Label < BaseControl
52
+
53
+ end
54
+
55
+ class CheckBox < BaseControl
56
+ def check
57
+ driver.ControlCommand(@parent_win.title, @parent_win.text, @control_id, "Check" ,"")
58
+ end
59
+
60
+ def uncheck
61
+ driver.ControlCommand(@parent_win.title, @parent_win.text, @control_id, "UnCheck" ,"")
62
+ end
63
+
64
+ def is_checked?
65
+ driver.ControlCommand(@parent_win.title, @parent_win.text, @control_id, "IsChecked" ,"") == 1
66
+ end
67
+
68
+ end
69
+
70
+ class RadioButton < BaseControl
71
+ def check
72
+ driver.ControlCommand(@parent_win.title, @parent_win.text, @control_id, "Check" ,"")
73
+ end
74
+
75
+ def uncheck
76
+ driver.ControlCommand(@parent_win.title, @parent_win.text, @control_id, "UnCheck" ,"")
77
+ end
78
+
79
+ def is_checked?
80
+ driver.ControlCommand(@parent_win.title, @parent_win.text, @control_id, "IsChecked" ,"") == 1
81
+ end
82
+
83
+ end
84
+
85
+ class ComboBox < BaseControl
86
+
87
+ def show_dropdown
88
+ driver.ControlCommand(@parent_win.title, @parent_win.text, @control_id, "ShowDropDown" ,"")
89
+ end
90
+
91
+ def hide_dropdown
92
+ driver.ControlCommand(@parent_win.title, @parent_win.text, @control_id, "HideDropDown" ,"")
93
+ end
94
+
95
+ def select_option(option)
96
+ driver.ControlCommand(@parent_win.title, @parent_win.text, @control_id, "SelectString" , option)
97
+ end
98
+
99
+ end
100
+
101
+
102
+ class Button < BaseControl
103
+ end
104
+
105
+ class Tab < BaseControl
106
+
107
+ def current
108
+ driver.ControlCommand(@parent_win.title, @parent_win.text, @control_id, "CurrentTab" , "")
109
+ end
110
+
111
+ end
112
+
113
+ class ListView < BaseControl
114
+
115
+ def item_count
116
+ result = driver.ControlListView(@parent_win.title, @parent_win.text, @control_id, "GetItemCount" , "", "").to_i
117
+ result ? result.to_i : 0
118
+ end
119
+
120
+ # row and column index starts from 0,
121
+ def get_item_text(row, col = 0)
122
+ driver.ControlListView(@parent_win.title, @parent_win.text, @control_id, "GetText" , "#{row}", col)
123
+ end
124
+
125
+ # can't use select, as it is Ruby keyword
126
+ def highlight(row_start, row_end = nil)
127
+ row_end ||= row_start
128
+ driver.ControlListView(@parent_win.title, @parent_win.text, @control_id, "Select" , "#{row_start}", "#{row_end}")
129
+ end
130
+
131
+ def de_highlight(row_start, row_end = nil)
132
+ row_end ||= row_start
133
+ driver.ControlListView(@parent_win.title, @parent_win.text, @control_id, "DeSelect" , "#{row_start}", "#{row_end}")
134
+ end
135
+ alias de_select de_highlight
136
+
137
+ def subitem_count
138
+ result = driver.ControlListView(@parent_win.title, @parent_win.text, @control_id, "GetSubItemCount" , "", "").to_i
139
+ result ? result.to_i : 0
140
+ end
141
+
142
+ def select_all
143
+ driver.ControlListView(@parent_win.title, @parent_win.text, @control_id, "SelectAll" , "", "")
144
+ end
145
+
146
+ def is_selected?(row)
147
+ 1 == driver.ControlListView(@parent_win.title, @parent_win.text, @control_id, "IsSelected" , "#{row}", "")
148
+ end
149
+
150
+ end
151
+
152
+
153
+ end
@@ -0,0 +1,80 @@
1
+ require 'win32ole'
2
+
3
+ module RFormSpec
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
+ if keys =~ /^Ctrl\+([A-Z])$/
52
+ filtered_keys = "^+#{$1}"
53
+ elsif keys =~ /^Ctrl\+Shift\+([A-Z])$/
54
+ filtered_keys = "^+#{$1.downcase}"
55
+ elsif keys =~ /^Alt+([A-Z])$/
56
+ filtered_keys = "!+#{$1}"
57
+ elsif keys =~ /^Alt\+Shift\+([a-z])$/
58
+ filtered_keys = "!+#{$1.downcase}"
59
+ else
60
+ filtered_keys = keys
61
+ end
62
+ filtered_keys = keys.gsub("Alt+", "!+").gsub("Ctrl+", "^+")
63
+ RFormSpec::Keyboard.press(filtered_keys)
64
+ sleep 0.5
65
+ end
66
+ alias press_key key_press
67
+
68
+ # standard open file dialog
69
+ def open_file_dialog(title, filepath)
70
+ wait_and_focus_window(title)
71
+ dialog = RFormSpec::OpenFileDialog.new(title)
72
+ dialog.enter_filepath(filepath)
73
+ sleep 1
74
+ dialog.click_open
75
+ end
76
+
77
+ #TODO: save as file dialog
78
+
79
+ end
80
+ 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 RFormSpec
9
+ class FormTestCase < Test::Unit::TestCase
10
+ include RFormSpec::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 RFormSpec
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 RFormSpec
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 RFormSpec
2
+ class OpenFileDialog < RFormSpec::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 RFormSpec
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 RFormSpec
2
+ class SaveasFileDialog < RFormSpec::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,104 @@
1
+ require File.dirname(__FILE__) + "/driver"
2
+ require File.dirname(__FILE__) + "/control"
3
+
4
+ module RFormSpec
5
+
6
+
7
+ class Window < BaseControl
8
+ attr_accessor :title, :text
9
+
10
+ def initialize(title, text = '', timeout = 10, options = {:wait => true})
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
+ if options[:wait] then
25
+ result = driver.WinWaitActive(@title, @text, timeout)
26
+ else
27
+ result = driver.WinActivate(@title, @text)
28
+ end
29
+ raise "timeout while waiting for window: #{self.to_s}" if result == 0
30
+ end
31
+
32
+ def focus
33
+ driver.WinActivate(@title, @text)
34
+ end
35
+
36
+ def close
37
+ driver.WinClose(@title, @text)
38
+ end
39
+
40
+ def exists?
41
+ driver.WinExists(@title, @text)
42
+ end
43
+
44
+ def get_text
45
+ driver.WinGetText(@title, @text)
46
+ end
47
+
48
+ def set_control_text(control_id, new_text)
49
+ BaseControl.new(self, control_id).set_text(new_text)
50
+ end
51
+
52
+ def click_button(btn_id)
53
+ Button.new(self, btn_id).click
54
+ end
55
+
56
+ def show_dropdown(combo_id)
57
+ combo = ComboBox.new(self, combo_id)
58
+ combo.show_dropdown
59
+ combo
60
+ end
61
+
62
+ def hide_dropdown(combo_id)
63
+ combo = ComboBox.new(self, combo_id)
64
+ combo.hide_dropdown
65
+ combo
66
+ end
67
+
68
+ def focus_control(ctrl_id)
69
+ BaseControl.new(self, ctrl_id).focus
70
+ end
71
+
72
+ def send_control_text(ctrl_id, text)
73
+ BaseControl.new(self, ctrl_id).send_text(text)
74
+ end
75
+
76
+ def get_control_text(ctrl_id)
77
+ BaseControl.new(self, ctrl_id).get_text
78
+ end
79
+
80
+ #Not fully verified yet
81
+ def statusbar_text
82
+ driver.StatusbarGetText(@title)
83
+ end
84
+
85
+ def pixel_color(x,y)
86
+ driver.PixelGetColor(x,y)
87
+ end
88
+ alias pixel_colour pixel_color
89
+ alias get_pixel_colour pixel_color
90
+ alias get_pixel_color pixel_color
91
+
92
+
93
+ def to_s
94
+ "Window{title => '#{@title}', text=>'#{@text}'}"
95
+ end
96
+
97
+ # a list
98
+ def button(button_id)
99
+ RFormSpec::Button.new(self, button_id)
100
+ end
101
+
102
+ end
103
+
104
+ end
data/lib/rformspec.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__) + "/rformspec/driver"
8
+ require File.dirname(__FILE__) + "/rformspec/control"
9
+ require File.dirname(__FILE__) + "/rformspec/mouse"
10
+ require File.dirname(__FILE__) + "/rformspec/keyboard"
11
+ require File.dirname(__FILE__) + "/rformspec/window"
12
+ require File.dirname(__FILE__) + "/rformspec/open_file_dialog"
13
+ require File.dirname(__FILE__) + "/rformspec/saveas_file_dialog"
14
+ require File.dirname(__FILE__) + "/rformspec/process"
15
+ require File.dirname(__FILE__) + "/rformspec/form_testcase"
data/sample/calc.rb ADDED
@@ -0,0 +1,25 @@
1
+ require 'rformspec'
2
+
3
+ module Calc
4
+ include RFormSpec::Driver
5
+
6
+ def start_calc
7
+ RFormSpec::Process.run("calc.exe")
8
+ RFormSpec::Window.new('Calculator')
9
+ end
10
+
11
+ def find_existing_calc_win
12
+ if window_exists?("Calculator")
13
+ focus_window('Calculator')
14
+ RFormSpec::Window.new('Calculator')
15
+ else
16
+ nil
17
+ end
18
+ end
19
+
20
+ def quit_calc
21
+ focus_window('Calculator')
22
+ RFormSpec::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 'rformspec'
2
+
3
+ include RFormSpec::Driver
4
+
5
+ RFormSpec::Process.run("C:\\WINDOWS\\NOTEPAD.EXE")
6
+ notepad_win = RFormSpec::Window.new('Untitled - Notepad')
7
+ RFormSpec::Keyboard.type("Hello, Missing No. 5.{ENTER}1 2 3 4 6 7 8 9 10{ENTER}")
8
+ RFormSpec::Keyboard.press("+{UP 2}")
9
+
10
+ # move cursor up and insert the missing number
11
+ RFormSpec::Mouse.move_to(70, 65)
12
+ RFormSpec::Mouse.click
13
+ RFormSpec::Keyboard.type("5 ")
14
+
15
+ notepad_win.close
16
+
17
+ notepad_confirm_dialog = RFormSpec::Window.new('Notepad', 'The text')
18
+ notepad_confirm_dialog.focus
19
+ RFormSpec::Button.new(notepad_confirm_dialog, "7").click
@@ -0,0 +1,14 @@
1
+ require 'rformspec'
2
+
3
+ include RFormSpec::Driver
4
+
5
+ RFormSpec::Process.run("C:\\WINDOWS\\NOTEPAD.EXE")
6
+ notepad_win = RFormSpec::Window.new('Untitled - Notepad')
7
+ RFormSpec::Keyboard.type("Hello from Notepad, {ENTER}1 2 3 4 5 6 7 8 9 10{ENTER}")
8
+ sleep(0.5)
9
+ RFormSpec::Keyboard.press("+{UP 2}")
10
+ sleep(0.5)
11
+ notepad_win.close
12
+
13
+ notepad_confirm_dialog = RFormSpec::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 'rformspec'
2
+
3
+ class CalcTest < RFormSpec::FormTestCase
4
+
5
+ def setup
6
+ RFormSpec::Process.run("calc.exe")
7
+ @calc_win = RFormSpec::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,88 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rformspec
3
+ version: !ruby/object:Gem::Version
4
+ hash: 23
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 3
9
+ - 2
10
+ version: 0.3.2
11
+ platform: x86-mingw32
12
+ authors:
13
+ - Zhimin Zhan
14
+ autorequire: rformspec
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-01-04 00:00:00 +00:00
19
+ default_executable:
20
+ dependencies: []
21
+
22
+ description:
23
+ email: zhimin@agileway.com.au
24
+ executables: []
25
+
26
+ extensions: []
27
+
28
+ extra_rdoc_files: []
29
+
30
+ files:
31
+ - Rakefile
32
+ - README
33
+ - CHANGELOG
34
+ - MIT-LICENSE
35
+ - lib/ext/rspec_rformunit.rb
36
+ - lib/rformspec/control.rb
37
+ - lib/rformspec/driver.rb
38
+ - lib/rformspec/form_testcase.rb
39
+ - lib/rformspec/keyboard.rb
40
+ - lib/rformspec/mouse.rb
41
+ - lib/rformspec/open_file_dialog.rb
42
+ - lib/rformspec/process.rb
43
+ - lib/rformspec/saveas_file_dialog.rb
44
+ - lib/rformspec/window.rb
45
+ - lib/rformspec.rb
46
+ - sample/calc.rb
47
+ - sample/calc_spec.rb
48
+ - sample/notepad.rb
49
+ - sample/notepad1.rb
50
+ - sample/rspec_calc.rb
51
+ - sample/test_calc.rb
52
+ - docs/index.html
53
+ has_rdoc: true
54
+ homepage: http://github.com/zhimin/rformspec
55
+ licenses: []
56
+
57
+ post_install_message:
58
+ rdoc_options: []
59
+
60
+ require_paths:
61
+ - lib
62
+ required_ruby_version: !ruby/object:Gem::Requirement
63
+ none: false
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ hash: 3
68
+ segments:
69
+ - 0
70
+ version: "0"
71
+ required_rubygems_version: !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ hash: 3
77
+ segments:
78
+ - 0
79
+ version: "0"
80
+ requirements:
81
+ - none
82
+ rubyforge_project:
83
+ rubygems_version: 1.3.7
84
+ signing_key:
85
+ specification_version: 3
86
+ summary: An wrap of AUTOIT3 for functional testing of Windows form applications
87
+ test_files: []
88
+