[小北De编程手记] : Lesson 07 - Selenium For C# 之 窗口处理

  在实际的自动化测试过程中,我们会遇见许多需要对窗口进行处理的情况。比如,点击删除某条信息的时候系统会显示一个Alert框。或者点击某个超链接时会在浏览器中打开一个新的页面。这一篇,来和大家分享一下Selenium WebDriver窗口处理相关的API。那么,还是照例先看一下本文主要涉及到的话题:

  • 窗口处理接口:ITargetLocator
  • 浏览器弹出窗口的处理(新页面)
  • JavaScript弹出框的处理:Alert, Confirm, Prompt
  • 内嵌框架的处理:Frame , iFrame

(一)窗口处理接口:ITargetLocator

  Selenium WebDriver处理窗口能力主要是由WebDriver对象的SwitchTo()方法返回的对象提供的。该对象实现了ITargetLocator接口,也基本涵盖了本文所有描述的所有情况(即对弹出窗口,JS模态窗口,内嵌框架的处理)。我们可以通过以下代码获取当前驱动的ITargetLocator对象:

 1         /// <summary>
 2         /// demo1 : 获取目标定位对象
 3         /// </summary>
 4         [Fact(DisplayName = "Cnblogs.WindowProcess.Demo1", Skip = "Just Demo")]
 5         public void WindowProcess_Demo1()
 6         {
 7             // 1. 获取窗口定位对象
 8             IWebDriver driver = new FirefoxDriver();
 9             //省略部分代码... ...
10             ITargetLocator locator = driver.SwitchTo();
11             //后续操作... ...
12             driver.Close();
13         }

  ITargetLocator接口的定义如下所示,这里我先简要的介绍一下这些方法的作用(本文后面会逐个介绍):

  • ActiveElement:获取当前焦点所在的元素,如果没有持有焦点的元素将返回Body元素(这个方法与窗口处理无关)。
  • Alert:切换到JS弹出的模态窗口。
  • DefaultContent:获取第一个页面上的Frame,当有iFrames的时候将获取主页面的Document。
  • Frame:此方法有三个重载的实现,用来切换到到Frame。
  • ParentFrame:选中获取当前页面的父辈Frame。
  • Window:切换窗口。
 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     }

(二)浏览器弹出窗口的处理(新页面)

  如上一小节所述,Selenium WebDriver对弹出窗口的处理主要是通过ITargetLocator.Window方法。下面我就来向大家介绍一下Selenium WebDriver中常用的窗口定位方式:

  • 用窗口名称定位
  • 结合标题和窗口句柄定位页面

@用窗口名称定位

  参照ITargetLocator.Window方法的定义,该方法接受一个窗口的名称。因此我们可以通过窗口的名称切换到该窗口(前提是开发人员定义了这个窗口的名字):

1             // 1. 获取窗口定位对象
2             IWebDriver driver = new FirefoxDriver();
3             //省略部分代码... ...
4             ITargetLocator locator = driver.SwitchTo();
5             driver = locator.Window("windowName");
6             //后续操作... ...
7             driver.Quit();

  我们可以通过上面的代码切换窗口,但是问题来了,我们怎么获取到窗口的名字呢?所有的浏览器都有执行JS脚本的命令行工具,我们只需要输入“window.name”便可以看见当前窗口的名字了,下图是我在Firebug中的操作:

@结合标题和窗口句柄定位页面

  很多情况下,开发人员是不会为每一个弹出的窗口定义名称的(实际上也没有这个必要)。那么,我们就需要用其他的方式来定位我们的目标窗口了,下面的代码使用了窗口句柄和标题定位需要访问的窗口,我们可以通过WebDriver对象的WindowHandles属性获取当前浏览器打开的所有句柄,在根据页面的特定条件(这里是用的标题)来判断哪一个句柄是需要操作的界面句柄。一般的情况下,我们需要保存当前的页面句柄,这样可以方便后操作完成之后能准确的返回当前页面。Demo的最后验证了操作页面的标题是否正确,代码如下:

 1         /// <summary>
 2         /// demo2 : 根据标题定位元素
 3         /// </summary>
 4         [Fact(DisplayName = "Cnblogs.WindowProcess.Demo2")]
 5         public void WindowProcess_Demo2()
 6         {
 7             var articleName = "[小北De编程手记] : Lesson 02 - Selenium For C# 之 核心对象";
 8
 9             _output.WriteLine("Step 01 : 启动浏览器并打开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 : 点击链接打开新页面。");
14             var lnkArticle02 = driver.FindElement(By.LinkText(articleName));
15             lnkArticle02.Click();
16
17             _output.WriteLine("Step 03 : 根据标题获取新页面的句柄。");
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 : 验证新页面标题是否正确。");
29             var articleTitle = driver.FindElement(By.Id("cb_post_title_url"));
30             Assert.Equal<string>(articleName, articleTitle.Text);
31
32             _output.WriteLine("Step 05 : 关闭浏览器。");
33             driver.Quit();
34         }

   值得说明的是,第22行代码使用了Title的内容做为判断是否是新开的页面的条件,这里你也可以根据实际的需要使用Url或是页面内容... ...等其他条件进行判断。

(三)JavaScript弹出框的处理

  稍有Web编程经验的人都应该知道JavaScript可以弹出模态对话框。在介绍处理这些弹出的窗体之前我们先回顾一下浏览器内置的弹出框都有哪些类型:

  • Alert:只有文字和一条提示信息以及一个确认按钮(用于提示用户)。
  • Confirm:较Alert多了一个取消按钮(用于向用户确认信息)。
  • Prompt:较Confirm多了一个文本输入框(向用户确认信息的同时可以获取用户输入)
  • AuthenticationCredentials:用于输入用户名和密码的窗口(下图中没有给出)。

  好了,现在我们开始介绍如何处理这些弹出框。上面我们提到过ITargetLocator.Alert方法可以用来处理模态窗口。该方法的返回对象实现了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     }

  在此,需要澄清一下,之前介绍的四种弹出窗口都是用实现了IAlert接口的对象描述的(也就是说Confirm,Prompt,AuthenticationCredentials都可以用实现了IAlert接口的对象进行处理):

  • Text:获取弹出框文本信息(适用于所有模态窗口)  
  • Accept:点击确定按钮(适用于所有模态窗口)
  • Dismiss:点击取消按钮(适用于Confirm,Prompt,AuthenticationCredentials)
  • SendKeys:输入文本信息(适用于Prompt)
  • SetAuthenticationCredentials:设置用户名和密码(适用于AuthenticationCredentials)

  是不是 so... ... easy? 下面还是照例看一下具体的使用代码:

1       IAlert alert = driver.SwitchTo().Alert();   //转到弹出框
2       alert.Accept();                             //确定:Alert , Confirm, Prompt
3       alert.Dismiss();                            //取消:Confirm, Prompt
4       var text = alert.Text;                      //获取提示内容:Alert , Confirm, Prompt
5       alert.SendKeys("input text.");              //输入提示文本:Prompt

(四)内嵌框架的处理

  本文的最后,我来介绍一下关于网页内嵌框架的处理。早期的一些B/S系统会用iFrame和Frame进行布局和页面的嵌套。之前也有利用iFrame构建全局弹出框的设计方式。因此,如果你们的产品已经有多年的历史。那么,你可能会需要处理这部分的内容。其实Frame和iFrame的处理和窗口很类似,这里我简单的给出一个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对象把Driver切换到Frame上。

总结:本文主要介绍如何利用Selenium WebDriver核心的ITargetLocator接口处理各种窗口。

  • 窗口处理接口:ITargetLocator
  • 浏览器弹出窗口的处理(新页面)
  • JavaScript弹出框的处理:Alert, Confirm, Prompt
  • 内嵌框架的处理:Frame , iFrame

《Selenium For C#》的相关文章:Click here.

说明:

  没有超链接的文章写完发表后,我会添加相应的链接,在此先列出目录。

  Demo地址:https://github.com/DemoCnblogs/Selenium

如果您认为这篇文章还不错或者有所收获,可以点击右下角的【推荐】按钮,因为你的支持是我继续写作,分享的最大动力!

作者:小北@North

来源:http://www.cnblogs.com/NorthAlan

声明:本博客原创文字只代表本人工作中在某一时间内总结的观点或结论,与本人所在单位没有直接利益关系。非商业,未授权,贴子请以现状保留,转载时必须保留此段声明,且在文章页面明显位置给出原文连接。

时间: 2024-10-09 22:52:19

[小北De编程手记] : Lesson 07 - Selenium For C# 之 窗口处理的相关文章

[小北De编程手记] : Lesson 08 - Selenium For C# 之 PageFactory &amp; 团队构建

本文想跟大家分享的是Selenium对PageObject模式的支持和自动化测试团队的构建.<Selenium For C#>系列的文章写到这里已经接近尾声了,如果之前的文章你是一篇篇的读下来并动手实践的话,我相信你应该可以模拟日常工作中80%常见的手动测试用例了.请注意:我的用词是模拟用例,而不是书写自动化测试用例.一个企业级的自动化测试的构建不是单靠Selenium一种技术就能Hold住的.所谓模拟指的是只能实现自动化的某个Case,但是不能工程化的使用.在本人所接触过几家公司的自动化测试

[小北De编程手记] : Lesson 06 - Selenium For C# 之 流程控制

无论你是用哪一种自动化测试的驱动框架,当我们构建一个复杂应用程序的自动化测试的时候.都希望构建一个测试流程稳定,维护成本较低的自动化测试.但是,现实往往没有理想丰满.而这一篇,我会为大家讲解我们在使用Selenium进行Web测试的时候应该如何控制我们的测试流程,从而尽可能地提高自动化测试可维护性.那么,先看一下这一篇的内容主要涉及到的话题: 自动化测试的成本 隐式的等待同步策略 显式的等待同步策略 自定义等待同步策略(一些关于自动化框架设计的探讨) (一)自动化测试的成本 <Selenium

[小北De编程手记] : Lesson 05 - Selenium For C# 之 API 下

上一篇,我们介绍了一些Selenium WebDriver相关的API,下面我们就接着上一篇继续介绍Selenium常用的API,这一篇的内容主要涉及到以下话题: Selenium API:复杂事件处理 Selenium API:特殊DOM元素处理 Selenium API:截图功能 Selenium API:关于框架扩展 (一)Selenium API:复杂事件处理 首先,我们试想一下这样的场景.待测试的系统支持一些组合键的操作,例如:按住Ctrl的同时点击某个表格的某个单元格,该数据行会高亮

[小北De编程手记] : Lesson 04 - Selenium For C# 之 API 上

这一部分,我准备向大家介绍Selenium WebDriver的常用API,学习这部分内容需要大家最好有一些简单的HTML相关知识,本文主要涉及到以下内容: Selenium API:元素检查 Selenium API:事件处理 Selenium API:其他操作 Selenium API:框架扩展 回顾一下我之前讲过的一个概念:所谓自动化测试,可以简单的归结为是一个从被测试程序中识别或是定位元素以及执行操作和验证元素的过程.从框架设计的角度来讲,一个自动化测试框架的驱动程序应该向使用者提供“元

[小北De编程手记] : Lesson 03 - Selenium For C# 之 元素定位

无论哪一种自动化测试的驱动框架(基于B/S,桌面应用,还是手机App).都应当具有一套优秀的元素定位技术.通常的自动化测试流程也可以简单的归结为是一个从被测试程序中识别或是定位元素以及执行操作和验证元素的过程.这一篇我们就开始给大家介绍一下Selenium中是如何定位DOM元素的.本文将会介绍如下内容: Selenium DOM 主要的定位方式. Selenium 如何扩展元素定位方式. 辅助浏览器工具 (一)Selenium DOM主要定位方式 上一篇中,我们介绍了WebDriver 和 We

[小北De编程手记] : Lesson 01 - Selenium For C# 之 环境搭建

在我看来一个自动化测试平台的构建,是一种很好的了解开发语言,单元测试框架,自动化测试驱动,设计模式等等等的途径.因此,在下选择了自动化测试的这个话题来和大家分享一下本人关于软件开发和自动化测试的认识.刚刚开通了博客,就从最基础的开始吧,算是写给初学者的编程手记,也算是给对自动化完全不了解的小伙伴开个头.时间允许的话会坚持更新下去... ... 后续的文章计划会谈到一些企业级自动化测试平台的构建(但愿有时间完成哈~~). 关于自动化测试的框架,网上有很多相关的对比,在这里我我就不评论和对比了.本人

[小北De编程手记] : Lesson 04 玩转 xUnit.Net 之 Fixture(下)

上一篇文章<[小北De编程手记] : Lesson 03 玩转 xUnit.Net 之 Fixture(上)>向大家介绍了xUnit.Net 共享数据的方式.Test Case的构造函数 & IDisposable.Dispose.Class级别的Fixture : IClassFixture.这一篇,我们接着讲解后面的内容,回顾一下本文要讨论的内容: xUnit.Net 共享数据的方式(上) Test Case的构造函数 & IDisposable.Dispose(上) Cl

[小北De编程手记] Lesson 01 - AutoFramework构建 之 从一个简单的Demo聊起

写在最前面 这个系列的主旨是要跟大家分享一下关于自动化测试框架的构建的一些心得.这几年,做了一些自动化测试框架以及团队的构建的工作.过程中遇到了很多这样的同学,他们在学习了某一门语言和一些自动化测试的类库或者工具之后,打算进一步的提高.我想这个系列也许会帮助到你,我们一起从各个维度来看一看自动化测试框架的一些最佳实践.本人能力有限,如果有什么不正确的的地方还各位大牛指正. 聊聊自动化测试的初心 在开始具体的技术和理论之前,我们先来思考一下自动化测试的目的是什么?我简单的罗列了几点: 替代手工测试

[小北De编程手记] : Lesson 03 玩转 xUnit.Net 之 Fixture(上)

在使用xUnit.Net Framework构建单元测试或自动化测试项目的时候,无论是针对一些比较耗费资源的对象亦或是为了支持Test case预设数据的能力,我们都需要有一些初始化或是清理相关的动作.在xUnit.Net中,提供了多种方式来满足我们的需要.还是照例看一下本文要讨论的内容: xUnit.Net 共享数据的方式(上) Test Case的构造函数 & IDisposable.Dispose(上) Class级别的Fixture : IClassFixture(上) 应用程序级别的F