測試對於一個應用系統來說是非常關鍵的,但沌單元測方式(XUnit)的方式在B/S結構的信息管理系統中仍然有一些不足,比如要測試界面元素,網頁導行方面,就需要其它的一些測試架框作為輔助,這兩天開始查找並學習了一些網站測試方面的框架。 把學習心得發出來與大家工享。
一、幾種常用框架的介紹。
1、NUnitAsp 官方網址:http://nunitASP.sourceforge.Net/
優點:可以在測試代碼中直接使用使用調用網頁中的服務器控件。並獲取該控件的屬性。
缺點:不夠靈活。正如他的官方網上所說的:
NUnitAsp is for unit testing ASP.NET code-behind only. It''s meant for programmers, not QA teams, and it''s not very good for QA-style acceptance tests. It only tests server-side logic. JavaScript and other clIEnt-side code is ignored. But if you''re using ASP.Net, it''s an essential part of your programmers'' toolset.
NUnitASP 主要是對後台代碼進行單元測試,即它主要是用於測試服務端的邏輯,JavaScript和其它的客戶端代碼是被忽略的。
2、WatiN 官方網址:http://watin.sourceforge.Net/
優點:非常靈活,可以模擬用戶在客戶端浏覽器中的大部份操作,API也比較簡單。
缺點:文檔較少,官方網上的例子也很少。
因為我的目的是測試網站裡網頁的導行,主要就是要模擬用戶的操作,因此選擇了使用WatiN。下面的內容也主要是講述它的使用。
二、最簡單的例子
下面先看一下官司方網站上給出的一個最簡單的例子。
[Test]
public void SearchForWatiNOnGoogle()
...{
/**//*這一句代碼會打開一個IE浏覽器,打開www.google.com網址。
*在創建軍了IE對象以後也可以用IE.GoTo(url);來轉到其它網址。
*/
using (IE ie = new IE("http://www.google.com"))
...{
/**//*在浏覽器中查找name屬性為"q"的輸入控件,然後調用它的TypeText方法
*模擬用戶用鍵盤輸入"WatiN"
*注意TypeText方法是真的模擬用戶一個一個字母地輸入進這個輸入框的。
*如果只是想設置該控件的內容可以把這句改為:
*ie.TextFIEld(Find.ByName("q")).Value="WatiN";
*/
ie.TextFIEld(Find.ByName("q")).TypeText("WatiN");
IE.Button(Find.ByName("btnG")).Click();
Assert.IsTrue(IE.ContainsText("WatiN"));
}
}
這段代碼的作用是模仿用戶打開IE浏覽器到GOOGLE網站查詢WatiN的內容,然後確定有沒有打到這些信息。
三、WatiN 裡常用的類
WatiN.Core.Find
最普遍使用的類就是Find類的,它是一個工廠類,主要使用它的靜態方法來實現一些查詢條件。比如像上面的例子中的這個語句“IE.Button(Find.ByName("btnG")).Click();”就調用了Find的靜態方法ByName來查詢一個name屬性為指定值的Html元素,然後再調用IE對象的Button方法把這個元素轉換為按鈕對象。
WatiN.Core.IE
這應該是最關鍵的類了。他常用的方法是和屬性為
屬性
HtmlDialogs 返回當前對象用JavaScript打開的模式窗口(需然幫助文檔中說非模式窗口也包括在內,但在試用中發現用window.open打開的窗口沒有被)
Frames 返回當前的象裡的所有Frames
方法
靜態方法 AttachToIE 與一個已經找開的IE關連。
Button,TextField,Image,Div 等一系列方法。與Find對象共同使用用於返回IE中特定的按鈕,輸入框,等Html元素。
四、應用中的一些技巧
1、如何去捕獲一個新彈出的窗口。
背景:有些鏈接是從一個新彈出的窗口中打開的,我如果關連上這類型的窗口。
方案:下面以一個具體例子為例。系統中有一個登陸界面:login.ASPx 登陸成功能後會調用JavaSCRIPT的window.open方法打開系統的主窗口,然後關閉當前這個窗login.ASPx。
剛開始時,我的代碼是這樣寫的
public void Login(string uid,string passwd)
...{
string url=Host+"login.ASPx";
ie = new IE();
IE.GoTo(url);
IE.WaitForComplete();
ie.TextFIEld(Find.ById("txtUserName")).Value=uid;
ie.TextFIEld(Find.ById("txtPwd")).Value=passwd;
IE.Button(Find.ById("btnLogin")).Click;//注意這裡,我每次執行到這裡都出錯。下面會說明原因。
ie = IE.AttachToIE(Find.ByTitle(new WatiN.Core.Comparers.RegexComparer(new System.Text.RegularExpressions.Regex(".*綜合信息系統.*"))));
IE.WaitForComplete();
MainFrame = IE.Frame(Find.ByName("MainFrame_00001"));
MenuFrame = IE.Frame(Find.ById("leftMenu"));
}
看到上面的注譯沒有?那麼執行完後WatiN都會出現一個等待完成超時的異常,這是因為點擊了登陸按鈕後,如果登陸成功的話,系統已經把這個窗口關閉了,因為它根本不可能完成。呵呵~~```所以要修改一下。
public void Login(string uid,string passwd)
...{
string url=Host+"frmlogon.ASPx";
ie = new IE();
IE.GoTo(url);
IE.WaitForComplete();
ie.TextFIEld(Find.ById("txtUserName")).Value=uid;
ie.TextFIEld(Find.ById("txtPwd")).Value=passwd;
ie.Button(Find.ById("btnLogin")).ClickNoWait();//這個方法改成這樣,那點擊後就不會等代碼IE完成了。
//下面這句就是處理登陸的技巧所在,系統打開了另一個窗口。
//下面這句就是用正則表達式捕獲這個窗口。
ie = IE.AttachToIE(Find.ByTitle(new WatiN.Core.Comparers.RegexComparer(new System.Text.RegularExpressions.Regex(".*綜合信息系統.*"))));
IE.WaitForComplete();
MainFrame = IE.Frame(Find.ByName("MainFrame_00001"));
MenuFrame = IE.Frame(Find.ById("leftMenu"));//把系統裡的Frame先保存下來。
}
2、對於alert 、confirm 等Javascript彈出的窗口的捕獲。
背景:一個系統經常會使用以上這些Javascript來彈出一些提示信息,如果捕獲這些窗口,並模擬用戶點擊這些窗口上的OK或Cancel按鈕?
方案:其實WatiN在默認情況下,都會自動地去點擊這些彈出式窗口上的Cancel按鈕的,但如果用戶要明確點擊哪些事件的話可以對IE對象增加一個“查看器”()
//錯誤事例
protected void f()
...{
WatiN.Core.DialogHandlers.ConfirmDialogHandler dh = new WatiN.Core.DialogHandlers.ConfirmDialogHandler();
IE.AddDialogHandler(dh);//這句增加了一個控制器
/**//*
假設yzp_dic_btn_cls這個按鈕的onclick事件會用JS彈出一個Confirm窗口。
錯誤,測會在這裡彈出一個窗口,然後等待用戶進行操作(隨便點擊一個按鈕才繼續執行)
然後因為用戶已經點擊了按鈕關閉 彈出窗口。下一句的dh.WaitUntilExists(3);將會超時,拋出異常
*/
doc.Button(Find.ByName("yzp_dic_btn_cls")).Click();
dh.WaitUntilExists(3);//等待彈出窗口的出來。最多等三秒。
dh.OKButton.Click();//點擊這個窗口的OK按鈕
IE.RemoveDialogHandler(dh);
doc.Button(Find.ByName("btn_close")).Click();
}
正確的示例應該是:
protected void f()
...{
WatiN.Core.DialogHandlers.ConfirmDialogHandler dh = new WatiN.Core.DialogHandlers.ConfirmDialogHandler();
IE.AddDialogHandler(dh);
doc.Button(Find.ByName("yzp_dic_btn_cls")).ClickNoWait();//把原來的Click改成這個方法。
dh.WaitUntilExists(3);//等待彈出窗口的出來。最多等三秒。
dh.OKButton.Click();//點擊這個窗口的OK按鈕
IE.RemoveDialogHandler(dh);
doc.Button(Find.ByName("btn_close")).Click();
}
3、關於用JS彈出的Modal窗口(模式窗口)的處理.
背景:有些地方需要彈出模式窗口來處理數據。
方解:當點擊了彈出模式窗口的按鈕或連接後馬上用IE對像的HtmlDialogs屬生來獲取模式窗口。
protected void f()
...{
//假設下面這行代碼會彈出一個模式窗口把原來的Click改成這個方法。
//記住這裡要用ClickNoWait而不能用Click,否則在模式窗口關閉之前代碼不會繼續執行。
IE.Button(Find.ByName("yzp_dic_btn_cls")).ClickNoWait();
ie.HtmlDialogs[IE.HtmlDialogs.Length-1].TextFIEld(Find.ByName("Q")).Value="Hello";
ie.HtmlDialogs[IE.HtmlDialogs.Length-1].Button(Find.ByName("btn_query")).Click();
}
總結
這個框架還是比較簡單,主要要主意的事情就是Html元素的Click與ClickNoWait方法的區別。還有對於輸入框,是直接設置它的Value還是調用TypeText或AppendText方法模擬用戶手工輸入內容。前者不會激發該控件的任何JS事件,而後者會激KeyDown、KeyUP等事件。