实用selenium+python实现web自动化测试

为什么选python

之前的菜鸟系列是基于java的,一年没学其实也忘的差不多了,目前所测的产品部分也是python写的,而且团队也在推广python ,其实就测试人员来说,python也相当受欢迎。易学,易用。翻翻各测试招聘,python出现的概率也颇高。

 

平台搭建:

前一篇中已经介绍,如果你也想体验一下自动化魅力,那就赶快搭建自己的环境吧~

selenium + python自动化测试环境搭建

 

第一个脚本:

下面看看python 穿上selenium webdriver 是多么的性感:

# coding = utf-8

 

from selenium import webdriver

 

browser = webdriver.Firefox()

 

browser.get("http://www.baidu.com")

browser.find_element_by_id("kw").send_keys("selenium")

browser.find_element_by_id("su").click()

browser.quit()

 

from selenium import webdriver

要想使用seleniumwebdriver 里的函数,首先把包导进来嘛

 

browser = webdriver.Firefox() 

我们需要操控哪个浏览器呢?Firefox ,当然也可以换成Ie  Chrome browser可以随便取,但后面要用它操纵各种函数执行。

 

browser.find_element_by_id("kw").send_keys("selenium")

一个控件有若干属性id name、(也可以用其它方式定位),百度输入框的id kw ,我要在输入框里输入 selenium 。多自然语言呀!

 

browser.find_element_by_id("su").click()

搜索的按钮的id su ,我需要点一下按钮( click() )。

 

browser.quit()

退出并关闭窗口的每一个相关的驱动程序,它还有个类似的表弟。

browser.close()

关闭当前窗口 ,用哪个看你的需求了。

 

添加休眠

什么?你说刚才太快没看清浏览器的操作过程。请time出马,让他跑慢点。

# coding = utf-8

 

from selenium import webdriver

import  time  #调入time函数

 

browser = webdriver.Firefox()

 

browser.get("http://www.baidu.com")

time.sleep(0.3)  #休眠0.3秒

browser.find_element_by_id("kw").send_keys("selenium")

browser.find_element_by_id("su").click()

time.sleep(3)  # 休眠3秒

browser.quit()

 

time.sleep() 函数随意插,哪里太快插哪里,再也不用担心看不清脚本的运行过程了。

 

其实,这个函数的真正用途不是给我们看脚本的运行过程的,有时候网络原因,或页面加载慢。假设搜索框输入框输入了selenium ,搜索按钮还没加载出来,那么脚本就报错。在适当的位置加入time.sleep()有助于减少网络原因造成的脚本执行失败;

 

输出

什么?在运行脚本的时候,上了个厕所,你都不知道刚才的脚本是否运行成功了。把刚才访问页面的title 打印出来。

 

# coding = utf-8

 

from selenium import webdriver

 

driver = webdriver.Chrome()

driver.get('http://www.baidu.com')

print driver.title  # 把页面title 打印出来

driver.quit()

 

虽然我没看到脚本的执行过程,但我在执行结果里看到了

>>>

百度一下,你就知道

说明页面正确被我打开了。

 

知识点:

· 打印URL

· 将浏览器最大化

· 设置浏览器固定宽、高

· 操控浏览器前进、后退

 

打印URL

上一节讲到,可以将浏览器的title打印出来,这里再讲个简单的,把当前URL打印出来。其实也没啥大用,可以做个凑数的用例。

 

#coding=utf-8

 

from selenium import webdriver

import time

 

browser = webdriver.Firefox()

 

url= 'http://www.baidu.com'

 

#通过get方法获取当前URL打印

print "now access %s" %(url)

browser.get(url)

 

time.sleep(2)

browser.find_element_by_id("kw").send_keys("selenium")

browser.find_element_by_id("su").click()

time.sleep(3)

browser.quit()   

 

其实,我们可以把这用户登录成功后的URL打印,用于验证用户登录成功。

又或者,我们打印其它信息,比如,一般的登录成功页会出现欢迎+用户名”,可以将这个信息打印表明用户登录成功。(如何实现,你自己琢磨一下吧~!)

 

将浏览器最大化

我们知道调用启动的浏览器不是全屏的,这样不会影响脚本的执行,但是有时候会影响我们观看脚本的执行。

#coding=utf-8

 

from selenium import webdriver

import time

 

browser = webdriver.Firefox()

 

browser.get("http://www.baidu.com")

time.sleep(2)

 

print "浏览器最大化"

browser.maximize_window()  #将浏览器最大化显示

time.sleep(2)

 

browser.find_element_by_id("kw").send_keys("selenium")

browser.find_element_by_id("su").click()

time.sleep(3)

browser.quit()

 

设置浏览器固定宽、高

最大化还是不够灵活,能不能随意的设置浏览的宽、高显示?当然是可以的。

 

#coding=utf-8

from selenium import webdriver

import time

 

browser = webdriver.Firefox()

 

browser.get("http://m.mail.10086.cn")

time.sleep(2)

 

print "设置浏览器宽480、高800显示"

browser.set_window_size(480, 800)  #参数数字为像素点

time.sleep(3)

browser.quit()

这个需求也还是有的,比如我们通过PC浏览器在访问一下手机网站时,调整浏览器为手机屏幕的宽、高,容易发现一些显示问题。(上面的手机邮箱网站就是笔者测试过的一个产品)

 

 

操控浏览器前进、后退

浏览器上有一个后退、前进按钮,对于浏览网页的人是比较方便的;对于做web自动化测试的同学来说应该算是一个比较难模拟的问题;其实很简单,下面看看python的实现方式

#coding=utf-8

 

from selenium import webdriver

import time

 

browser = webdriver.Firefox()

 

#访问百度首页

first_url= 'http://www.baidu.com'

print "now access %s" %(first_url)

browser.get(first_url)

time.sleep(2)

 

#访问新闻页面

second_url='http://news.baidu.com'

print "now access %s" %(second_url)

browser.get(second_url)

time.sleep(2)

 

#返回(后退)到百度首页

print "back to  %s "%(first_url)

browser.back()

time.sleep(1)

 

#前进到新闻页

print "forward to  %s"%(second_url)

browser.forward()

time.sleep(2)

 

browser.quit()

为了使过程让你看得更清晰,在每一步操作上都加了print sleep 

说实话,这两个功能平时不太常用,所能想到的场景就是几个页面来回跳转,但又不想用get url的情况下。

 

 

 

 

 

 

本节重点:

简单对象的定位

对象的定位应该是自动化测试的核心,要想操作一个对象,首先应该识别这个对象。一个对象就是一个人一样,他会有各种的特征(属性),如比我们可以通过一个人的身份证号,姓名,或者他住在哪个街道、楼层、门牌找到这个人。

那么一个对象也有类似的属性,我们可以通过这个属性找到这对象。

 

定位对象的目的一般有下面几种

· 操作对象

· 获得对象的属性,如获得测试对象的class属性,name属性等等

· 获得对象的text

· 获得对象的数量

 

webdriver提供了一系列的对象定位方法,常用的有以下几种

· · id

· · name

· · class name

· · link text

· · partial link text

· · tag name

· · xpath

· · css selector

 

我们可以看到,一个百度的输入框,可以用这么用种方式去定位。

#coding=utf-8

 

from selenium import webdriver

import time

 

browser = webdriver.Firefox()

 

browser.get("http://www.baidu.com")

time.sleep(2)

 

#########百度输入框的定位方式##########

 

#通过id方式定位

browser.find_element_by_id("kw").send_keys("selenium")

 

#通过name方式定位

browser.find_element_by_name("wd").send_keys("selenium")

 

#通过tag name方式定位

browser.find_element_by_tag_name("input").send_keys("selenium")

 

#通过class name 方式定位

browser.find_element_by_class_name("s_ipt").send_keys("selenium")

 

#通过CSS方式定位

browser.find_element_by_css_selector("#kw").send_keys("selenium")

 

#通过xphan方式定位

browser.find_element_by_xpath("//input[@id='kw']").send_keys("selenium")

 

############################################

 

browser.find_element_by_id("su").click()

time.sleep(3)

browser.quit()

 

OK~!通过上面一个例子,就帮我们展示了几种定位方式,下面来介绍每种定位方式:

 

id 和 name

 

 

id  name 是我们最最常用的定位方式,因为大多数控件都有这两个属性,而且在对控件的id name命名时一般使其有意义也会取不同的名字。通过这两个属性使我们找一个页面上的属性变得相当容易

 

我们通过前端工具,找到了百度输入框的属性信息,如下:

<input id="kw" class="s_ipt" type="text" maxlength="100" name="wd" autocomplete="off">

 

id=”kw”

通过find_element_by_id("kw") 函数就是捕获到百度输入框

name=”wd”

通过find_element_by_name("wd")函数同样也可以捕获百度输入框

 

 

tag name 和class name

从上面的百度输入框的属性信息中,我们看到,不单单只有id  name两个属性,比如class  tag name(标签名)

<input>

input 就是一个标签的名字,可以通过find_element_by_tag_name("input") 函数来定位。

class="s_ipt"

通过find_element_by_class_name("s_ipt")函数捕获百度输入框。

但是,碰下面的一组控件属性,我们就哭了。

<th width="95"></th>

<th width="">文件名</th>

<th class="c1">创建时间</th>

<th class="c1">状态</th>

<th class="c1">文件大小</th>

<th class="c1">时长</th>

 

下面的css  XPath就没有上面的那么直观,如果不懂前端的话可能不太好理解

 

CSS定位

 

CSS(Cascading Style Sheets)是一种语言,它被用来描述HTMLXML文档的表现。CSS使用选择器来为页面元素绑定属性。这些选择器可以被selenium用作另外的定位策略。

CSS的比较灵活可以选择控件的任意属性,上面的例子中:

find_element_by_css_selector("#kw")

通过find_element_by_css_selector( )函数,选择取百度输入框的id属性来定义

也可以取name属性

<a href="http://news.baidu.com" name="tj_news"> </a>

driver.find_element_by_css_selector("a[name=\"tj_news\"]").click()

 

可以取title属性

<a onclick="queryTab(this);" mon="col=502&pn=0" title="web" href="http://www.baidu.com/">网页</a>

driver.find_element_by_css_selector("a[title=\"web\"]").click()

 

也可以是取..:

<a class="RecycleBin xz" href="javascript:void(0);">

driver.find_element_by_css_selector("a.RecycleBin").click()

虽然我也没全部理解CSS的定位,但是看上去应该是一种非常灵活和牛的定位方式

 

扩展阅读:

http://www.w3.org/TR/css3-selectors/

http://www.w3school.com.cn/css/css_positioning.asp

 

 

XPath

 

什么是XPathhttp://www.w3.org/TR/xpath/
XPath基础教程:http://www.w3schools.com/xpath/default.asp

selenium中被误解的XPath  http://magustest.com/blog/category/webdriver/

 

XPath是一种在XML文档中定位元素的语言。因为HTML可以看做XML的一种实现,所以selenium用户可是使用这种强大语言在web应用中定位元素。

XPath扩展了上面idname定位方式,提供了很多种可能性,比如定位页面上的第三个多选框。

 

xpath:attributer (属性)

 

driver.find_element_by_xpath("//input[@id='kw']").send_keys("selenium")

 

#input标签下id =kw的元素

 

xpath:idRelative (id相关性)

 

driver.find_element_by_xpath("//div[@id='fm']/form/span/input").send_keys("selenium")

 

#在/form/span/input 层级标签下有个div标签的id=fm的元素

 

driver.find_element_by_xpath("//tr[@id='check']/td[2]").click()

 

# id为'check' 的tr ,定闪他里面的第2个td

 

xpath:position (位置)

 

driver.find_element_by_xpath("//input").send_keys("selenium")

 

driver.find_element_by_xpath("//tr[7]/td[2]").click()

 

#第7个tr 里面的第2个td

 

xpath: href (水平参考)

 

driver.find_element_by_xpath("//a[contains(text(),'网页')]").click()

 

#在a标签下有个文本(text)包含(contains)'网页' 的元素

 

xpath:link

 

driver.find_element_by_xpath("//a[@href='http://www.baidu.com/']").click()

 

#有个叫a的标签,他有个链接href='http://www.baidu.com/ 的元素

 

 

link 定位

 

有时候不是一个输入框也不是一个按钮,而是一个文字链接,我们可以通过link

#coding=utf-8

 

from selenium import webdriver

import time

 

browser = webdriver.Firefox()

 

browser.get("http://www.baidu.com")

time.sleep(2)

    

browser.find_element_by_link_text("贴 吧").click()

time.sleep(2)

browser.quit()

 

一般一个那页面上不会出现相同的文件链接,通过文字链接来定位也是一种简单有效的定位方式。

 

 

 

Partial Link Text 定位

 

通过部分链接定位,这个有时候也会用到,我还没有想到很好的用处。拿上面的例子,我可以只用链接的一部分文字进行匹配:

browser.find_element_by_partial_link_text("贴").click()

 

#通过find_element_by_partial_link_text() 函数,我只用了“贴”字,脚本一样找到了"贴 吧" 的链接

 

本节要解决的问题:

如何定位一组元素?

 

场景

从上一节的例子中可以看出,webdriver可以很方便的使用findElement方法来定位某个特定的对象,不过有时候我们却需要定位一组对象,

这时候就需要使用findElements方法。

 

定位一组对象一般用于以下场景:

· 批量操作对象,比如将页面上所有的checkbox都勾上

· 先获取一组对象,再在这组对象中过滤出需要具体定位的一些对象。比如定位出页面上所有的checkbox,然后选择最后一个

 

<html>

    <head>

        <meta http-equiv="content-type" content="text/html;charset=utf-8" />

        <title>Checkbox</title>

        <script type="text/javascript" async="" src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>

        <link href="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstrap-combined.min.css" rel="stylesheet" />

        <script src="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/js/bootstrap.min.js"></script>

    </head>

    <body>

        <h3>checkbox</h3>

        <div class="well">

            <form class="form-horizontal">

                <div class="control-group">

                    <label class="control-label" for="c1">checkbox1</label>

                    <div class="controls">

                        <input type="checkbox" id="c1" />

                    </div>

                </div>

                <div class="control-group">

                    <label class="control-label" for="c2">checkbox2</label>

                    <div class="controls">

                        <input type="checkbox" id="c2" />

                    </div>

                </div>

                <div class="control-group">

                    <label class="control-label" for="c3">checkbox3</label>

                    <div class="controls">

                        <input type="checkbox" id="c3" />

                    </div>

                </div>    

        

                <div class="control-group">

                    <label class="control-label" for="r">radio</label>

                    <div class="controls">

                        <input type="radio" id="r1" />

                    </div>

                </div>

                

                <div class="control-group">

                    <label class="control-label" for="r">radio</label>

                    <div class="controls">

                        <input type="radio" id="r2" />

                    </div>

                </div>

            </form>

        </div>

    </body>

</html>

 

将这段代码保存复制到记事本中,将保存成checkbox.html文件。(注意,这个页面需要和我们的自动化脚本放在同一个目录下

 

 

第一种方法:

通过浏览器打个这个页面我们看到三个复选框和两个单选框。下面我们就来定位这三个复选框。

# -*- coding: utf-8 -*-

from selenium import webdriver

import time

import os

 

dr = webdriver.Firefox()

file_path =  'file:///' + os.path.abspath('checkbox.html')

dr.get(file_path)

 

# 选择页面上所有的input,然后从中过滤出所有的checkbox并勾选之

inputs = dr.find_elements_by_tag_name('input')

for input in inputs:

    if input.get_attribute('type') == 'checkbox':

        input.click()

time.sleep(2)

 

dr.quit()

 

你可以试着把input.get_attribute('type') == 'checkbox' 中的checkbox 变成radio ,那这个脚本定位的会是两个单选框。

 

第二种定位方法:

# -*- coding: utf-8 -*-

from selenium import webdriver

import time

import os

 

dr = webdriver.Firefox()

file_path =  'file:///' + os.path.abspath('checkbox.html')

dr.get(file_path)

 

# 选择所有的checkbox并全部勾上

checkboxes = dr.find_elements_by_css_selector('input[type=checkbox]')

for checkbox in checkboxes:

    checkbox.click()

time.sleep(2)

 

# 打印当前页面上有多少个checkbox

print len(dr.find_elements_by_css_selector('input[type=checkbox]'))

time.sleep(2)

 

dr.quit()

 

第二种写法与第一种写法差别不大,都是通过一个循环来勾选控件;如果你学过上一章的话,细心的你一定发现用的定位函数不一样,

第一种用的name ,第二种用的CSS

 

 如何去掉勾选:

还有一个问题,有时候我们并不想勾选页面的所有的复选框(checkbox),可以通过下面办法把最后一个被勾选的框去掉。如下:

# -*- coding: utf-8 -*-

from selenium import webdriver

import time

import os

 

dr = webdriver.Firefox()

file_path =  'file:///' + os.path.abspath('checkbox.html')

dr.get(file_path)

 

# 选择所有的checkbox并全部勾上

checkboxes = dr.find_elements_by_css_selector('input[type=checkbox]')

for checkbox in checkboxes:

    checkbox.click()

time.sleep(2)

 

# 把页面上最后1个checkbox的勾给去掉

dr.find_elements_by_css_selector('input[type=checkbox]').pop().click()

time.sleep(2)

 

dr.quit()

 

其实,去掉勾选表也逻辑也非常简单,就是再次点击勾选的按钮。可能我们比较迷惑的是如何找到最后一个按钮。pop() 可以实现这个功能。

好吧!在web自动化的学习过程中,我们必须要知道一些前端的东西,这里扩展一下:

http://www.w3school.com.cn/js/jsref_pop.asp

 

尝试

find_elements_by_css_selector('input[type=checkbox]').pop().click() 中的checkbox 变成radio 会是什么效果,自己尝试一下吧!

 

本节要解决的问题:

· 层级定位

 

场景:

  假如两个控件,他们长的一模样,还都叫张三,唯一的不同是一个在北京,一个在上海,那我们就可以通过,他们的城市,区,街道,来找到他们。

 

  在实际的测试中也经常会遇到这种问题:页面上有很多个属性基本相同的元素,现在需要具体定位到其中的一个。由于属性基本相当,所以在定位的时候会有些麻烦,这时候就需要用到层级定位。先定位父元素,然后再通过父元素定位子孙元素。

 

<html>

    <head>

        <meta http-equiv="content-type" content="text/html;charset=utf-8" />

        <title>Level Locate</title>        

        <script type="text/javascript" async="" src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>

        <link href="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstrap-combined.min.css" rel="stylesheet" />        

    </head>

    <body>

        <h3>Level locate</h3>

        <div class="span3">        

            <div class="well">

                <div class="dropdown">

                    <a class="dropdown-toggle" data-toggle="dropdown" href="#">Link1</a>

                    <ul class="dropdown-menu" role="menu" aria-labelledby="dLabel" id="dropdown1" >

                        <li><a tabindex="-1" href="#">Action</a></li>

                        <li><a tabindex="-1" href="#">Another action</a></li>

                        <li><a tabindex="-1" href="#">Something else here</a></li>

                        <li class="divider"></li>

                        <li><a tabindex="-1" href="#">Separated link</a></li>

                    </ul>

                </div>                

            </div>            

        </div>

        <div class="span3">        

            <div class="well">

                <div class="dropdown">

                    <a class="dropdown-toggle" data-toggle="dropdown" href="#">Link2</a>

                    <ul class="dropdown-menu" role="menu" aria-labelledby="dLabel" >

                        <li><a tabindex="-1" href="#">Action</a></li>

                        <li><a tabindex="-1" href="#">Another action</a></li>

                        <li><a tabindex="-1" href="#">Something else here</a></li>

                        <li class="divider"></li>

                        <li><a tabindex="-1" href="#">Separated link</a></li>

                    </ul>

                </div>                

            </div>            

        </div>

    </body>

    <script src="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/js/bootstrap.min.js"></script>

</html>

 

将这段代码保存复制到记事本中,将保存成level_locate.html文件,(注意,这个页面需要和我们的自动化脚本放在同一个目录下)浏览器打开:

 

  这里自制了一个页面,上面有两个文字链接,点击两个链接会弹出一模一样的的两个下拉菜单,这两个菜单的属性基本一样。那么我如何区分找到相应的菜单项呢?

 

方法如下:

# -*- coding: utf-8 -*-

from selenium import webdriver

from selenium.webdriver.support.ui import WebDriverWait

import time

import os

 

dr = webdriver.Firefox()

file_path =  'file:///' + os.path.abspath('level_locate.html')

dr.get(file_path)

 

#点击Link1链接(弹出下拉列表)

dr.find_element_by_link_text('Link1').click()

 

#找到id 为dropdown1的父元素

WebDriverWait(dr, 10).until(lambda the_driver: the_driver.find_element_by_id('dropdown1').is_displayed())

#在父亲元件下找到link为Action的子元素

menu = dr.find_element_by_id('dropdown1').find_element_by_link_text('Action')

 

#鼠标定位到子元素上

webdriver.ActionChains(dr).move_to_element(menu).perform()

 

time.sleep(2)

 

dr.quit()

 

定位思路:

具体思路是:先点击显示出1个下拉菜单,然后再定位到该下拉菜单所在的ul,再定位这个ul下的某个具体的link。在这里,我们定位第1个下拉菜单中的Action这个选项。

 ---------------------------------------------------------------------

虽然我每行代码前叫了注释,但可能还是不太容易理解,因为里面多了不少以前没见过的新东东。

WebDriverWait(dr, 10) 

10秒内每隔500毫秒扫描1次页面变化,当出现指定的元素后结束。dr就不解释了,前面操作webdriver.firefox()的句柄

 

is_displayed()

该元素是否用户可以见

 

class ActionChains(driver)

driver: 执行用户操作实例webdriver 

生成用户的行为。所有的行动都存储在actionchains对象。通过perform()存储的行为。

 

move_to_element(menu)

移动鼠标到一个元素中,menu上面已经定义了他所指向的哪一个元素

to_element:元件移动到

 

perform()

执行所有存储的行为

 ------------------------------需要我们日常工作中细细品味、慢慢消化这些函数的用法

 

我们只是想达到一种效果,下拉列表中Action选项处于被选中状态,通过鼠标移动到选项上就达到到了这种效果,但通过程序模拟确实比较麻烦:

 

 

本节知识点:

操作对象:

· · click 点击对象

· · send_keys 在对象上模拟按键输入

· · clear 清除对象的内容,如果可以的话

WebElement  另一些常用方法:

· · text  获取该元素的文本

· · submit  提交表单

· · get_attribute  获得属性值

======================================

 

操作测试对象

 

前面讲到了不少知识都是定位元素,定位只是第一步,定位之后需要对这个原素进行操作。

鼠标点击呢还是键盘输入,这要取决于我们定位的是按钮还输入框。

一般来说,webdriver中比较常用的操作对象的方法有下面几个

· click 点击对象

· send_keys 在对象上模拟按键输入

· clear 清除对象的内容,如果可以的话

在我们本系列开篇的第一个例子里就用到了到click send_skys ,别翻回去找了,我再贴一下代码:

# coding = utf-8

from selenium import webdriver

 

browser = webdriver.Firefox()

 

browser.get("http://www.baidu.com")

browser.find_element_by_id("kw").clear()

browser.find_element_by_id("kw").send_keys("selenium")

browser.find_element_by_id("su").click()

browser.quit()

 

send_keys("XX")   用于在一个输入框里输入内容。

click()   用于点击一个按钮。

clear() 用于清除输入框的内容,比如百度输入框里默认有个请输入关键字的信息,再比如我们的登陆框一般默认会有账号”“密码这样的默认信息。clear可以帮助我们清除这些信息。

 

 

WebElement  另一些常用方法:

 

· text  获取该元素的文本

· submit  提交表单

· get_attribute  获得属性值

 

text  

用于获取元素的文本信息

下面把百度首页底部的声明打印输出

#coding=utf-8

from selenium import webdriver

 

import  time

 

driver = webdriver.Firefox()

driver.get("http://www.baidu.com")

time.sleep(2)

 

#id = cp 元素的文本信息

data=driver.find_element_by_id("cp").text

print data   #打印信息

 

time.sleep(3)

driver.quit()

输出:

>>>

©2013 Baidu 使用百度前必读 京ICP证030173号

 

 

submit

提交表单

我们把百度一下的操作从click 换成submit 

#coding=utf-8

from selenium import webdriver

 

import time

 

driver = webdriver.Firefox()

driver.get("http://www.baidu.com")

 

driver.find_element_by_id("kw").send_keys("selenium")

time.sleep(2)

#通过submit() 来操作

driver.find_element_by_id("su").submit()  

 

time.sleep(3)

driver.quit()

这里用submit click的效果一样,我暂时还没想到只能用submit 不能用click的场景。他们之间到底有啥区别,知道的同学请留言告诉我。

 

get_attribute

获得属性值。

这个函数的用法前面已经有出现过,在定位一组元素的时候有使用到它,只是我们没有做过多的解释。

一般用法:

select = driver.find_element_by_tag_name("select")

 

allOptions = select.find_elements_by_tag_name("option")

 

for option in allOptions:

 

    print "Value is: " + option.get_attribute("value")

 

    option.click()

具体应用参考:

定位一组元素http://www.cnblogs.com/fnng/p/3190966.html

 

小结:

学到这里我们是不是已经撑握了不少知识,简单的操作浏览器,定位元素,操作元素以及打印一些信息。其实,我们前面的学习中大多使用的是WebElement 里的方法。

 

WebElement的方法:

 

一般来说,所有有趣的操作与页面进行交互的有趣的操作,都通过 WebElement 完成

classselenium.webdriver.remote.webelement.WebElement(parent, id_)

这个类代表HTML页面元素

 

 

 

id_

#当前元素的ID

 

tag_name

#获取元素标签名的属性

 

text

#获取该元素的文本。

 

click()

#单击(点击)元素

 

submit()

#提交表单

 

clear()

#清除一个文本输入元素的文本

 

get_attribute(name)

#获得属性值

 

is_selected(self)

#元素是否被选择

 

Whether the element is selected.

is_enabled()

 

#元素是否被启用

 

 

find_element_by_id(id_)

find_elements_by_id(id_)

 

#查找元素的id

 

find_element_by_name(name)

find_elements_by_name(name)

 

#查找元素的name

 

find_element_by_link_text(link_text)

find_elements_by_link_text(link_text)

#查找元素的链接文本

 

find_element_by_partial_link_text(link_text)

find_elements_by_partial_link_text(link_text)

 

#查找元素的链接的部分文本

 

find_element_by_tag_name(name)

find_elements_by_tag_name(name)

 

#查找元素的标签名

 

find_element_by_xpath(xpath)

 

#查找元素的xpath

 

find_elements_by_xpath(xpath)

#查找元素内的子元素的xpath

 

find_element_by_class_name(name)

#查找一个元素的类名

 

find_elements_by_class_name(name)

#查找元素的类名

 

find_element_by_css_selector(css_selector)

#查找并返回一个元素的CSS 选择器

 

find_elements_by_css_selector(css_selector)

#查找并返回多个元素的CSS 选择器列表

 

send_keys(*value)

#模拟输入元素

 

 

本节知识点:

多层框架或窗口的定位:

· switch_to_frame()

· switch_to_window()

智能等待:

· implicitly_wait()

 

对于一个现代的web应用,经常会出现框架(frame 或窗口(window)的应用,这也就给我们的定位带来了一个难题。

有时候我们定位一个元素,定位器没有问题,但一直定位不了,这时候就要检查这个元素是否在一个frame中,seelnium  webdriver 提供了一个switch_to_frame方法,可以很轻松的来解决这个问题。

 

frame.html

 

<html>

<head>

<meta http-equiv="content-type" content="text/html;charset=utf-8" />

<title>frame</title>

<script type="text/javascript" async=""

src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js

"></script>

<link href="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstrap-combined.min.css" rel="stylesheet" />

<script type="text/javascript">

$(document).ready(function(){

});

</script>

</head>

<body>

<div class="row-fluid">

<div class="span10 well">

<h3>frame</h3>

<iframe id="f1" src="inner.html" width="800",

height="600"></iframe>

</div>

</div>

</body>

<script src="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/js/bootstrap.min.js"></script>

</html>

 

inner.html

 

<html>

<head>

<meta http-equiv="content-type" content="text/html;charset=utf-8" />

<title>inner</title>

</head>

<body>

<div class="row-fluid">

<div class="span6 well">

<h3>inner</h3>

<iframe id="f2" src="http://www.baidu.com" width="700"

height="500"></iframe>

<a href="javascript:alert('watir-webdriver better than

selenium webdriver;')">click</a>

</div>

</div>

</body>

</html>

 

frame.html 中嵌套inner.html ,两个文件和我们的脚本文件放同一个目录下:

 

switch_to_frame()

操作上面页面,代码如下:

 

#coding=utf-8

from selenium import webdriver

import time

import os

 

browser = webdriver.Firefox()

file_path =  'file:///' + os.path.abspath('frame.html')

browser.get(file_path)

 

browser.implicitly_wait(30)

#先找到到ifrome1(id = f1)

browser.switch_to_frame("f1")

#再找到其下面的ifrome2(id =f2)

browser.switch_to_frame("f2")



#下面就可以正常的操作元素了

browser.find_element_by_id("kw").send_keys("selenium")

browser.find_element_by_id("su").click()

time.sleep(3)


browser.quit()

 

driver.switch_to_window()

有可能嵌套的不是框架,而是窗口,还有真对窗口的方法:switch_to_window

用法与switch_to_frame 相同:

driver.switch_to_window("windowName")

 

implicitly_wait()

细心的话会发现上面的例子中有browser.implicitly_wait(30),它的用法应该比time.sleep() 更智能,后者只能选择一个固定的时间的等待,前者可以在一个时间范围内智能的等待。

文档解释:

selenium.webdriver.remote.webdriver.implicitly_wait(time_to_wait)

隐式地等待一个无素被发现或一个命令完成;这个方法每次会话只需要调用一次

time_to_wait: 等待时间

用法:

driver.implicitly_wait(30)

 

本节重点:

调用js方法

· execute_script(script, *args)

在当前窗口/框架 同步执行javaScript

脚本:JavaScript的执行。

*参数:适用任何JavaScript脚本。

使用:

driver.execute_script‘document.title’

 

 

使快播登陆用户名输入框标红显示

#coding=utf-8

from selenium import webdriver

import time

 

driver = webdriver.Firefox()

driver.get("http://passport.kuaibo.com/login/?referrer=http%3A%2F%2Fvod.kuaibo.com%2F%3Ft%3Dhome")

 

#给用户名的输入框标红

js="var q=document.getElementById(\"user_name\");q.style.border=\"1px solid red\";"

#调用js

driver.execute_script(js)

time.sleep(3)

 

driver.find_element_by_id("user_name").send_keys("username")

driver.find_element_by_id("user_pwd").send_keys("password")

driver.find_element_by_id("dl_an_submit").click()

time.sleep(3)

 

driver.quit()

js解释:

q=document.getElementById(\"user_name\")

元素qid user_name

q.style.border=\"1px solid red\

元素q的样式,边框为1个像素红色

 

隐藏元素

js.html

<html>

    <head>

      <meta http-equiv="content-type" content="text/html;charset=utf-8" />

      <title>js</title>     

      <script type="text/javascript" async="" src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>

      <link href="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstrap-combined.min.css" rel="stylesheet" />        

      <script type="text/javascript">

        $(document).ready(function(){

          $('#tooltip').tooltip({"placement": "right"});

        });

      </script>

    </head>

 

    <body>

      <h3>js</h3>

      <div class="row-fluid">

        <div class="span6 well">        

          <a id="tooltip" href="#" data-toggle="tooltip" title=" selenium-webdriver(python)">hover to see tooltip</a>

          <a class="btn">Button</a>

        </div>      

      </div>        

    </body>

    <script src="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/js/bootstrap.min.js"></script>

  </html>

 

(保持html文件与执行脚本在同一目录下)

执行js一般有两种场景:

· 一种是在页面上直接执行JS

· 另一种是在某个已经定位的元素上执行JS

 

#coding=utf-8

from selenium import webdriver

import time,os

 

driver = webdriver.Firefox()

file_path =  'file:///' + os.path.abspath('js.html')

driver.get(file_path)

 

#######通过JS 隐藏选中的元素#########

#第一种方法:

driver.execute_script('$("#tooltip").fadeOut();')

time.sleep(5)

 

#第二种方法:

button = driver.find_element_by_class_name('btn')

driver.execute_script('$(arguments[0]).fadeOut()',button)

time.sleep(5)

 

driver.quit()

 

js解释:

arguments对象,它是调用对象的一个特殊属性,用来引用Arguments对象。Arugments对象就像数组

fadeOut() 方法使用淡出效果来隐藏被选元素,假如该元素是隐藏的。

 

PS:可以看到js 可以做selenium 做不到的事情,但是在什么样的自动化的时候才能(或必须)要js帮忙,我还没遇到过。不过js可以selenium完成更强大的功能,这是不容置疑的。

另外,之前没有学过JS ,所以js代码很陌生。如果有时间的话也建议各位同学补充这方面的知识。UI自动化离不开前端技术。

 

本节重点:

· 上传文件

文件上传操作也比较常见功能之一,上传功能没有用到新有方法或函数,关键是思路。

上传过程一般要打开一个本地窗口,从窗口选择本地文件添加。所以,一般会卡在如何操作本地窗口添加上传文件。

其实,在selenium  webdriver 没我们想的那么复杂;只要定位上传按钮,通send_keys添加本地文件路径就可以了。绝对路径和相对路径都可以,关键是上传的文件存在。下面通地例子演示。

upload_file.html

<html>

<head>

<meta http-equiv="content-type" content="text/html;charset=utf-8" />

<title>upload_file</title>

<script type="text/javascript" async=""

src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js

"></script>

<link href="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstrap-combined.min.css" rel="stylesheet" />

<script type="text/javascript">

</script>

</head>

<body>

<div class="row-fluid">

<div class="span6 well">

<h3>upload_file</h3>

<input type="file" name="file" />

</div>

</div>

</body>

<script src="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/js/bootstrap.min.js"></script>

</html>

 

upload.py

#coding=utf-8

from selenium import webdriver

import os,time

 

driver = webdriver.Firefox()

 

#脚本要与upload_file.html同一目录

file_path =  'file:///' + os.path.abspath('upload_file.html')

driver.get(file_path)

 

#定位上传按钮,添加本地文件

driver.find_element_by_name("file").send_keys('D:\\selenium_use_case\upload_file.txt')

time.sleep(2)

 

driver.quit()

 

 

其它有些应用不好找,所以就自己创建页面,这样虽然麻烦,但脚本代码突出重点。

这里找一139邮箱的实例,有帐号的同学可以测试一下~

(登陆基础版的139邮箱,网盘模块上传文件。)

139upload.py

 

#coding=utf-8

from selenium import webdriver

import os,time

 

driver = webdriver.Firefox()

 

driver.get("http://m.mail.10086.cn")

driver.implicitly_wait(30)

 

#登陆

driver.find_element_by_id("ur").send_keys("手机号")

driver.find_element_by_id("pw").send_keys("密码")

driver.find_element_by_class_name("loading_btn").click()

time.sleep(3)

 

#进入139网盘模块

driver.find_element_by_xpath("/html/body/div[3]/a[9]/span[2]").click()

time.sleep(3)

 

#上传文件

driver.find_element_by_id("id_file").send_keys('D:\\selenium_use_case\upload_file.txt')

time.sleep(5)

 

driver.quit()

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值