在實(shí)際的自動(dòng)化測(cè)試過程中,我們會(huì)遇見許多需要對(duì)窗口進(jìn)行處理的情況。比如,點(diǎn)擊刪除某條信息的時(shí)候系統(tǒng)會(huì)顯示一個(gè)Alert框?;蛘唿c(diǎn)擊某個(gè)超鏈接時(shí)會(huì)在瀏覽器中打開一個(gè)新的頁面。這一篇,來和大家分享一下Selenium WebDriver窗口處理相關(guān)的API。那么,還是照例先看一下本文主要涉及到的話題:
Selenium WebDriver處理窗口能力主要是由WebDriver對(duì)象的SwitchTo()方法返回的對(duì)象提供的。該對(duì)象實(shí)現(xiàn)了ITargetLocator接口,也基本涵蓋了本文所有描述的所有情況(即對(duì)彈出窗口,JS模態(tài)窗口,內(nèi)嵌框架的處理)。我們可以通過以下代碼獲取當(dāng)前驅(qū)動(dòng)的ITargetLocator對(duì)象:
1 /// <summary> 2 /// demo1 : 獲取目標(biāo)定位對(duì)象 3 /// </summary> 4 [Fact(DisplayName = "Cnblogs.WindowProcess.Demo1", Skip = "Just Demo")] 5 public void WindowProcess_Demo1() 6 { 7 // 1. 獲取窗口定位對(duì)象 8 IWebDriver driver = new FirefoxDriver(); 9 //省略部分代碼... ...10 ITargetLocator locator = driver.SwitchTo();11 //后續(xù)操作... ...12 driver.Close();13 }
ITargetLocator接口的定義如下所示,這里我先簡(jiǎn)要的介紹一下這些方法的作用(本文后面會(huì)逐個(gè)介紹):
1 // Summary: 2 // Defines the interface through which the user can locate a given frame or 3 // window. 4 public interface ITargetLocator 5 { 6 IWebElement ActiveElement(); 7 IAlert Alert(); 8 IWebDriver DefaultContent(); 9 IWebDriver Frame(int frameIndex);10 IWebDriver Frame(IWebElement frameElement);11 IWebDriver Frame(string frameName);12 IWebDriver ParentFrame();13 IWebDriver Window(string windowName);14 }
如上一小節(jié)所述,Selenium WebDriver對(duì)彈出窗口的處理主要是通過ITargetLocator.Window方法。下面我就來向大家介紹一下Selenium WebDriver中常用的窗口定位方式:
參照ITargetLocator.Window方法的定義,該方法接受一個(gè)窗口的名稱。因此我們可以通過窗口的名稱切換到該窗口(前提是開發(fā)人員定義了這個(gè)窗口的名字):
1 // 1. 獲取窗口定位對(duì)象2 IWebDriver driver = new FirefoxDriver();3 //省略部分代碼... ...4 ITargetLocator locator = driver.SwitchTo();5 driver = locator.Window("windowName");6 //后續(xù)操作... ...7 driver.Quit();
我們可以通過上面的代碼切換窗口,但是問題來了,我們?cè)趺传@取到窗口的名字呢?所有的瀏覽器都有執(zhí)行JS腳本的命令行工具,我們只需要輸入“window.name”便可以看見當(dāng)前窗口的名字了,下圖是我在Firebug中的操作:
很多情況下,開發(fā)人員是不會(huì)為每一個(gè)彈出的窗口定義名稱的(實(shí)際上也沒有這個(gè)必要)。那么,我們就需要用其他的方式來定位我們的目標(biāo)窗口了,下面的代碼使用了窗口句柄和標(biāo)題定位需要訪問的窗口,我們可以通過WebDriver對(duì)象的WindowHandles屬性獲取當(dāng)前瀏覽器打開的所有句柄,在根據(jù)頁面的特定條件(這里是用的標(biāo)題)來判斷哪一個(gè)句柄是需要操作的界面句柄。一般的情況下,我們需要保存當(dāng)前的頁面句柄,這樣可以方便后操作完成之后能準(zhǔn)確的返回當(dāng)前頁面。Demo的最后驗(yàn)證了操作頁面的標(biāo)題是否正確,代碼如下:
1 /// <summary> 2 /// demo2 : 根據(jù)標(biāo)題定位元素 3 /// </summary> 4 [Fact(DisplayName = "Cnblogs.WindowProcess.Demo2")] 5 public void WindowProcess_Demo2() 6 { 7 var articleName = "[小北De編程手記] : Lesson 02 - Selenium For C# 之 核心對(duì)象"; 8 9 _output.WriteLine("Step 01 : 啟動(dòng)瀏覽器并打開Lesson 01 - Selenium For C#");10 IWebDriver driver = new FirefoxDriver();11 driver.Url = "http://www.cnblogs.com/NorthAlan/p/5155915.html";12 13 _output.WriteLine("Step 02 : 點(diǎn)擊鏈接打開新頁面。");14 var lnkArticle02 = driver.FindElement(By.LinkText(articleName));15 lnkArticle02.Click();16 17 _output.WriteLine("Step 03 : 根據(jù)標(biāo)題獲取新頁面的句柄。");18 var oldWinHandle = driver.CurrentWindowHandle;19 foreach (var winHandle in driver.WindowHandles)20 {21 driver.SwitchTo().Window(winHandle);22 if (driver.Title.Contains(articleName))23 {24 break;25 }26 }27 28 _output.WriteLine("Step 04 : 驗(yàn)證新頁面標(biāo)題是否正確。");29 var articleTitle = driver.FindElement(By.Id("cb_post_title_url"));30 Assert.Equal<string>(articleName, articleTitle.Text);31 32 _output.WriteLine("Step 05 : 關(guān)閉瀏覽器。");33 driver.Quit();34 }
值得說明的是,第22行代碼使用了Title的內(nèi)容做為判斷是否是新開的頁面的條件,這里你也可以根據(jù)實(shí)際的需要使用Url或是頁面內(nèi)容... ...等其他條件進(jìn)行判斷。
稍有Web編程經(jīng)驗(yàn)的人都應(yīng)該知道JavaScript可以彈出模態(tài)對(duì)話框。在介紹處理這些彈出的窗體之前我們先回顧一下瀏覽器內(nèi)置的彈出框都有哪些類型:
好了,現(xiàn)在我們開始介紹如何處理這些彈出框。上面我們提到過ITargetLocator.Alert方法可以用來處理模態(tài)窗口。該方法的返回對(duì)象實(shí)現(xiàn)了IAlert接口:
1 // Summary: 2 // Defines the interface through which the user can manipulate JavaScript alerts. 3 public interface IAlert 4 { 5 string Text { get; } 6 void Accept(); 7 void Dismiss(); 8 void SendKeys( string keysToSend); 9 void SetAuthenticationCredentials( string userName, string password);10 }
在此,需要澄清一下,之前介紹的四種彈出窗口都是用實(shí)現(xiàn)了IAlert接口的對(duì)象描述的(也就是說Confirm,Prompt,AuthenticationCredentials都可以用實(shí)現(xiàn)了IAlert接口的對(duì)象進(jìn)行處理):
是不是 so... ... easy? 下面還是照例看一下具體的使用代碼:
1 IAlert alert = driver.SwitchTo().Alert(); //轉(zhuǎn)到彈出框2 alert.Accept(); //確定:Alert , Confirm, Prompt3 alert.Dismiss(); //取消:Confirm, Prompt4 var text = alert.Text; //獲取提示內(nèi)容:Alert , Confirm, Prompt5 alert.SendKeys("input text."); //輸入提示文本:Prompt
本文的最后,我來介紹一下關(guān)于網(wǎng)頁內(nèi)嵌框架的處理。早期的一些B/S系統(tǒng)會(huì)用iFrame和Frame進(jìn)行布局和頁面的嵌套。之前也有利用iFrame構(gòu)建全局彈出框的設(shè)計(jì)方式。因此,如果你們的產(chǎn)品已經(jīng)有多年的歷史。那么,你可能會(huì)需要處理這部分的內(nèi)容。其實(shí)Frame和iFrame的處理和窗口很類似,這里我簡(jiǎn)單的給出一個(gè)Demo:
1 ITargetLocator tagetLocator = driver.SwitchTo();2 tagetLocator.Frame(1); //frame index.3 tagetLocator.Frame("frameName"); //frame frame name.4 5 IWebElement frame = driver.FindElement(By .Id("frameId or iframeId" ));6 tagetLocator.Frame(frame);7 tagetLocator.DefaultContent();
從上面的代碼中可以看到,可以使用index,frame name,或者frame對(duì)象把Driver切換到Frame上。
總結(jié):本文主要介紹如何利用Selenium WebDriver核心的ITargetLocator接口處理各種窗口。
《Selenium For C#》的相關(guān)文章:Click here.
說明:Demo地址:https://github.com/DemoCnblogs/Selenium
聯(lián)系客服