Pythone_Selenium实战
自动化测试基础
什么样的项目适合自动化测试
1,任务测试明确,不会频繁变动
2,每日构建后的测试验证;
3,比较频繁的回归测试;
4,软件系统界面稳定,变动少
5,需要在多平台运行的相同案例、组合遍历型的测试、大量重复任务;
6,软件维护周期长;
7,项目进度压力不大;
8,被测软件系统开发比较规范,能够保证系统的可测试性;
9,具备大量的自动化测试平台
10,测试人员具备较强的编程能力
以上具备 3个条件,既可以开展;
什么是 Selenium?
Selenium 自动化测试工具,它主要是用于 Web 应用程序的自动化测试,但并不只局限于此,它还支
持所有基于 web 的管理任务自动化。
Selenium 的特点:
l开源,免费
l多浏览器支持:FireFox、Chrome、IE、Opera
l多平台支持:linux 、windows、MAC
l多语言支持:java、Python、Ruby、php、C#、JavaScript
l对 web 页面有良好的支持
l简单(API 简单)、灵活(用开发语言驱动)
l支持分布式测试用例执行
脚本编辑环境搭建
Phthon安装
https://www.python.org/downloads/windows/
环境变量配置
步骤:a: 右键 我的电脑�>属性->高级系统设置->环境变量配置
步骤: b: 在系统变量中点击 新建,输入如下内容(注意变量名可以随便取,变量值就是python的安装目录)
步骤:c: 在系统变量中找到 Path->选择编辑->新建,输入%PYTHON_HOME%(PYTHON_HOME就是上一步中的变量名),接着在新建再输入如下内容:%PYTHON_HOME%\Scripts、%PYTHON_HOME%\DLLs、%PYTHON_HOME%\Lib\lib-tk (注意:后面这几个是为了使用pip,esay_install而添加的,如果不需要则可不用添加了)
浏览器环境搭建
FireFox、 Chrome
安装浏览器驱动driver
1.chromedriver 下载地址:https://code.google.com/p/chromedriver/downloads/list
2.Firefo驱动下载地址:https://github.com/mozilla/geckodriver/releases/
注意:下载解压后,将chromedriver.exe , geckodriver.exe , Iedriver.exe发到Python的安装目录,例如 D:\python 。 然后再将Python的安装目录添加到系统环境变量的Path下面。
FireFox 需要安装插件 : Firebug、Firepath、Xpath find;
Chrome需要安装插件: x path for free
编写第一个自动化脚本
#coding = utf-8
#导入webdriver驱动
from selenium import webdriver
#webdriver 的 Firefox 赋值给 browser
driver = webdriver.Firefox()
#给浏览器 定义一个地址
driver.get('http://www.baidu.com')
#查找元素,同时输入selenium2
driver.find_element_by_id("kw").send_keys("selenium2")
#查找元素 点击提交
driver.find_element_by_id("su").click()
#关闭
driver.quit()
WebDriver API
ID定位 (www.baidu.com)
driver.find_element_by_id("kw")
Name定位(http://www.csdn.net/)
find_element_by_name("passwordtwo")
Class定位
find_element_by_class_name("s_ipt")
Tag定位
find_element_by_tag_name("input")
find_element_by_tag_name("input")
Link定位
link 定位与前面介绍的几种定位方法有所不同,它专门用来定位本链接。百度输入框上面的几个文本
链接的代码如下:
<a class="mnav" name="tj_trnews" href="http://news.baidu.com">新闻</a>
<a class="mnav" name="tj_trhao123" href="http://www.hao123.com">hao123</a>
<a class="mnav" name="tj_trmap" href="http://map.baidu.com">地图</a>
<a class="mnav" name="tj_trvideo" href="http://v.baidu.com">视频</a>
<a class="mnav" name="tj_trtieba" href="http://tieba.baidu.com">贴吧>
find_element_by_link_text("新闻")
find_element_by_link_text("hao123")
find_element_by_link_text()方法通过元素标签对之间的部分文本信息来定位元素
Partial link定位
parial link 定位是对 link 定们的一个种补充,有些文本连接会比较长,这个时候我们可以取文本链接的
有一部分定位,只要这一部分信息可以唯一的标识这个链接。
<a class="mnav" name="tj_lang" href="#">一个很长很长的文本链接</a>
通过 partial link 定位如下:
find_element_by_partial_link_text("一个很长的")
find_element_by_partial_link_text("文本连接")
Xpath定位
//表示当前页面某个目录下,input 表示定位元素的标签名,[@id='kw'] 表示这个元素的 id 属性值等于
kw。下面通过 name 和 class 属性值来定位。
find_element_by_xpath("//input[@id='wd']")
find_element_by_xpath("//input[@class='s_ipt']")
find_element_by_xpath("//*[@class='bg s_btn']")
如果不想指定标签名也可以用星号(*)代替。当然,使用 XPath 不仅仅只局限在 id、name 和 class 这
三个属性值,元素的任意属性值都可以使用,只要它能唯一的标识一个元素。
find_element_by_xpath("//input[@maxlength='100']")
find_element_by_xpath("//input[@autocomplete='off']")
find_element_by_xpath("//input[@type='submit']")
假如百度输入框本身没有可利用的属性值,我们可以查找它的上一级属性。比如,“小明”刚出生的
时候没有名字,没上户口(没身份证号),那么亲朋好友来找“小明”可以先到小明的爸爸,因为他爸爸
是有很多属性特征的,找到了小明的爸爸,抱在怀里的一定就是小明了。通过 XPath 描述如下:
《Selenium2 Python 自动化测试实战》样张
66
find_element_by_xpath("//span[@class='bg s_ipt_wr']/input")
find_element_by_xpath("//span[@class='bg s_btn_wr']/input")
span[@class='bg s_ipt_wr'] 通过 class 属性定位到是父元素,后面/input 也就表示父元素下面标签名为
input 的子元素。如果父元素没有可利用的属性值,那么可以继续向上查找“爷爷”元素。
find_element_by_xpath("//form[@id='form']/span/input")
find_element_by_xpath("//form[@id='form']/span[2]/input")
使用逻辑运算符
如果一个属性不能唯一的区分一个元素,我们还可以使用逻辑运算符连接多个属性来区别于其它属
性。
……
<input id="kw" class="su" name="ie">
<input id="kw" class="aa" name="ie">
<input id="bb" class="su" name="ie">
……
如上面的三行元素,假如我们现在要定位第一行元素,如果使用 id 将会与第二行元素重名,如果使用
class 将会与第三行元素的重名。那么如果同时使用 id 和 class 就会唯一的标识这个元素。那么这个时候就
可以通过逻辑运算符号连接。
find_element_by_xpath("//input[@id='kw' and @class='su']/span/input")
当然,我们也可以用 and 连接更多的属性来唯一的标识一个元素
Css定位
"百度搜索框"
<span class="soutu-btn"/>
<input id="kw" class="s_ipt" name="wd" value="" maxlength="255" autocomplete="off"/>
<a id="quickdelete" class="quickdelete" href="javascript:;" title="清空" style="top: 0px; right: 0px; display: none;"/
“百度提交按钮”
<span class="bg s_btn_wr">
<input id="su" class="bg s_btn btnhover" value="百度一下" type="submit"/>
</span>
通过class 属性定位:
find_element_by_css_selector(".s_ipt")
find_element_by_css_selector(".bg s btn btnhover")
通过id 属性定位:
find_element_by_css_selector("#kw")
find_element_by_css_selector("#su")
通过标签名定位:
find_element_by_css_selector("input")
通过父子关系定位:
find_element_by_css_selector("span>input")
上面的写法表示有父亲元素,它的标签名叫 span,查找它的所有标签名叫 input 的子元素
通过属性定位:
find_element_by_css_selector("input[autocomple='off']"
find_element_by_css_selector("input[maxlength='255']")
find_element_by_css_selector("iniput[type='submit']")
在css当中也可以使用元素的任意属性,只要这些熟悉可以唯一的标识这个元素。
组合定位:
find_element_by_css_selector("span.bg s_ipt_wr>input.s_ipt")
find_element_by_cess_selector("span.bg S_ipt_wr>input#su")
用By定位元素
from selenium.webdriver.common.by import By
具体通过哪种定位方式(id 或 name)根据实际场景而定位,By 就可以设
置定位策略
find_elenium(By.ID,"kw")
find_elenium(By.NAME,"wd")
find_elenium(By.CLASS_NAME,"s_ipt")
find_elenium(By.TAG_NAME,"input")
find_elenium(By.LINK_TEXT,u"新闻")
find_elenium(By.PARTIAL_LINK_TEXT,u"新闻")
find_elenium(By.XPATH,"//*[@class='bg s_btn]")
find_elenium(By.CSS_SELECTOR,"span.bg s_btn_wr>input#su")
控制浏览器
#设置浏览器大小
driver.set_window_size(480,800)
#设置浏览器最大化
driver.maximize_window()
浏览器的前进、后退
driver.get("http://www.baidu.com")
driver.get("http://news.baidu.com")
driver.back()
driver.forward()
简单元素操作
clear() 清除文本、send_keys(*value) 输入 、click()点击元素;
案例: 登录github
from selenium import webdriver
import time
driver = webdriver.Firefox()
driver.get("https://github.com/")
driver.find_element_by_xpath(".//*[@id='user[login]']").click()
driver.find_element_by_xpath(".//*[@id='user[email]']").send_keys("ppppppppppppppppp")
paswd=driver.find_element_by_xpath(".//*[@id='user[password]']")
paswd.send_keys("0000000000000000000000000000000000000")
paswd.clear()
time.sleep(100)
driver.quit()
注意 :接口提交数据使用submit()要求提交对象是一个表单
driver.find_element_by_xpath("xxxxx").submit()
l size 返回元素的尺寸。
l text 获取元素的文本。
user=driver.find_element_by_xpath(".//*[@id='user[login]']").size
email=driver.find_element_by_xpath("html/body/div[4]/div[6]/div[2]/form/p").text
print(user)
print(email)
l get_attribute(name) 获得属性值。
user=driver.find_element_by_xpath(".//*[@id='user[login]']").get_attribute("type")
get_attribute 可以获取 id、class、name、type
l is_displayed() 设置该元素是否用户可见ss
#返回元素的结果是否可见,返回结果为 True 或 False
email=driver.find_element_by_xpath("html/body/div[4]/div[6]/div[2]/form/p").is_displayed()
鼠标事件
ActionChains 类提供的鼠标操作的常用方法:
l perform() 执行所有 ActionChains 中存储的行为
l context_click() 右击
l double_click() 双击
l drag_and_drop() 拖动
l move_to_element() 鼠标悬停
#定位到要右击的元素
right_click =driver.find_element_by_id("xx")
#对定位到的元素执行鼠标右键操作
ActionChains(driver).context_click(right_click).perform()
from selenium.webdriver import ActionChains
对于 ActionChains 类下面的方法,在使用之前需要先将模块导入。
ActionChains(driver)
调用 ActionChains()方法,在使用将浏览器驱动 driver 作为参数传入。
context_click(right_click)
context_click()方法用于模拟鼠标右键事件,在调用时需要传入右键的元素。
perform()
执行所有 ActionChains 中存储的行为,可以理解成是对整个操作事件的提交动作
鼠标悬浮操作
#定位到要悬停的元素
above =driver.find_element_by_id("xx")
#对定位到的元素执行悬停操作
ActionChains(driver).move_to_element(above).perform()
鼠标双击操作
#定位到要悬停的元素
double_click = driver.find_element_by_id("xx")
#对定位到的元素执行双击操作
ActionChains(driver).double_click(double_click).perform()
鼠标堆放操作(拖动操作)
#定位元素的源位置
element = driver.find_element_by_name("xxx")
#定位元素要移动到的目标位置
target = driver.find_element_by_name("xxx")
#执行元素的拖放操作
ActionChains(driver).drag_and_drop(element,target).perform()
键盘事件
from selenium.webdriver.common.keys import Keys
#输入框输入内容
driver.find_element_by_id("kw").send_keys("seleniumm")
#删除多输入的一个 m
driver.find_element_by_id("kw").send_keys(Keys.BACK_SPACE)
#输入空格键+“教程”
driver.find_element_by_id("kw").send_keys(Keys.SPACE)
driver.find_element_by_id("kw").send_keys(u"教程")
#ctrl+a 全选输入框内容
driver.find_element_by_id("kw").send_keys(Keys.CONTROL,'a')
#ctrl+x 剪切输入框内容
driver.find_element_by_id("kw").send_keys(Keys.CONTROL,'x')
#ctrl+v 粘贴内容到输入框
driver.find_element_by_id("kw").send_keys(Keys.CONTROL,'v')
#通过回车键盘来代替点击操作
driver.find_element_by_id("su").send_keys(Keys.ENTER)
获得验证信息
获得验证处理 常用通过 title 和 URL text 、get_attribute() 获取属性值
#获取页面 title
driver.title
#获取页面URL
driver.current_url
#获取指定位置的,文本 信息
driver.find_element_by_xpath().text
#获取页面 title
title=driver.title
#获取页面URL
url=driver.current_url
#获取指定位置的,文本 信息
baid=driver.find_element_by_xpath(".//*[@id='su']").get_attribute("value")
设置元素等待
显示等待:
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium import webdriver
from selenium.webdriver.common.by import By
driver=webdriver.Firefox()
driver.get("http://www.baidu.com")
element=WebDriverWait(driver,5,0,5).until(
EC.presence_of_element_located((By.ID,"kw"))
)
element.send_keys("selenium")
driver.quit()
WebDriverWait()
它是由 webdirver 提供的等待方法。在设置时间内,默认每隔一段时间检测一次当前页面元素是否存
在,如果超过设置时间检测不到则抛出异常。具体格式如下:
WebDriverWait(driver, timeout, poll_frequency=0.5, ignored_exceptions=None)
driver - WebDriver 的驱动程序(Ie, Firefox,Chrome 等)
timeout - 最长超时时间,默认以秒为单位
until()
WebDriverWait()一般由 until()(或 until_not())方法配合使用,下面是 until()和 until_not()方法的说明。
until(method, message=’ ’)
调用该方法提供的驱动程序作为一个参数,直到返回值为 Ture。
until_not(method, message=’ ’)
调用该方法提供的驱动程序作为一个参数,直到返回值为 False。
Expected Conditions
在本例中, 我们在使用 expected_conditions 类时对其时行了重命名, 通过 as 关键字对其重命名为 EC,
并调用 presence_of_element_located()判断元素是否存在。
expected_conditions 类提供一些预期条件的实现。
title_is 用于判断标题是否 xx。
title_contains 用于判断标题是否包含 xx 信息。
presence_of_element_located 元素是否存在。
visibility_of_element_located 元素是否可见。
visibility_of 是否可见
presence_of_all_elements_located 判断一组元素的是否存在
text_to_be_present_in_element 判断元素是否有 xx 文本信息
text_to_be_present_in_element_value 判断元素值是否有 xx 文本信息
frame_to_be_available_and_switch_to_it 表单是否可用,并切换到该表单。
invisibility_of_element_located 判断元素是否隐藏
element_to_be_clickable 判断元素是否点击,它处于可见和启动状态
staleness_of 等到一个元素不再是依附于 DOM。
element_to_be_selected 被选中的元素。
element_located_to_be_selected 一个期望的元素位于被选中。
element_selection_state_to_be 一个期望检查如果给定的元素被选中。
element_located_selection_state_to_be 期望找到一个元素并检查是否选择状态
alert_is_present 预期一个警告信息
隐式等待
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium import webdriver
from selenium.webdriver.common.by import By
driver=webdriver.Firefox()
driver.get("http://www.baidu.com")
driver.implicitly_wait(10)
休眠设置
from time import sleep
sleep(2)
定位一组元素
通过 find_elements_xxx
如果遇到 checkbox 点击操作:
1,driver.find_element_by_xx().pop().click()
2, ActionChains(driver).double_click(driver.find_element_by_xx).perform()
如果遇到重复多的 需要进行过滤:
#然后从中过滤出 tpye 为 checkbox 的元素,单击勾选
for i in inputs:
if i.get_attribute('type') == 'checkbox':
i.click()
多表单切换
from selenium import webdriver
import time
import os
driver=webdriver.Firefox()
file_path='file:///'+ os.path.abspath('fram.html')
driver.get(file_path)
driver.switch_to.frame("if")
driver.find_element_by_id("kw").send_keys("selenium")
driver.find_element_by_id("su").click()
time.sleep(3)
driver.quit()
切换表单:
driver.switch_to.frame("if")
退回到上一步骤:
driver.switch_to.default_content()
如果表单嵌套在当前页面,要先定位表单frame:
切换表单:
driver.switch_to.frame("if")
多窗口切换
current_window_handle 获得当前窗口句柄
window_handles 返回的所有窗口的句柄到当前会话
switch_to_window()
from selenium import webdriver
from time import sleep
driver=webdriver.Firefox()
driver.implicitly_wait(10)
driver.get("http://www.baidu.com")
sreach_windows=driver.current_window_handle
driver.find_element_by_xpath(".//*[@id='u1']/a[7]").click()
sleep(3)
driver.find_element_by_xpath(".//*[@id='TANGRAM__PSP_10__submitWrapper']/a[1]").click()
sleep(3)
all_windos=driver.window_handles
for handle in all_windos:
if handle!=sreach_windows:
driver.switch_to.window(handle)
print("now register window")
driver.find_element_by_xpath(".//*[@id='TANGRAM__PSP_3__userName']").send_keys("username")
driver.find_element_by_xpath(".//*[@id='TANGRAM__PSP_3__password']").send_keys("userpassd")
for handle in all_windos:
if handle == sreach_windows:
driver.switch_to.window(handle)
print("now sreach winow")
#关闭登录tab
driver.find_element_by_xpath(".//*[@id='TANGRAM__PSP_4__closeBtn']").click()
driver.find_element_by_id("kw").send_keys("selenium")
driver.find_element_by_id("su").click()
sleep(3)
driver.quit()
警告框处理
switch_to_alert
l text 返回 alert/confirm/prompt 中的文字信息。
l accept 点击确认按钮。
l dismiss 点击取消按钮,如果有的话。
l send_keys 输入值,这个 alert\confirm 没有对话框就不能用了,不然会报错
sleep(2)
move=driver.find_element_by_xpath(".//*[@id='u1']/a[8]")
ActionChains(driver).move_to_element(move).perform()
sleep(2)
driver.find_element_by_xpath(".//*[@id='wrapper']/div[6]/a[1]").click()
sleep(2)
driver.find_element_by_xpath(".//*[@id='gxszButton']/a[1]").click()
sleep(2)
driver.switch_to.alert.accept()
上传文件
#coding=utf-8
from selenium import webdriver
import os
driver = webdriver.Firefox()
#打开上传功能页面
file_path = 'file:///' + os.path.abspath('upfile.html')
driver.get(file_path)
#定位上传按钮,添加本地文件
driver.find_element_by_name("file").send_keys('D:\\upload_file.txt')
driver.quit()
通过这种方法上传,就绕开了操作 Windows 控件的步骤。如果能找上传的 input 标签,那么基本都可
以通过 send_keys()方法向其输入一个文件地址来实现上传
下载文件
让 FireFox 让浏览器能实现文件的载,我们需要通过 FirefoxProfile() 对其参数做一个设置。
browser.download.folderList
设置成 0 代表下载到浏览器默认下载路径;设置成 2 则可以保存到指定目录。
browser.download.manager.showWhenStarting
是否显示开始,Ture 为显示,Flase 为不显示。
browser.download.dir
用于指定你所下载文件的目录。os.getcwd() 该函数不需要传递参数,用于返回当前的目录。
browser.helperApps.neverAsk.saveToDisk
指定要下载页面的 Content-type 值,“application/octet-stream”为文件的类型。HTTP Content-type 常
用对照表:http://tool.oschina.net/commons
这些参数的设置可以通过在 Firefox 浏览器地址栏输入:about:config 进行设置,如图 4.17。
图 4.17 FireFire 参数设置
操作 Cookie
业务场景:
开发人员开发一个功能,当用户登录后,会将用户的用户名写入浏览器 cookie,指定的 key 为“username”,那么我们就可以通过 get_cookies() 找到 useranme,
打印 vlaue,如果找不到 username 或对应的 value 为空,那么说明保存浏览器的 cookie 是有问题的
#coding=utf-8
from selenium import webdriver
from time import sleep
driver = webdriver.Firefox()
driver.get("http://www.baidu.com")
#获取cookie信息
cookie = driver.get_cookies()
#将获得cookie 的信息打印
print(cookie)
driver.add_cookie({'name':'key-aaaaa','value':'value-bbbbbb'})
#遍历cookies的name 和 value
for cookie in driver.get_cookies():
print("%s -> %s"%(cookie['name'],cookie['value']))
driver.quit()
l webdriver 操作 cookie 的方法有:
l get_cookies() 获得所有 cookie 信息
l get_cookie(name) 返回有特定 name 值有
l add_cookie(cookie_dict) 添加 cookie,必须有 n
l delete_cookie(name) 删除特定(部分)的 cook
l delete_all_cookies() 删除所有 cookie 信息
调用 JavaScript
通过浏览器打开百度进行搜索,搜索的一屏无法完全显示将会出现滚动条。这个时候就可以通过
JavaScript 代码控制滚动条在任意位置,需要改变的就是 scrollTop 的值。通过 execute_script()方法来执行这段 JavaScript 代码
般用到操作滚动条的会两个场景:
l 注册时的法律条文的阅读,判断用户是否阅读完成的标准是:滚动条是否拉到最下方。
l 要操作的页面元素不在视觉范围,无法进行操作,需要拖动滚动条。
#coding=utf-8
from selenium import webdriver
from time import sleep
driver = webdriver.Firefox()
driver.get("http://www.baidu.com")
#搜索
driver.find_element_by_id("kw").send_keys("selenium")
driver.find_element_by_id("su").click()
sleep(3)
#将页面滚动条拖到底部
js = "var q=document.documentElement.scrollTop=1000"
driver.execute_script(js)
js_="var q = document.documentElement.scrollTop=0"
driver.execute_script(js_)
sleep(3)
driver.quit()
窗口截图
#coding=utf-8
from selenium import webdriver
import logging
logging.basicConfig(level=logging.DEBUG)
driver = webdriver.Firefox()
driver.get("http://www.baidu.com")
try:
driver.find_element_by_id("kw_error").send_keys('selenium')
driver.find_element_by_id("su").click()
except :
driver.get_screenshot_as_file("D:\\baidu_error\\baidu_error.jpg")
driver.quit()
自动化测试模型
线性测试
模块化与类库
public.py
#coding=utf-8
from selenium import webdriver
#登陆
def login():
driver.find_element_by_id("idInput").clear()
driver.find_element_by_id("idInput").send_keys("username")
driver.find_element_by_id("pwdInput").clear()
driver.find_element_by_id("pwdInput").send_keys("password")
driver.find_element_by_id("loginBtn").click()
#退出
def logout():
driver.find_element_by_link_text(u"退出").click()
driver.quit()
driver = webdriver.Firefox()
driver.implicitly_wait(10)
driver.get("http://www.126.com")
login() #调用登陆模块
#收信、写信、删除信件等操作
logout() #调用退出模块
mail126.py
#coding=utf-8
from selenium import webdriver
from time import sleep
import public
driver = webdriver.Firefox()
driver.get("http://www.126.com")
#调用登录模块
public.login(driver)
#调用退出模块
public.logout(driver)
数据驱动
#coding=utf-8
from selenium import webdriver
file_info=open('info.txt','r')
values = file_info.readlines()
file_info.close()
for serch in values:
driver=webdriver.Firefox()
driver.implicitly_wait(10)
driver.get("http://www.baidu.com")
driver.find_element_by_id("kw").send_keys(serch)
driver.find_element_by_id("su").click()
driver.quit()
文本读取
读取txt文件
l read() 读取整个文件。
l readline() 读取一行数据。
l readlines() 读取所有行的数据
#coding=utf-8
zhangsan,123
lisi,456
wangwu,789
from selenium import webdriver
file_info=open('info.txt','r')
values = file_info.readlines()
file_info.close()
for serch in values:
username= serch.split(',')[0]
passwd=serch.split(',')[1]
读取 csv 文件
import csv
#读取本地csv文件
my_file='E:\\info.csv'
date = csv.reader(open(my_file,'rb'))
#循环输出
for user in date:
print(user)
读取xml文件
import xml.dom.minidom as do
#打开xml文档
dom=do.parse('info.xml')
#获得文档元素对象
root=dom.documentElement
获取标签的属性值
#coding=utf-8
import xml.dom.minidom
#打开 xml 文档
dom = xml.dom.minidom.parse('info.xml')
#得到文档元素对象
root = dom.documentElement
logins = root.getElementsByTagName('login')
#获得 login 标签的 username 属性值
username=logins[0].getAttribute("username")
print username
#获得 login 标签的 passwd 属性值
password=logins[0].getAttribute("passwd")
print password
items = root.getElementsByTagName('item')
#获得第一个 item 标签有 id 属性值
id1=items[0].getAttribute("id")
print id1
#获得第二个 item 标签有 id 属性值
id2=items[1].getAttribute("id")
获取标签之间的数据
#coding=utf-8
import xml.dom.minidom
#打开 xml 文档
dom = xml.dom.minidom.parse('info.xml')
#得到文档元素对象
root = dom.documentElement
captions=dom.getElementsByTagName('caption')
#获得第一个标签对的值
c1=captions[0].firstChild.data
print c1
#获得第二个标签对的值
c2=captions[1].firstChild.data
print c2
#获得第三个标签对的值
c3=captions[2].firstChild.data
print c3
unittest 单元测试框架
提供用例组织与执行:对一个功能编写几个测试用例来说,当然不同讲究用例的组织,但测试用例达
到成百上千时,就需要考虑编写用例的规范与组织,否则后期的维护成本是呈现指数级增加的。可能,我
们都无法顾及开发新功能,而花费大量的时间和精力在维护测试用例。这也是单元测试用例的目的。
提供比较方法:不是管是功能测试用例,还是单元测试都会有一个预期结果,测试的过程其实就是执
行某些操作之后拿实际的结果与预期结果进行比较,当然,这个比较有我们前面介绍来的断言与验证。
提供丰富的日志:当所有用例执行完成,要有足够清晰的日志信息告诉我哪些用例失败以及它们失败
的位置,如果没这清晰的日志,那么将会大大提供 debug 问题也是一件非常耗时的工作。
#coding=utf-8
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import Select
from selenium.webdriver.common.keys import Keys
from selenium.common.exceptions import NoSuchElementException
from selenium.common.exceptions import NoAlertPresentException
import unittest2,time,re
class BaiduTest(unittest2.TestCase):
def setUp(self):
self.driver=webdriver.Firefox()
self.driver.implicitly_wait(30)
self.base_url="http://www.baidu.com"
self.verificationErrors=[]
self.accept_next_alert= True
def test_baidu(self):
driver=self.driver
driver.get(self.base_url+"/")
driver.find_element_by_id("kw").click()
driver.find_element_by_id("kw").send_keys("selenium ide")
driver.find_element_by_id("su").click()
def is_element_present(self,how,what):
try:
self.driver.find_element(by=how,value=what)
except NoSuchElementException as e:
return False
return True
def is_alert_present(self):
try:
self.driver.switch_to.alert()
except NoAlertPresentException as e:
return False
return True
def close_alert_and_get_its_text(self):
try:
alert=self.driver.switch_to.alert()
alert_text=alert.text
if self.accept_next_alert:
alert.accept()
else:
alert.dismiss()
return alert_text
finally:
self.accept_next_alert=True
def tearDown(self):
self.driver.quit()
self.assertAlmostEqual([],self.verificationErrors)
if __name__ == '__main__':
unittest2.main()
unittest 单元测试框架解析
#coding=utf-8
from count import Count
import unittest
class TestCount(unittest.TestCase):
def setUp(self):
self.j = Count(2,3)
def test_add(self):
self.add = self.j.add()
self.assertEqual(self.add,5)
def tearDown(self):
pass
if __name__ == '__main__':
unittest.main()
unittest 的文档中开篇就介绍了 4 个重要的概念:test fixture, test case, test suite, test
runner,我觉得只有理解了这几个概念,才能真正的理解单元测试的基本原理。
test case --测试用例
一个 TestCase 的实例就是一个测试用例。什么是测试用例呢?就是一个完整的测试流程,包括测试
前准备环境的搭建(setUp),实现测试过程的代码(run),以及测试后环境的还原(tearDown)。元测试(unit
test)的本质也就在这里,一个测试用例是一个完整的测试单元,通过运行这个测试单元,可以对某一个
功能进行验证。
test suite ---测试方案
对一个功能的验证往往是需要多测试用例的,可以把多的测试用例集合在一起执行,这就产生了测试
套件 TestSuite 的概念,它用来组装单个测试用例,而且 TestSuite 也可以嵌套 TestSuite。
可以通过 addTest 加载 TestCase 到 TestSuite 中,再返回一个 TestSuite 实例。
test runner ----测试执行
TextTestRunner 是来执行测试用例的,其中的 run(test)用来执行 TestSuite/TestCase。测试的结果
会保存到 TextTestResult 实例中,包括运行了多少测试用例,成功了多少,失败了多少等信息。
test fixture -----创建于销毁
对一个测试用例环境的搭建和销毁,是一个 fixture,通过覆盖 TestCase 的 setUp()和 tearDown()
方法来实现。这个有什么用呢?比如说在这个测试用例中需要访问数据库,那么可以在 setUp()中建立数
据库连接以及进行一些初始化, 在 tearDown()中清除在数据库中产生的数据, 然后关闭连接。 注意 tearDown
的过程很重要,要为以后的 TestCase 留下一个干净的环境。
# coding=utf-8
import unittest2
class Count:
def __index__(self, a, b):
self.a = a
self.b = b
def add(self):
return self.a + self.b
class TestCount(unittest2.TestCase):
def setUp(self):
self.j = Count(2, 3)
def test_add(self):
self.add = self.j.add()
self.assertEqual(self.add, 5)
def tearDown(self):
pass
if __name__ == '__main__':
# 构造suit
suit = unittest2.TestSuite()
suit.addTest(TestCount("test_add"))
# 执行测试
test_suit = unittest2.TextTestRunner()
test_suit.run(suit)
count.py
#coding=utf-8
#计算器类
class Count:
def __init__(self,a,b):
self.a = a
self.b = b
def add(self):
return self.a + self.b
all_count.py
#coding=utf-8
from .count import Count
import unittest
class Testcase(unittest.TestCase):
def setUp(self):
pass
#测试整数相加
def test_add(self):
self.j=Count(2,3)
self.add=self.j.add()
self.assertEqual(self.add,5)
# 测试小数相加
def test_add2(self):
self.j=Count(2.3,4.2)
self.add=self.j.add()
self.assertEqual(self.add,6.5)
#测试字符窜 相加
def test_add3(self):
self.j=Count("hello","world")
self.add=self.j.add()
self.assertEqual(self.add,"helloworld")
if __name__ == '__main__':
#构造测试集
suit= unittest.TestSuite()
suit.addTest(Testcase("test_add"))
suit.addTest(Testcase("test_add2"))
suit.addTest(Testcase("test_add3"))
#执行测试
runner = unittest.TextTestRunner()
runner.run(suit)
TestLoader
该类根据各种标准负责加载测试用例,并它们返回给测试套件。正常情况下没有必要创建这个类的实
例。unittest 提供了可以共享了 defaultTestLoader 类,可以使用其子类和方法创建实例,所以我们可以
使用其下面的 discover()方法来创建一个实例。
discover(start_dir,pattern='test*.py',top_level_dir=None)
找到指定目录下所有测试模块,并可递归查到子目录下的测试模块,只有匹配到文件名才能被加载。
如果启动的不是顶层目录,那么顶层目录必须要单独指定。
start_dir :要测试的模块名或测试用例目录。
pattern='test*.py' :表示用例文件名的匹配原则。星号“*”表示任意多个字符。
top_level_dir=None:测试模块的顶层目录。如果没顶层目录(也就是说测试用例不是放在多级目录
中),默认为 None。
#coding =utf-8
import unittest
def creatsuit():
testnuit=unittest.TestSuite()
test_dir='E:\\hello'
discover=unittest.defaultTestLoader.discover(test_dir,pattern='test*.py',top_level_dir=None
)
#discover筛选出来,
for test_unit in discover:
for test_case in test_unit:
testnuit.addTest(test_case)
return testnuit
if __name__ == '__main__':
#测试执行
runner=unittest.TextTestRunner()
runner.run(creatsuit())
创建 creatsuite()函数用于查找指定条件的下的所有测试用例,并将其组装到测试套件中。
调用 discover()方法,首先通过 test_dir 定义查找测试文件的目录,pattern 用来定义匹配测试文
件的文件名,如果文件名以 test 开头的.py 文件,那么就认为它是一个测试文件。top_level_dir 默认为
None。
discover()只能找到了测试文件,接下来通过 for 循环来找到测试文件下的每一个测试用例,并且将
其添加测试套件中
项目实战
测试类型
测试静态内容
静态内容测试是最简单的测试,用于验证静态的、不变化的 UI 元素的存在性。例如:
•每个页面都有其预期的页面标题?这可以用来验证链接指向一个预期的页面。
•应用程序的主页包含一个应该在页面顶部的图片吗?
•网站的每一个页面是否都包含一个页脚区域来显示公司的联系方式,隐私政策,以及商标信息?
•每一页的标题文本都使用的<h1>标签吗?每个页面有正确的头部文本内吗?
您可能需要或也可能不需要对页面内容进行自动化测试。如果您的网页内容是不易受到影响手工对内
容进行测试就足够了。如果,例如您的应用文件的位置被移动,内容测试就非常有价值。
测试链接
Web 站点的一个常见错误为的失效的链接或链接指向无效页。链接测试涉及点各个链接和验证预期的
页面是否存在。如果静态链接不经常更改,手动测试就足够。但是,如果你的网页设计师经常改变链接,或者
文件不时被重定向,链接测试应该实现自动化。
功能测试
在您的应用程序中,需要测试应用的特定功能,需要一些类型的用户输入,并返回某种类型的结果。通常
一个功能测试将涉及多个页面,一个基于表单的输入页面,其中包含若干输入字段、提交“和”取消“操作,
以及一个或多个响应页面。用户输入可以通过文本输入域,复选框,下拉列表,或任何其他的浏览器所支持的
输入。
功能测试通常是需要自动化测试的最复杂的测试类型,但也通常是最重要的。典型的测试是登录,注册
网站账户,用户帐户操作,帐户设置变化,复杂的数据检索操作等等。功能测试通常对应着您的应用程序的描
述应用特性或设计的使用场景。
测试动态元素
通常一个网页元素都有一个唯一的标识符,用于唯一地定位该网页中的元素。通常情况下,唯一标识符
用 HTML 标记的’id’属性或’name’属性来实现。这些标识符可以是一个静态的,即不变的、字符串常量。
它们也可以是动态生产值,在每个页面实例上都是变化的。例如,有些 Web 服务器可能在一个页面实例
上命名所显示的文件为 doc3861,并在其他页面实例上显示为 doc6148,这取决于用户在检索的‘文档’。
验证文件是否存在的测试脚本,可能无法找到不变的识别码来定位该文件。通常情况下,具有变化的标识符
的动态元素存在于基于用户操作的结果页面上,然而,显然这取决于 Web 应用程序。
Ajax 的测试
Ajax 是一种支持动态改变用户界面元素的技术。页面元素可以动态更改,但不需要浏览器重新载入页
面,如动画,RSS 源,其他实时数据更新等等。Ajax 有不计其数的更新网页上的元素的方法。但是了解 AJAX
的最简单的方式,可以这样想,在 Ajax 驱动的应用程序中,数据可以从应用服务器检索,然后显示在页面上,
而不需重新加载整个页面。只有一小部分的页面,或者只有元素本身被重新加载
编写自动化测试用例
在编写用例过程中应该遵守以下几点原则:
1、一个脚本是一个完整的场景,从用户登陆操作到用户退出系统关闭浏览器。
2、一个脚本脚本只验证一个功能点,不要试图用户登陆系统后把所有的功能都进行验证再退出系统
3、尽量只做功能中正向逻辑的验证,不要考虑太多逆向逻辑的验证,逆向逻辑的情况很多(例如手
号输错有很多种情况),验证一方面比较复杂,需要编写大量的脚本,另一方面自动化脚本本身比较脆弱,
很多非正常的逻辑的验证能力不强。(我们尽量遵循用户正常使用原则编写脚本即可)
4、脚本之间不要产生关联性,也就是说编写的每一个脚本都是独立的,不能依赖或影响其他脚本。
5、如果对数据进行了修改,需要对数据进行还原。
6、在整个脚本中只对验证点进行验证,不要对整个脚本每一步都做验证。
用例存放&维护:
发送邮件:
#coding=utf-8
from selenium import webdriver
import unittest, time
from public import login
import xml.dom.minidom
#打开 xml 文档
dom = xml.dom.minidom.parse('E:\\test_object\\test_date\\login.xml')
#得到文档元素对象
root = dom.documentElement
《Selenium2 Python 自动化测试实战》样张
193
class TestSendMail(unittest.TestCase):
def setUp(self):
self.driver = webdriver.Firefox()
self.driver.maximize_window()
self.driver.implicitly_wait(30)
logins = root.getElementsByTagName('url')
self.base_url=logins[0].firstChild.data
self.verificationErrors = []
#只填写收件人发送邮件
def test_send_mail(self):
driver = self.driver
driver.get(self.base_url)
#登录
login.login(self,"testingwtb","a123456")
#写信
driver.find_element_by_css_selector("#_mail_component_47_47 >
span.oz0").click()
#填写收件人
driver.find_element_by_xpath("//*[@class='bz0']/div[2]/div/input")
.send_keys('testingwtb@126.com')
#发送邮件
driver.find_element_by_xpath("/html/body/div[2]/div/div[2]/header
/div/div/div/span[2]").click()
driver.find_element_by_xpath("//*[@class='nui-msgbox-ft-btns']
/div/span").click()
#断言发送结果
text = driver.find_element_by_class_name('tK1').text
self.assertEqual(text,u'发送成功')
login.logout(self)
def tearDown(self):
self.driver.quit()
self.assertEqual([], self.verificationErrors)
if __name__ == "__main__":
unittest.main()
系统会弹框提示“确定真的不需要写主题吗?”,在用例中默认 click
“确定”。邮件发送成功,验证“发送成功”的提示信息
搜索邮件:
............................
#搜索邮件
def test_search_mail(self):
driver = self.driver
driver.get(self.base_url)
#调用登录模块
login.login(self,'testingwtb','a123456')
#搜索邮件
driver.find_element_by_xpath("//input[@class='nui-ipt-input' and
@type='text']").send_keys(u'小明')
driver.find_element_by_xpath("//input[@class='nui-ipt-input' and
@type='text']").send_keys(Keys.ENTER)
#断言搜索邮件标签页面
text= driver.find_element_by_xpath("//div[@id='dvMultiTab']/ul
/li[5]/div[3]").text
self.assertEqual(text,u'搜索邮件')
#调用退出
login.logout(self)
.........................................
自动化测试高级应用
安装和使用HTMLTestRunner生成测试报告
HTMLTestRunner 是 Python 标准库的 unittest 单元测试框架的一个扩展。它生成易于使用的 HTML 测
试报告。 HTMLTestRunner 是在 BSD 许可证下发布。
首先要下 HTMLTestRunner.py 文件,下载地址:
http://tungwaiyip.info/software/HTMLTestRunner.html
HTMLTestRunner.py 本是一个.py 文件,将它放到 Python 安装目录下即可调用。
Windows :将下载的文件放入...\Python\Lib 目录下。
#coding=utf-8
from selenium import webdriver
import unittest, time
import HTMLTestRunner #引入 HTMLTestRunner 包
class Baidu(unittest.TestCase):
def setUp(self):
self.driver = webdriver.Firefox()
self.driver.implicitly_wait(10)
self.base_url = "http://www.baidu.com/"
self.verificationErrors = []
# 百度搜索用例
def test_baidu_search(self):
driver = self.driver
driver.get(self.base_url)
driver.find_element_by_id("kw").send_keys("HTNMLTestRunner")
driver.find_element_by_id("su").click()
def tearDown(self):
self.driver.quit()
self.assertEqual([], self.verificationErrors)
if __name__ == "__main__":
#测试套件
testunit=unittest.TestSuite()
#添加测试用例到测试套件中
testunit.addTest(Baidu("test_baidu_search"))
#定义个报告存放路径
filename = 'E:\\result.html'
fp = open(filename, 'wb')
#定义测试报告
runner =HTMLTestRunner.HTMLTestRunner(
stream=fp,
title=u'百度搜索测试报告',
description=u'用例执行情况:')
#运行测试用例
runner.run(testunit)
#关闭报告文件
fp.close()
更易读的测试报告
……
#百度搜索用例
def test_baidu_search(self):
u'''百度搜索用例'''
driver = self.driver
driver.get(self.base_url)
driver.find_element_by_id("kw").send_keys("HTNMLTestRunner")
driver.find_element_by_id("su").click()
……
再次运行测试用例,查看测试报告。如图 9.2
测试报告文件名称
time
time.time() 获取当前时间戳。
time.ctime() 当前时间的字符串形式。
time.localtime() 当前时间的 struct_time 形式。
time.strftime() 用来获得当前时间,可以将时间格式化为字符串。
Python 中时间日期格式化符号(区分大小写):
Directive | Meaning |
%a | 星期几的简写 |
%A | 星期几的全称 |
%w | 十进制表示的星期几(值从 0 到 6,星期天为 0) |
%d | 十进制表示的每月的第几天 |
%b | 月份的简写 |
%B | 月份的全称 |
%m | 十进制表示的月份 |
%y | 不带世纪的十进制年份(值从 0 到 99) |
%Y | 带世纪部分的十制年份 |
%H | 24 小时制的小时 |
%I | 12 小时制的小时 |
%p | 本地的 AM 或 PM 的等价显示 |
%M | 十时制表示的分钟数 |
Directive | Meaning |
%S | 十进制的秒数 |
%f | 十进制的微秒,零填充左边 |
%Z | 当前时区的名称 |
%j | 十进制表示的每年的第几天 |
%U | 一年中的星期数(00-53)星期天为星期的开始 |
%W | 一年中的星期数(00-53)星期一为星期的开始 |
%x | 本地相应的日期表示 |
%X | 本地相应的时间表示 |
%% | %号本身 |
#获取当前时间
now = time.strftime("%Y-%m-%d %H_%M_%S")
#定义个报告存放路径
filename = 'E:\\test_object\\report\\'+now+'result.html'
#coding=utf-8
import unittest
import HTMLTestRunner
import time
def creatsuite():
testunit=unittest.TestSuite()
#定义测试文件查找的目录
test_dir='E:\\test_object\\test_case'
#定义 discover 方法的参数
discover=unittest.defaultTestLoader.discover(test_dir,pattern='test*.py',
top_level_dir=None)
#discover 方法筛选出来的用例,循环添加到测试套件中
for test_case in discover:
print test_case
testunit.addTests(test_case)
return testunit
now = time.strftime("%Y-%m-%d %H_%M_%S")
filename = 'E:\\test_object\\report\\'+now+'result.html'
fp = file(filename, 'wb')
runner =HTMLTestRunner.HTMLTestRunner(
stream=fp,
title=u'百度搜索测试报告',
description=u'用例执行情况:')
alltestnames = creatsuite()
runner.run(alltestnames)
fp.close()
Selenium Grid2
Selenium2 工作原理
Selenium2 中因为使用的 WebDriver,这个技术不是靠 js 驱动的,而是直接调用浏览器的原生态接口
驱动的。所以就没有同源问题,也就不需要使用 RC 来执行本地脚本了(当然缺点就是并不是所有的浏览
器都有提供很好的驱动支持,但 JavaScript 却是所有浏览器都通用的)。所以 Selenium2 中执行本地脚
本的方式是:通过本地 WebDriver 驱动直接调用本地浏览器接口就可以了。
Selenium 1(RC)代码
我们可以通过 Selenium IDE 将录制的脚本导出为“Python2/unittest/Remote Control”格式。通过
编辑器打开导出的脚本
selenium grid 工作方式
#coding=utf-8
from selenium import selenium
import unittest, time, re
class serc(unittest.TestCase):
def setUp(self):
self.verificationErrors = []
self.selenium = selenium("localhost", 4444, "*chrome",
"http://www.baidu.com/")
self.selenium.start()
def test_serc(self):
sel = self.selenium
sel.open("/")
sel.type("id=kw", "selenium grid")
sel.click("id=su")
sel.wait_for_page_to_load("30000")
def tearDown(self):
self.selenium.stop()
self.assertEqual([], self.verificationErrors)
if __name__ == "__main__":
unittest.main()
Selenium Server 环境配置
环境搭建
第一步、 配置 java 环境
java 下载地址:http://www.java.com/zh_CN/download/manual.jsp
第二步、下载运行 selenium server
下载地址:http://selenium-release.storage.googleapis.com/2.41/selenium-server-2.41.0.zip
在页面的左侧列表中找到 selenium-server-standalone-XXX.jar 进行下载。下载完成可以放到任意
位置,直接在命令提示符下启动 Selenium Server:
C:\selenium> java -jar selenium-server-standalone-XXX.jar
调用 Selenium Grid 的基本结构图
样例演示 :
在浏览器中打开:http://127.0.0.1:4444/grid/console
Selenium Grid 应用
WebDriver 提供了 Remote 可以发送指令到远程服务器控制浏览器。 首先我们先来认识 Remote 的格式
from selenium.webdriver import Remote
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
driver = Remote(command_executor='http://127.0.0.1:4444/wd/hub',
desired_capabilities=DesiredCapabilities.CHROME
)
driver.get('http://www.baidu.com')
……
driver.quit()
Desired Capabilities 本质上是 key value 的对象,它告诉 Selenium Server 脚本执行的基本运行环
境:
'platform': 'ANY' 平台默认可以是任何(Windows,MAC,android)。
'browserName': 'chrome' 浏览器名字是 chrome。
'version': '' 浏览器的版本默认为空。
'javascriptEnabled': True javascript 启动状态为 True
from selenium.webdriver import Remote
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
driver = Remote(command_executor='http://127.0.0.1:4444/wd/hub',
desired_capabilities={'platform': 'ANY',
'browserName':'chrome',
'version': '',
'javascriptEnabled': True
})
driver.get('http://www.baidu.com')
……
driver.quit()
WebDriver API 提供了不同平台及浏览器的参数:
ANDROID = {'platform': 'ANDROID', 'browserName': 'android', 'version': '', |
CHROME = {'platform': 'ANY', 'browserName': 'chrome', 'version': '', |
FIREFOX = {'platform': 'ANY', 'browserName': 'firefox', 'version': '', |
HTMLUNIT = {'platform': 'ANY', 'browserName': 'htmlunit', 'version': ''} |
HTMLUNITWITHJS = {'platform': 'ANY', 'browserName': 'htmlunit', 'version': |
INTERNETEXPLORER = {'platform': 'WINDOWS', 'browserName': 'internet |
IPAD = {'platform': 'MAC', 'browserName': 'iPad', 'version': '', |
IPHONE = {'platform': 'MAC', 'browserName': 'iPhone', 'version': '', |
SAFARI = {'platform': 'ANY', 'browserName': 'safari', 'version': '', |
PHANTOMJS = {'platform': 'ANY', 'browserName': 'phantomjs', 'version': '', |
OPERA = {'platform': 'ANY', 'browserName': 'opera', 'version': '', |
参数化浏览器执行用例
#coding=utf-8
from selenium.webdriver import Remote
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
#浏览器数组
lists=['chrome','firefox','internet explorer']
#读取不同的浏览器执行脚本
for browser in lists:
print browser
driver = Remote(
command_executor='http://127.0.0.1:4444/wd/hub',
desired_capabilities={'platform': 'ANY',
'browserName':browser,
'version': '',
'javascriptEnabled': True
})
driver.get("http://www.baidu.com")
driver.find_element_by_id("kw").send_keys(browser)
driver.find_element_by_id("su").click()
driver.close()
多节点执行用例
#coding=utf-8
from selenium.webdriver import Remote
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
#定义主机与浏览器
lists={'http://127.0.0.1:4444/wd/hub':'chrome',
'http://127.0.0.1:5555/wd/hub':'firefox',
'http://127.0.0.1:5556/wd/hub':'internet explorer'}
#通过不同的浏览器执行脚本
for host,browser in lists.items():
print host,browser
driver = Remote(
command_executor=host,
desired_capabilities={'platform': 'ANY',
'browserName':browser,
'version': '',
'javascriptEnabled': True
})
driver.get("http://www.baidu.com")
driver.find_element_by_id("kw").send_keys(browser)
driver.find_element_by_id("su").click()
driver.close()
启动远程 node
我们目前启动的 hub 与 node 都是在一台主机上。 那么要在其它主机启动 node 必须满足以下几个要求:
l 本地 hub 主机与远程 node 主机之间可以相互 ping 通。
l 远程主机必须安装运行脚本的运行环境(Python 、Selenium、浏览器及浏览器驱动 )。
l 远程主机必须安装 java 环境,因为需要运行 Selenium Server。
操作步骤如下:
启动本地 hub 主机(本地主机 IP 为:172.16.10.66):
C:\selenium>java -jar selenium-server-standalone-2.39.0.jar -role hub |
启动远程主机(操作系统:Ubuntu ,IP 地址:172.16.10.34):
远程主机启动 node 方式如下:
fnngj@fnngj-VirtualBox:~/selenium$ java -jar selenium-server-standalone-2.39.0ar -role node -port 5555 |
(设置的端口号为:5555 ,指向的 hub ip 为 172.16.10.66)
修改远程主机的 IP 地址及端口号,在其上面的 firefox 浏览下运行脚本。
hosts.py
……
#定义主机与浏览器
lists={'http://127.0.0.1:4444/wd/hub':'chrome',
'http://127.0.0.1:5555/wd/hub':'internet explorer',
'http://172.16.10.34:5555/wd/hub': 'firefox'}
……
小技巧:
自从使用 Selenium Server 执行自动化脚本后,常常会因为忘记启动 Selenium Server 导致脚本运行
报错。其实我们以在脚本中执行 cmd 命令。如在我们创建的 all_test.py 文件中添加:
import os
os.chdir('E:\\selenium')
os.system('java -jar selenium-server-standalone-2.39.0.jar')
这样就再也不会因为忘记启动 Selenium Server 导致测试脚本运行失败了
https://www.cnblogs.com/yufeihlf/p/5764099.html
http://blog.csdn.net/boonya/article/details/55049483