电竞比分网-中国电竞赛事及体育赛事平台

分享

[小北De編程手記](méi) : Lesson 07

 黃金屋1 2019-12-11

  在實(shí)際的自動(dòng)化測(cè)試過(guò)程中,我們會(huì)遇見(jiàn)許多需要對(duì)窗口進(jìn)行處理的情況。比如,點(diǎn)擊刪除某條信息的時(shí)候系統(tǒng)會(huì)顯示一個(gè)Alert框?;蛘唿c(diǎn)擊某個(gè)超鏈接時(shí)會(huì)在瀏覽器中打開(kāi)一個(gè)新的頁(yè)面。這一篇,來(lái)和大家分享一下Selenium WebDriver窗口處理相關(guān)的API。那么,還是照例先看一下本文主要涉及到的話題:

  • 窗口處理接口:ITargetLocator
  • 瀏覽器彈出窗口的處理(新頁(yè)面)
  • JavaScript彈出框的處理:Alert, Confirm, Prompt
  • 內(nèi)嵌框架的處理:Frame , iFrame

(一)窗口處理接口:ITargetLocator

  Selenium WebDriver處理窗口能力主要是由WebDriver對(duì)象的SwitchTo()方法返回的對(duì)象提供的。該對(duì)象實(shí)現(xiàn)了ITargetLocator接口,也基本涵蓋了本文所有描述的所有情況(即對(duì)彈出窗口,JS模態(tài)窗口,內(nèi)嵌框架的處理)。我們可以通過(guò)以下代碼獲取當(dāng)前驅(qū)動(dòng)的ITargetLocator對(duì)象:

復(fù)制代碼
 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         }
復(fù)制代碼

  ITargetLocator接口的定義如下所示,這里我先簡(jiǎn)要的介紹一下這些方法的作用(本文后面會(huì)逐個(gè)介紹):

  • ActiveElement:獲取當(dāng)前焦點(diǎn)所在的元素,如果沒(méi)有持有焦點(diǎn)的元素將返回Body元素(這個(gè)方法與窗口處理無(wú)關(guān))。
  • Alert:切換到JS彈出的模態(tài)窗口。
  • DefaultContent:獲取第一個(gè)頁(yè)面上的Frame,當(dāng)有iFrames的時(shí)候?qū)@取主頁(yè)面的Document。
  • Frame:此方法有三個(gè)重載的實(shí)現(xiàn),用來(lái)切換到到Frame。
  • ParentFrame:選中獲取當(dāng)前頁(yè)面的父輩Frame。
  • Window:切換窗口。
復(fù)制代碼
 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     }
復(fù)制代碼

 

(二)瀏覽器彈出窗口的處理(新頁(yè)面)

  如上一小節(jié)所述,Selenium WebDriver對(duì)彈出窗口的處理主要是通過(guò)ITargetLocator.Window方法。下面我就來(lái)向大家介紹一下Selenium WebDriver中常用的窗口定位方式:

  • 用窗口名稱定位
  • 結(jié)合標(biāo)題和窗口句柄定位頁(yè)面

@用窗口名稱定位

  參照ITargetLocator.Window方法的定義,該方法接受一個(gè)窗口的名稱。因此我們可以通過(guò)窗口的名稱切換到該窗口(前提是開(kāi)發(fā)人員定義了這個(gè)窗口的名字):

復(fù)制代碼
1             // 1. 獲取窗口定位對(duì)象
2             IWebDriver driver = new FirefoxDriver();
3             //省略部分代碼... ...
4             ITargetLocator locator = driver.SwitchTo();
5             driver = locator.Window("windowName");
6             //后續(xù)操作... ...
7             driver.Quit();
復(fù)制代碼

  我們可以通過(guò)上面的代碼切換窗口,但是問(wèn)題來(lái)了,我們?cè)趺传@取到窗口的名字呢?所有的瀏覽器都有執(zhí)行JS腳本的命令行工具,我們只需要輸入“window.name”便可以看見(jiàn)當(dāng)前窗口的名字了,下圖是我在Firebug中的操作:

@結(jié)合標(biāo)題和窗口句柄定位頁(yè)面

  很多情況下,開(kāi)發(fā)人員是不會(huì)為每一個(gè)彈出的窗口定義名稱的(實(shí)際上也沒(méi)有這個(gè)必要)。那么,我們就需要用其他的方式來(lái)定位我們的目標(biāo)窗口了,下面的代碼使用了窗口句柄和標(biāo)題定位需要訪問(wèn)的窗口,我們可以通過(guò)WebDriver對(duì)象的WindowHandles屬性獲取當(dāng)前瀏覽器打開(kāi)的所有句柄,在根據(jù)頁(yè)面的特定條件(這里是用的標(biāo)題)來(lái)判斷哪一個(gè)句柄是需要操作的界面句柄。一般的情況下,我們需要保存當(dāng)前的頁(yè)面句柄,這樣可以方便后操作完成之后能準(zhǔn)確的返回當(dāng)前頁(yè)面。Demo的最后驗(yàn)證了操作頁(yè)面的標(biāo)題是否正確,代碼如下:

復(fù)制代碼
 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編程手記](méi) : Lesson 02 - Selenium For C# 之 核心對(duì)象";
 8 
 9             _output.WriteLine("Step 01 : 啟動(dòng)瀏覽器并打開(kāi)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)擊鏈接打開(kāi)新頁(yè)面。");
14             var lnkArticle02 = driver.FindElement(By.LinkText(articleName));
15             lnkArticle02.Click();
16 
17             _output.WriteLine("Step 03 : 根據(jù)標(biāo)題獲取新頁(yè)面的句柄。");
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)證新頁(yè)面標(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         }
復(fù)制代碼

   值得說(shuō)明的是,第22行代碼使用了Title的內(nèi)容做為判斷是否是新開(kāi)的頁(yè)面的條件,這里你也可以根據(jù)實(shí)際的需要使用Url或是頁(yè)面內(nèi)容... ...等其他條件進(jìn)行判斷。

(三)JavaScript彈出框的處理

  稍有Web編程經(jīng)驗(yàn)的人都應(yīng)該知道JavaScript可以彈出模態(tài)對(duì)話框。在介紹處理這些彈出的窗體之前我們先回顧一下瀏覽器內(nèi)置的彈出框都有哪些類型:

  • Alert:只有文字和一條提示信息以及一個(gè)確認(rèn)按鈕(用于提示用戶)。
  • Confirm:較Alert多了一個(gè)取消按鈕(用于向用戶確認(rèn)信息)。
  • Prompt:較Confirm多了一個(gè)文本輸入框(向用戶確認(rèn)信息的同時(shí)可以獲取用戶輸入)
  • AuthenticationCredentials:用于輸入用戶名和密碼的窗口(下圖中沒(méi)有給出)。

  好了,現(xiàn)在我們開(kāi)始介紹如何處理這些彈出框。上面我們提到過(guò)ITargetLocator.Alert方法可以用來(lái)處理模態(tài)窗口。該方法的返回對(duì)象實(shí)現(xiàn)了IAlert接口:

復(fù)制代碼
 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     }
復(fù)制代碼

  在此,需要澄清一下,之前介紹的四種彈出窗口都是用實(shí)現(xiàn)了IAlert接口的對(duì)象描述的(也就是說(shuō)Confirm,Prompt,AuthenticationCredentials都可以用實(shí)現(xiàn)了IAlert接口的對(duì)象進(jìn)行處理):

  • Text:獲取彈出框文本信息(適用于所有模態(tài)窗口)  
  • Accept:點(diǎn)擊確定按鈕(適用于所有模態(tài)窗口)
  • Dismiss:點(diǎn)擊取消按鈕(適用于Confirm,Prompt,AuthenticationCredentials)
  • SendKeys:輸入文本信息(適用于Prompt)
  • SetAuthenticationCredentials:設(shè)置用戶名和密碼(適用于AuthenticationCredentials)

  是不是 so... ... easy? 下面還是照例看一下具體的使用代碼:

1       IAlert alert = driver.SwitchTo().Alert();   //轉(zhuǎn)到彈出框
2       alert.Accept();                             //確定:Alert , Confirm, Prompt
3       alert.Dismiss();                            //取消:Confirm, Prompt
4       var text = alert.Text;                      //獲取提示內(nèi)容:Alert , Confirm, Prompt
5       alert.SendKeys("input text.");              //輸入提示文本:Prompt

(四)內(nèi)嵌框架的處理

  本文的最后,我來(lái)介紹一下關(guān)于網(wǎng)頁(yè)內(nèi)嵌框架的處理。早期的一些B/S系統(tǒng)會(huì)用iFrame和Frame進(jìn)行布局和頁(yè)面的嵌套。之前也有利用iFrame構(gòu)建全局彈出框的設(shè)計(jì)方式。因此,如果你們的產(chǎn)品已經(jīng)有多年的歷史。那么,你可能會(huì)需要處理這部分的內(nèi)容。其實(shí)Frame和iFrame的處理和窗口很類似,這里我簡(jiǎn)單的給出一個(gè)Demo:

復(fù)制代碼
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();
復(fù)制代碼

  從上面的代碼中可以看到,可以使用index,frame name,或者frame對(duì)象把Driver切換到Frame上。

 

總結(jié):本文主要介紹如何利用Selenium WebDriver核心的ITargetLocator接口處理各種窗口。

  • 窗口處理接口:ITargetLocator
  • 瀏覽器彈出窗口的處理(新頁(yè)面)
  • JavaScript彈出框的處理:Alert, Confirm, Prompt
  • 內(nèi)嵌框架的處理:Frame , iFrame

《Selenium For C#》的相關(guān)文章:Click here.

說(shuō)明:Demo地址:https://github.com/DemoCnblogs/Selenium

 

如果您認(rèn)為這篇文章還不錯(cuò)或者有所收獲,可以點(diǎn)擊右下角的【推薦】按鈕,因?yàn)槟愕闹С质俏依^續(xù)寫(xiě)作,分享的最大動(dòng)力!
作者:小北@North
來(lái)源:http://www.cnblogs.com/NorthAlan
聲明:本博客原創(chuàng)文字只代表本人工作中在某一時(shí)間內(nèi)總結(jié)的觀點(diǎn)或結(jié)論,與本人所在單位沒(méi)有直接利益關(guān)系。非商業(yè),未授權(quán),貼子請(qǐng)以現(xiàn)狀保留,轉(zhuǎn)載時(shí)必須保留此段聲明,且在文章頁(yè)面明顯位置給出原文連接。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多