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

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

  • Selenium DOM 主要的定位方式。
  • Selenium 如何扩展元素定位方式。
  • 辅助浏览器工具

(一)Selenium DOM主要定位方式

  上一篇中,我们介绍了WebDriver 和 WebElement两个类型。他们都具有方法FindElement和FindElements。 这便是Selenium WebDriver的API提供给我们的元素定位方式。IWebDriver要求同时实现接口ISearchContext,元素查找的方法便是在这个接口中定义的:

1 public interface IWebDriver : ISearchContext, IDisposable
2 {
3     //省略部分Code... ...
4 }
 1 namespace OpenQA.Selenium
 2 {
 3     // Summary:
 4     //     Defines the interface used to search for elements.
 5     public interface ISearchContext
 6     {
 7         IWebElement FindElement(By by);
 8
 9         ReadOnlyCollection<IWebElement> FindElements(By by);
10     }
11 }

他们都会接受一个By类型的参数。该类型的官网定义如下所示,Selenium主要提供了以下几种方式定位元素:

  • ID : 根据DOM元素的ID属性定位。
  • Name : 根据DOM元素的Name属性定位。
  • ClassName : 根据DOM元素的Class属性定位。
  • TagName : 根据DOM元素的TagName定位。
  • LinkText : 根据DOM元素(link)的文本内容定位。
  • PartialLinkText : 根据DOM元素(link)的部分文本内容定位。
  • CssSelector:根据CSS 选择器定位元素。
  • XPath:使用XPath定位元素。

  

元素定位的调用方式如下:

 1 IWebDriver driver = new FirefoxDriver ();
 2 IWebElement element;
 3
 4 element = driver.FindElement(By.Id("ObjectID"));
 5 element = driver.FindElement(By.Name("ObjectName"));
 6 element = driver.FindElement(By.ClassName("ObjectClassName"));
 7 element = driver.FindElement(By.TagName("ObjectTagText"));
 8 element = driver.FindElement(By.LinkText("ObjectLinkText"));
 9 element = driver.FindElement(By.PartialLinkText( "ObjectPartialLinkText"));
10
11 // Use css selector.
12 element = driver.FindElement(By.CssSelector( "CssSelector For Object"));
13 // Use xPath.
14 element = driver.FindElement(By.XPath("XPath For Object"));

  下面简单的介绍一下DOM元素的ID,Name,ClassName... ...XPath,CssSelector都是些什么鬼? 当然,如果你是一个已经很熟悉这些概念的小伙伴就可以直接忽略这部分内容。关于DOM元素的基本概念和知识这里我就不详细的描述了,有兴趣的小伙伴可以到这个链接学习一下:http://www.runoob.com/html/html-tutorial.html。

  简单的说基本的HTML元素(DOM元素)构成了网页的内容,每个元素都是以一个个DOM标签的形式表现出来的。下面是一个网页标签的结构。我标出了ID,TagName,ClassName,Name所对应了位置。

  结合之前介绍的By Class提供的静态方法。我们就可以定位到对应的HTML元素的位置。说到这里,很多资料或是书本都会有这样的描述:“编码中,使用ID,Name,Class属性是定位元素的首选方法”。没错这些元素定位简单直接,而且理论上的执行效率较快。但是(请注意,我说了但是~~~),现实的情况是开发人员可能根本就没有为元素定义这些属性,或者实际的应用ID是自动随机生成的,Name和ClassName又不能准确的唯一定位,此刻我们就需要其他的方式来定位元素。这也是XPath和Css选择器的作用了,实际的工作中,这两种定位方式应当是伴随你的主要方式,so ... ... 好好了解一下还是很有必要的。关于XPath和Css选择器的语法已经超出了我们要讨论的问题,想了解的小伙伴可以网上找一下相关的资料,这里我就不多说了。下面我们可以看一下定位博客园首页导航的XPath:

1 var divMain = driver.FindElement(By.Id("main"));
2 var lnkHome = driver.FindElement(By.XPath(".//ul[@class=‘post_nav_block‘]/li[1]/a"));
3 var lnkEssence = driver.FindElement(By.XPath(".//ul[@class=‘post_nav_block‘]/li[2]/a"));
4 var lnkCandidate = driver.FindElement(By.XPath(".//ul[@class=‘post_nav_block‘]/li[3]/a"));
5 var lnkNews = driver.FindElement(By.XPath(".//ul[@class=‘post_nav_block‘]/li[4]/a"));

关于获取超链接元素的两个方法By.LinkText和By.PartialLinkText,简单明了,在此我就不多做介绍了。

(二)Selenium 如何扩展元素定位的方式

除了基本的定位方式之外,如果我们想拥有自定义的定位应该如何处理呢?比如,我们的测试过程中,我们想一次性获取到所有CSS样式是.btn的input标签应当如何处理?

  Selenium本身的底层驱动是基于JS的,同时也为我们上层的使用者(测试CASE编写者或测试框架开发者)为提供了可以的执行自定义JS,并返回数据的方法。回顾一下上文中将到的核心对象WebDriver,都是继承自RemoteWebDriver。而RemoteWebDriver实现了IJavaScriptExecutor接口,该接口定义了执行JS的行为:

 1 namespace OpenQA.Selenium
 2 {
 3     // Summary:
 4     //     Defines the interface through which the user can execute JavaScript.
 5     public interface IJavaScriptExecutor
 6     {  7         object ExecuteAsyncScript(string script, params object[] args);
 8         object ExecuteScript(string script, params object[] args);
 9     }
10 }

  因此,我们可以利用如下方式来执行我们自定义的JS,略懂JavaScript的同学看到这里,貌似应该明白了什么。没错,你可以自由的翱翔了(定义任何你想要的定位逻辑,不仅仅是定位元素)。当然,这个只是Selenium提供的接口,真正的使用和企业级的封装有机会的话我会开一个新的系列为大家介绍,本节先介绍到这里。

1 IJavaScriptExecutor jsExecutor = driver as IJavaScriptExecutor ;
2 jsExecutor.ExecuteScript("return $(‘#elementID‘)");

(三)浏览器辅助工具

编程就像习武,功力深厚固然好,但总要有合手的兵器。接下来,为大家推荐一下元素定位可能会用到的工具:

如果你用的是Firefox浏览器,建议你下载Firebug和FirePath:

  • Firebug拥有很多功能(元素定位,脚本调试,网络监控 等等),可以帮你轻松的定位元素和观察DOM结构。
  • FirePath理论上可以用来生成元素的XPath或是验证XPath的定位效果。(虽然工具可以生成XPath也不要指望靠他生成,还是要好好学习XPath的... ... 因为,工具生成的结果往往不是你想要的)。

如果你用的是Chrome或是IE浏览器,他们都有内置的开发者工具。

关于XPath的验证步骤,请参考下图(输入Xpath>点击Eval>查看定位到的元素):

(四)Demo

  说了这么多,又到了做Demo时候了。so... 同样做了个简单的Demo供大家参考。Code上传到Github地址是:https://github.com/DemoCnblogs/Selenium,本节的Demo是用来验证了博客园首页的导航栏内的文字是否正确,使用了几种方式获取DOM元素,代码如下:

 1 using OpenQA.Selenium;
 2 using OpenQA.Selenium.Firefox;
 3 using System.Collections.Generic;
 4 using Xunit;
 5 using Xunit.Abstractions;
 6
 7 namespace Demo.SeleniumTest
 8 {
 9     public class Lesson03_FindElement
10     {
11         /// <summary>
12         /// 输出对象
13         /// </summary>
14         private readonly ITestOutputHelper _output;
15         /// <summary>
16         /// 构造函数,初始化输出对象
17         /// </summary>
18         /// <param name="output">注入输出对象</param>
19         public Lesson03_FindElement(ITestOutputHelper output)
20         {
21             this._output = output;
22         }
23
24         /// <summary>
25         /// demo1 : 获取元素
26         /// </summary>
27         [Fact(DisplayName = "Cnblogs.CheckNavBar.Demo1")]
28         public void CheckNavBar_GetElement()
29         {
30             _output.WriteLine("Step 01 : 启动浏览器并打开博客园首页。");
31             IWebDriver driver = new FirefoxDriver();
32             driver.Url = "http://www.cnblogs.com";
33
34             _output.WriteLine("Step 02 : 寻找需要检查的页面元素。");
35             var divMain = driver.FindElement(By.Id("main"));
36             var lnkHome = driver.FindElement(By.XPath(".//ul[@class=‘post_nav_block‘]/li[1]/a"));
37             var lnkEssence = driver.FindElement(By.XPath(".//ul[@class=‘post_nav_block‘]/li[2]/a"));
38             var lnkCandidate = driver.FindElement(By.XPath(".//ul[@class=‘post_nav_block‘]/li[3]/a"));
39             var lnkNews = driver.FindElement(By.XPath(".//ul[@class=‘post_nav_block‘]/li[4]/a"));
40
41             _output.WriteLine("Step 03 : 检查导航条文字信息。");
42             Assert.Equal<string>("首页", lnkHome.Text);
43             Assert.Equal<string>("精华", lnkEssence.Text);
44             Assert.Equal<string>("候选", lnkCandidate.Text);
45             Assert.Equal<string>("新闻", lnkNews.Text);
46
47             _output.WriteLine("Step 04 : 关闭浏览器。");
48             driver.Close();
49         }
50
51
52         [Fact(DisplayName = "Cnblogs.CheckNavBar.Demo2")]
53         public void CheckNavBar_GetElements()
54         {
55             _output.WriteLine("Step 00 : 准备测试数据。");
56             var testDatas = new List<string>() { "首页", "精华", "候选", "新闻" };      //准备测试数据
57
58             _output.WriteLine("Step 01 : 启动浏览器并打开博客园首页。");
59             IWebDriver driver = new FirefoxDriver();
60             driver.Url = "http://www.cnblogs.com";
61
62             _output.WriteLine("Step 02 : 寻找需要检查的页面元素。");
63             var divMain = driver.FindElement(By.Id("main"));
64             var lnkNavList = driver.FindElements(By.XPath(".//ul[@class=‘post_nav_block‘]/li[1]/a"));
65
66             _output.WriteLine("Step 03 : 检查导航条文字信息。");
67             for (var i = 0; i < lnkNavList.Count; i++)
68             {
69                 Assert.Equal<string>(testDatas[i], lnkNavList[i].Text);
70             }
71             _output.WriteLine("Step 04 : 关闭浏览器。");
72             driver.Close();
73         }
74     }
75 }

总结:本文主要介绍了以下几点内容。

  • Selenium元素定位方式(ID,Name,ClassName,TagName,XPath,Css选择器等等)。
  • 如何扩展Selenium,并自定义定位方式
  • 推荐了一些辅助工具

关于《Selenium For C#》 系列,我计划给大家逐一介绍一些Selenium Driver的基础知识和框架的扩展点。 当然,之后会有更多关于测试框架构以及软件构建方面的文章。愿我主保佑我有时间做完这件事情... ...

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

作者:小北@North

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

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

时间: 2024-09-28 21:18:25

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

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

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

[小北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 06 - Selenium For C# 之 流程控制

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

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

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

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

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

[小北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聊起

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