5. 異常對象識別(Watir應用解決方案)
Watir基於處理,繼承於web document的對象提供較好的支援方法,但相對於處理windows對象較弱. 就目前從各網站收集的對象來看, 基本上,對於在IE執行個體對象開啟的web標準對象
能夠成功識別與操作,其它的脫離當前IE視窗,開啟的所有彈出框都不能正常識別。其中,彈出框對象佔有異常對象識別中很大一部分。
目前碰到的彈出框, 我把他們分為三大類型:
1, Alerts 警告作用,如:sorry, 目前使用者沒有許可權操作
2, Confirm 需要操作按鈕, 如:你確認要刪除目前記錄?
3, Prompt+ select +confirm 需要使用者輸入,操作查詢或點擊, 最後確認, 如:Download/upload (瀏覽+選擇檔案)
下面給出,上面幾種彈出框watir實現識別與操作的方法,
5.1. 彈出框基於autoIT + 線程實現方式
此種方法,對於第一、二種彈出框操作較有效,
因點擊某個link/button等對象,而彈出的視窗(大部分彈出框可應用此種方式來實現。)
1, 定義方法
def check_for_popups
autoit = WIN32OLE.new('AutoItX3.Control')
#
# Do forever - assumes popups could occur anywhere/anytime in your application.
loop do
# Look for window with given title. Give up after 1 second.
ret = autoit.WinWait('訊息 -- 網頁對話方塊', '', 1)
#ret = WinActivate("Microsoft Internet Explorer", "")
#autoit.ControlClick("Microsoft Internet Explorer", "", "[CLASS:Button; INSTANCE:1]", 2)
puts(ret)
#
# If window found, send appropriate keystroke (e.g. {enter}, {Y}, {N}).
if (ret==1) then autoit.Send("{Enter}") end
#
# Take a rest to avoid chewing up cycles and give another thread a go.
# Then resume the loop.
sleep(3)
end
end
2, 程式體代碼
ie.button(:name, "signin").click_no_wait
sleep(20)
$popup = Thread.new { check_for_popups } # start popup handler
at_exit { Thread.kill($popup) }
5.2. Call 另一ruby檔案
對於第二種彈出框,像安全警告點擊, 並不通過操作與點擊任何對象, 即呈現快顯視窗。
我嘗試用3.1方法來實現,不成功。用下面方法替代:
1, 在watir/WindowHelper.rb檔案中增加方法
def push_security_alert_yes_cn
@autoit.WinWait "安全警報", ""
@autoit.Send "{TAB}"
@autoit.Send "{TAB}"
@autoit.Send "{SPACE}"
End
2, 定義另一調用檔案 tmp.rb
require 'watir/WindowHelper'
helper = WindowHelper.new
helper.push_security_alert_cn_yes
3, 在開啟安全URL之前,啟動調用ruby檔案
require 'rubygems'
require 'watir' # the watir controller
require 'win32ole'
require 'watir/WindowHelper'
Thread.new{system('ruby c:/tmp.rb')} #你定義tmp檔案存放路徑
ie = Watir::IE.new
ie.goto("http://www.alipay.com.cn/")
5.3. 修改架構底層
此種方法,針對彈出框3.
舉例一, 上傳下載檔案
1, 修改底層代碼input_elements.rb檔案,
類 FileField中, 方法set.
為了支援中文,有一句替換修改為:
system("rubyw -e /"require 'win32ole'; @autoit=WIN32OLE.new('AutoItX3.Control');waitresult=@autoit.WinWait'選擇檔案', '', 15; sleep 1; if waitresult == 1/" -e /"@autoit.ControlSetText '選擇檔案', '', 'Edit1', '#{setPath}'; @autoit.ControlSend '選擇檔案', '', 'Button2', '{ENTER}';/" -e /"end/"")
2, 定義方法
def save_file(filepath)
ai = WIN32OLE.new("AutoItX3.Control")
ai.WinWait("檔案下載", "", 5)
ai.ControlFocus("檔案下載", "", "儲存(&S)")
sleep 1
ai.ControlClick("檔案下載", "", "儲存(&S)", "left")
ai.WinWait("另存新檔", "", 5)
sleep 1
ai.ControlSend("另存新檔", "", "Edit1",filepath)
ai.ControlClick("另存新檔", "", "儲存(&S)", "left")
ai.WinWait("下載完畢", "", 5)
ai.ControlClick("下載完畢", "", "關閉")
end
3, 程式體代碼:
ie.file_field(:name, "xlsfile").set("c://samenameobject.html")
#上傳你所指定的檔案
或
ie.span(:text, "匯出Excel表").click_no_wait
save_file("C://abc.xls")
#下載到你所指定的路徑
針對彈出框3, 需要使用者介入查詢並操作:
舉例二, 中供crm中類目與客戶選擇的彈出框,與第一種實現方式不同在於,
用到autoit中WinActivate與ControlClick方法,
require 'rubygems'
require 'watir' # the watir controller
require 'watir/WindowHelper'
require 'win32ole'
def check_for_popups
autoit = WIN32OLE.new('AutoItX3.Control')
loop do
ret = autoit.Winwait("選擇 -- 網頁對話方塊", "", 1)
puts ret
if (ret==1) then
autoit.WinActivate("[CLASS:Internet Explorer_TridentDlgFrame]", "")
autoit.Send("{TAB}")
autoit.Send("{TAB}")
#autoit.Send("湖州")
#autoit.Send("{ASC 2709}")
#autoit.SendUnicode("a")
#autoit.ClipPut ("杭")
#autoit.ClipGet
#autoit.ToolTip "This is a tooltip杭州", 0, 0
#autoit.Sleep 2000
autoit.Send("{TAB}")
autoit.Send("{TAB}")
autoit.Send("{Enter}")
autoit.WinActivate("[CLASS:Internet Explorer_TridentDlgFrame]", "")
autoit.ControlClick("選擇 -- 網頁對話方塊", "", "[CLASS:Internet Explorer_TridentLstBox; INSTANCE:2]", 2)
autoit.Send("{TAB}")
autoit.Send("{Enter}")
autoit.Send("{TAB}")
autoit.Send("{TAB}")
autoit.Send("{TAB}")
autoit.Send("{TAB}")
autoit.Send("{Enter}")
end
sleep(3)
end
end
ie=Watir::IE.new
ie.goto("http://10.2.6.4:5100/bin/member/signin")
#ie.goto("http://10.2.6.4:5100/")
#ie.element_by_xpath("//span[contains(text(), 'Main Road Nijmegen')]").click
ie.text_field(:name, "id").set("mhl1805")
ie.text_field(:name, "password").set("zxcvbnm")
ie.button(:name, "signin").click
ie.frame(:name, "left").link(:url, "http://10.2.6.4:5100/v3/help_cust.htm").click
ie.frame(:name, "left").link(:text, "新簽中供客戶").click
# start popup handler
ie.frame(:name, "right").frame(:name, "rtop").button(:value, "選擇客戶").click_no_wait
sleep(20)
$popup = Thread.new { check_for_popups }
at_exit { Thread.kill($popup) }
針對第三種popup window, 如果需要與使用者互動,且需要輸入中文時,若用autoit sendkey對待中文支援(但官方文檔說支援中文輸入, 網上有不少人和我遇到同樣問題),尚沒有找到有效方案,有待進一步跟進。
除上述彈出框需要特殊處理外,watir中也有一些擴充tag,或第三方控制項需要特殊處理的,
像:
5.4. web HTML編輯器
中文站的html編輯器提供: 操作ID或name操作起來較方便直接
require 'rubygems'
require 'watir' # the watir controller
require 'watir/WindowHelper'
require 'win32ole'
ie=Watir::IE.new
ie=Watir::IE.attach(:title, /阿里助手/)
ie.text_field(:name, "_fmo.a._0.s").set("mhl1805")
ie.document.getElementByid("_editor").contentWindow.focus()
ie.send_keys("abcsadfasfd")
但也碰到有些web頁面,不提供任何ID,只能用autoIT方法來send tab實現
require 'rubygems'
require 'watir' # the watir controller
require 'watir/WindowHelper'
require 'win32ole'
ie=Watir::IE.new
#ie=Watir::IE.attach(:title, /Alibaba/)
ie.goto('http://us.my.alibaba.com/product/buyoffer/post_buying_lead.htm')
ie.text_field(:name, "_fmp.bu._0.su").set("mhl1805")
ie.text_field(:name, "_fmp.bu._0.su").set("中國人")
ie.checkbox(:id, "detailDesc").set
ie.checkbox(:id, "detailDesc").focus()
ie.send_keys("/t"*9)
ie.send_keys('Hello Worldabcdef')
5.5. 對象識別其它常用TAG內建方法引用
如:IE.div , ie.span, ie.cell, ie.table方法,可以實現點擊操作,取值操作等.
另外提供QTP類似描述性編程,同類型對象統計:
ie.buttons.each { |b| puts b.to_s }
puts ie.checkboxes.length
puts ie.links.length
puts ie.buttons.length等等
對於常用的innertext屬性, 在watir中已經封裝到方法,可以直接引用。如:
ruby在對象識別底層,封裝了innertext
實現,調用方法text即可:
如:puts ie.div(:id, "intelligentWord").link(:id, index.to_s).text
最後:返迴文本與原始碼,用下面方法:
puts ie.text()
puts ie.html()
5.6. 識別對象Regex支援
當然,ruby提供強大的Regex支援,如:屬性標識正則
ie=Watir::IE.attach(:title, /Alibaba/)
Ruby的Regex以"//"作為基本架構,運算式內容位於"/"之間。運算式返回一個RegExp的對象。
運算式的一般規則:
/a/匹配字元a。
//?/匹配特殊字元?。特殊字元包括^, $, ? , ., /, /, [, ], {, }, (, ), +, *.
.匹配任一字元,例如/a./匹配ab和ac。
/[ab]c/匹配ac和bc,[]之間代表範圍。例如:/[a-z]/ , /[a-zA-Z0-9]/。
/[^a-zA-Z0-9]/匹配不在該範圍內的字串。
/[/d]/代表任一數字,/[/w]/代表任意字母,數字或者_,/[/s]/代表空白字元,包括空格,TAB和換行。
/[/D]/,/[/W]/,/[/S]/均為上述的否定情況。
關於正則其它用法,請參照《watir技術集錦》
5.7. 最後攻略
總之,對於對象識別與操作,要藉助於上述文檔中的, 靈活運用autoit, xpath與異常對象操作方法。對於watir不支援的windows控制項,想到第一個方法,就是採用第三方autoit技術,來類比鍵盤或滑鼠操作。
對於操作web對象,watir不支援特殊tag,除了擴充其底層代碼外,只能深深研究一下xpath了.
最後,再搞不定,就只能到watir group裡諮詢高人了,呵呵。