Selenium提供多种find_element_by 方法用于定位页面元素。这些方法根据一定的标准去查找元素,如果元素被正常定位,那么WebElement实例将返回。反之,将抛出NoSuchElementException的异常。同时,Selenium还提供多种find_elements_by 方法去定位多个元素,这类方法根据所匹配的值,搜索并返回一个list数组(元素)。
Selenium提供8种find_element_by 方法用于定位元素。接下来的部分,我们将逐一介绍方法细节,如下表所示。
方 法 | 描 述 | 参 数 | 示 例 |
---|---|---|---|
ind_element_by_id(id) | 通过元素的ID属性值来定位元素 | id:元素的ID | driver.find_element_by_id('search') |
find_element_by_name(name) | 通过元素的name属性值来定位元素 | name:元素的name | driver.find_element_by_name('q') |
find_element_by_class_name(name) | 通过元素的class名来定位元素 | name:元素的类名 | driver.find_element_by_class_name('input-text') |
find_element_by_tag_name(name) | 通过元素的tag name来定位元素 | name:tag name | driver.find_element_by_tag_name('input') |
find_element_by_xpath(xpath) | 通过XPath来定位元素 | XPath:元素的XPath | driver.find_element_by_xpath('//form[0]/div[0]/input[0]') |
find_element_by_css_selector(css_selector) | 通过CSS选择器来定位一组元素 | css_selector:元素的CSS选择器 | driver.find_element_by_css_selector('#search') |
find_element_by_link_text(link_text) | 通过元素标签对之间的文本信息来定位一组元素 | link_text:文本信息 | driver.find_element_by_link_text('Log In') |
find_element_by_partial_link_text(link_text) | 通过元素标签对之间的部分文本信息来定位一组元素 | link_text:部分文本信息 | driver.find_element_by_partial_link_text('Log') |
通过ID查找元素是查找页面上元素的最佳方法。
find_element_by_id()和find_elements_by_id()方法返回与ID属性值匹配的一个元素或一组元素。
find_element_by_id()方法返回的是与ID属性值匹配的第一元素,如果没有元素与之匹配,则抛出NoSuchElementException异常。
如下图所示,我们尝试来定位搜索框。
通过查看HTML,我们可以看到搜索框的ID值被定义为search。
<input id="search" type="text" name="q" value=""
class="input-text" maxlength="128" autocomplete="off">
接下来我们使用find_element_by_id() 方法,id值为search来定位搜索框,同时检查maxlength的属性值。
def test_search_text_field_max_length(self):
# get the search textbox
search_field = self.driver.find_element_by_id("search")
# check maxlength attribute is set to 128
self.assertEqual("128", search_field.get_attribute("maxlength"))
此外,如果使用find_elements_by_id() 方法,那么将返回匹配ID值的所有元素。
name定位 通过name定位是另外一个常用的查找元素的方式。
find_element_by_name() 和 find_elements_by_name()方法可以通过匹配name值来定位单个或一组元素。同样,name值匹配成功可返回定位的元素;反之,则抛出NoSuchElementException的异常。
回到之前的例子,我们可以用匹配name属性值的方式来替换ID值的匹配,同样可以定位到搜索框。
# get the search textbox
self.search_field = self.driver.find_element_by_name("q")
此外,如果使用find_elements_by_name() 方法,那么将返回匹配name值的所有元素。
class定位 除了使用ID和name属性,我们还可通过class属性来定位元素。class用来关联CSS中定义的属性。
find_element_by_class_name()和find_elements_by_class_name()方法可以通过匹配class属性来定位单个或一组元素。同样,class值匹配成功可返回定位的元素;反之,则抛出NoSuchElementException的异常。
通过对元素ID、name和class属性来查找元素是最为普遍和快捷的方法。此外,Selenium WebDriver还提供了其他一些方法用于定位元素,在接下来的段落中会有详细介绍。
我们可以尝试用find_element_by_class_name() 的方法来定位元素。
搜索按钮在HTML中是用<button>标签(元素)以及对应的class属性与属性值定义的,具体如下。
<button type="submit" title="Search"
class="button"><span><span>Search</span></span></button>
下面我们用class属性值来定位搜索按钮,代码如下。
def test_search_button_enabled(self):
# get Search button
search_button = self.driver.find_element_by_class_name
("button")
# check Search button is enabled
self.assertTrue(search_button.is_enabled())
此外,如果使用find_elements_by_class_name() 方法,那么将返回匹配class属性值的所有元素。
tag定位
find_element_by_tag_name()和find_elements_by_tag_name() 方法是通过对HTML页面中tag name匹配的方式来定位元素的。这些方法跟JavaScript中的DOM方法getElementsBy TagName()类似。同样,通过成功匹配tag name可以返回定位的元素;反之,则抛出NoSuchElementException的异常。
这个方法在某些特定的场景下格外有用,例如,我们可以通过<tr> 的tag name一次定位页面的table中所有的行数据(元素)。
如banner图,通过查看HTML代码,我们可以看出包含有<img>或者<ul>的标签。
这几张banner图采用无序列表标签<ul>内嵌图像标签<img>来实现。
<ul class="promos">
<li>
<a href="http://demo.magentocommerce.com/home-decor.html">
<img src="/media/wysiwyg/homepage-three-column-promo-
01B.png" alt="Physical & amp; Virtual Gift Cards">
</a>
</li>
<li>
<a href="http://demo.magentocommerce.com/vip.html">
<img src="/media/wysiwyg/homepage-three-column-promo-
02.png" alt="Shop Private Sales - Members Only">
</a>
</li>
<li>
<a href="http://demo.magentocommerce.com/accessories/ bags-luggage.html">
<img src="/media/wysiwyg/homepage-three-column-
promo-03.png" alt="Travel Gear for Every Occasion">
</a>
</li>
</ul>
我们使用find_elements_by_tag_name()方法来定位所有的banner图片。首先我们用find_element_by_class_name()方法定位这一组banner图,然后用find_elements_by_tag_name()方法去匹配<img>的tag name,最后把结果返回给banners对象。
def test_count_of_promo_banners_images(self):
# get promo banner list
banner_list = self.driver.find_element_by_class_name("promos")
# get images from the banner_list
banners = banner_list.find_elements_by_tag_name("img")
# check there are 20 tags displayed on the page
self.assertEqual(2, len(banners))
XPath定位
XPath是一种在XML文档中搜索和定位元素的查询语言。几乎所有的浏览器都支持XPath。同样,Selenium也可以通过XPath的方式在Web页面上定位元素。
当我们发现通过ID、name或class属性值都无法定位元素时,不妨尝试用XPath的方式。我们可以灵活地运用绝对或相对路径定位,也可以通过除ID、name以外的其他属性来定位,甚至还可以通过属性值的一部分(如starts-with()、contains()和ends-with())来帮助我们定位。
了解更多关于XPath的知识,可访问相关网站了解。
想要了解更多关于XPath定位的知识,可以参考《Selenium Testing Tools Cookbook》,Packt Publishing。
我们可以使用find_element_by_xpath()和find_elements_by_xpath() 方法来定位元素了。例如,我们通过之前的广告banner图,单击banner图片进入对应的页面。
名为“Shop Private Sales”的banner图,在<img> 的tag下,其中代码并不包含ID、name或class属性等信息,且这个页面还包含很多其他的<img>,所以我们不能通过传统的方法如findby tag_name()简单地定位了。
<ul class="promos">
...
<li>
<a href="http://demo.magentocommerce.com/vip.html">
<img src="/media/wysiwyg/homepage-three-column-
promo-02.png" alt="Shop Private Sales - Members Only">
</a>
</li>
...
</ul>
我们尝试使用find_element_by_xpath()方法,用<img>标签下的 alt 属性值来定位我们要找的元素。
代码如下。
def test_vip_promo(self):
# get vip promo image
vip_promo = self.driver.\
find_element_by_xpath("//img[@alt='Shop Private Sales - Members Only']")
# check vip promo logo is displayed on home page
self.assertTrue(vip_promo.is_displayed())
# click on vip promo images to open the page
vip_promo.click()
# check page title
self.assertEqual("VIP", self.driver.title)
此外,如果使用find_elements_by_xpath() 方法,那么将返回匹配XPath查询到的所有元素。
CSS选择器定位
CSS(层叠样式表)是一种用于页面设计(HTML)与表现的文件样式,是一种计算机语言,能灵活地为页面提供各种样式风格。CSS使用选择器为页面元素绑定属性(如ID、class、type、attribute、value等)。
类似XPath,Selenium也可以利用CSS选择器的特性,用于帮助我们来定位元素。如果想进一步了解关于CSS选择器的一些知识,请访问相关网站了解。
下面介绍find_element_by_css_selector()和find_elements_by_css_selector()两种方法。
回到首页的例子,可以看到购物车按钮,单击这个按钮,将进入购物车页面。如果此时没有添加任何商品,那么系统会提示“你还没有添加商品到购物车”
HTML代码如下。
<div class="minicart-wrapper">
<p class="block-subtitle">
Recently added item(s)
<a class="close skip-link-close" href="#" title="Close">
×</a>
</p>
<p class="empty">You have no items in your shopping cart.
</p>
</div>
我们设计测试程序来校验这个提示信息。首先我们将使用CSS选择器来定位购物车按钮,然后单击它,紧接着定位即将弹出的信息。
def test_shopping_cart_status(self):
# check content of My Shopping Cart block on Home page
# get the Shopping cart icon and click to open the
# Shopping Cart section
shopping_cart_icon = self.driver.\
find_element_by_css_selector("div.header-minicart span.icon")
shopping_cart_icon.click()
# get the shopping cart status
shopping_cart_status = self.driver.\
find_element_by_css_selector("p.empty").text
self.assertEqual("You have no items in your shopping cart.", shopping_cart_status)
# close the shopping cart section
close_button = self.driver.\
find_element_by_css_selector("div.minicart-wrapper a.close")
close_button.click()
从上面的测试脚本可以看出,我们使用了元素tag和class name来缩小获取购物车按钮的范围。
shopping_cart_icon = self.driver.\
find_element_by_css_selector("div.header-minicart span.icon")
首先定位到tag 名为<div>的元素,然后接着“.header-minicart”的类名,其下面的标签<span>下又有“.icon”的类名。
想要了解更多关于CSS选择器的知识,请参考《Selenium Testing Tools Cookbook》,Packt Publishing。
Link定位
find_element_by_link_text() 和 find_elements_by_link_text()方法是通过文本链接来定位元素。如下示例。
(1)定位首页上的Account链接,如下图所示,我们可以使用find_element_by_link_text()方法。
(2)查看对应的HTML代码,具体如下。
<a href="#header-account" class="skip-link skip-account">
<span class="icon"></span>
<span class="label">Account</span>
</a>
(3)编写测试脚本,先通过文本定位Account链接,然后单击查看是否能显示。
def test_my_account_link_is_displayed(self):
# get the Account link
account_link =
self.driver.find_element_by_link_text("ACCOUNT")
# check My Account link is displayed/visible in
# the Home page footer
self.assertTrue(account_link.is_displayed())
此外,如果使用find_elements_by_link_text()方法,那么将返回匹配文本的所有元素。
Partial link定位
find_element_by_partial_link_text()和find_elements_by_partial_link_text()两个方法是通过文本链接的一部分文本来定位元素的方法。如下示例。
(1)同样是首页,有两个链接可以查看个人账户(Account)页面,一个是页面标头(header)部分的Account文字链接,另外一个是页脚(footer)部分的My Account文字链接。
(2)我们使用find_elements_by_partial_link_text()方法,通过部分文本信息“Account”来定位,验证页面中的两个文本链接是否都能定位到(断言)。代码如下。
def test_account_links(self):
# get the all the links with Account text in it
account_links = self.driver.\
find_elements_by_partial_link_text("ACCOUNT")
# check Account and My Account link is displayed/visible in the Home page footer
self.assertTrue(2, len(account_links))