自己在做selenium自动化测试的时候,写了几个常用的模块,可以减少重复代码的编写,这里记录下。
一、获取WebDriver
# 获取默认的远程浏览器driver
def getDefaultChromeRemoteDriver():
return webdriver.Remote(command_executor='http://xxx.xxx.xx.xx:4444/wd/hub',desired_capabilities=DesiredCapabilities.CHROME)
# 获取远程浏览器driver,使用自己指定的selenium-server
def getChromeRemoteDriver(remoteUrl):
return webdriver.Remote(command_executor=remoteUrl,desired_capabilities=DesiredCapabilities.CHROME)
这里写了两个获取RemoteDriver的方法,一个是使用默认的远程服务地址,一个是自己指定的服务地址。正式环境中可以使用默认的,自己测试的时候可以指定自己的服务地址。顺便说一句,使用RemoteDriver的好处是,浏览器和脚本不一定要在一起!比如我应用和脚本部署在linux机器上,而浏览器最稳定的还是windows环境,这样我就可以把浏览器安装在windows机器上,然后部署一个selenium-server-standalone即可。具体怎么做可以参考我的这篇文章:搭建Selenium-Server-StandAlone服务。
二、登录模块
# 默认登录,使用amdin用户
def defaultLogin(driver,loginUrl="http://xx.xx.xx.xx:xx/xx/login"):
driver.get(loginUrl);
userName = driver.find_element_by_xpath(".//*[@id='id']");
userName.clear();
userName.send_keys("admin");
password = driver.find_element_by_xpath(".//*[@id='pwd']");
password.clear();
password.send_keys("xxx");
code = driver.find_element_by_xpath(".//*[@id='check_code']");
code.clear();
code.send_keys("xxx");
loginBtn = driver.find_element_by_xpath(".//*[@id='login']/span/span");
loginBtn.click();
# 通用登录,需提供用户,密码,万能验证码
def login(driver,loginUrl,username,pwd,vcode):
driver.get(loginUrl);
userName = driver.find_element_by_xpath(".//*[@id='id']");
userName.clear();
userName.send_keys(username);
password = driver.find_element_by_xpath(".//*[@id='pwd']");
password.clear();
password.send_keys(pwd);
code = driver.find_element_by_xpath(".//*[@id='check_code']");
code.clear();
code.send_keys(vcode);
loginBtn = driver.find_element_by_xpath(".//*[@id='login']/span/span");
loginBtn.click();
Web自动化测试,第一关通常就是模拟登录,如果有验证码的话,就棘手了。一般是需要后台应用开发一个万能验证码的功能,然后对于特定的用户,输入用户名,密码加上这个万能验证码,就可以登录了。这就避免了需要去做一个验证码识别的功能。这个模块很简单,替换掉里面的xpath为你自己的登录页面相应元素的xpath就可以了。
三、智能find模块
有时候元素加载需要时间,例如菜单加载完成后,我们才可以选中某个菜单并点击,如果还没加载完成就点击,那么脚本会报错,导致测试进行不下去。最简单的做法是设置一个隐性的等待时间,但这里不推荐,因为它会增加测试的时间。最佳实践是提供一个重试次数,获取不到则等待一会,再次尝试获取,如果超过设置的最大次数,则抛出错误。
# 智能find
def smart_find_element(driver,byType,value):
ele = None;
max_time = 10; # 最多允许重试10次
times = 0;
while(ele == None):
try:
ele = driver.find_element(byType,value);
except :
times += 1;
if(times > max_time):
raise Exception(u'查找元素超过最大次数');
time.sleep(1); #休息1s
if(ele != None):
return ele;
这里设置的最大重试次数为10次,每次间隔1s。很简单,却很好用。
四、业务模板
通常一个测试脚本的操作步骤都是获取driver,登录,获取传递进脚本的参数,业务逻辑,关闭driver这几个步骤,因此我们可以将其封装起来,用户只需要提供一个业务逻辑的操作函数即可。
# 测试模板代码,测试脚本只需要提供业务逻辑即可
def startLogic(businessLogic,remoteUrl='http://xxx.xx.xxx.xxx:4444/wd/hub'):
# 模板代码
driver = getChromeRemoteDriver(remoteUrl);
try:
# 拿到参数
try:
expect = json.loads(sys.argv[1].replace('!','"')); # 期望结果,可根据实际业务修改
inParam = json.loads(sys.argv[2].replace('!','"')); # 输入参数,可根据实际业务修改
except Exception,args:
raise Exception(u"参数解析异常",args);
# 业务方法调用
businessLogic(driver,expect,inParam);
except Exception,args:
raise Exception(u"脚本异常",args);
finally:
if(driver != None):
try:
driver.close();
finally:
driver.quit();
最后上一个完整的测试脚本例子:
#!/usr/bin/python
# -*- coding: utf-8 -*-
'''
示例脚本写法
@author gameloft9 2018.7.11
'''
from selenium import webdriver;
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities;
from selenium.webdriver.common.by import By;
import SupportUtil; # 写的模块放在SupportUtil里面
# 业务代码(根据自己业务逻辑替换即可)
# @param driver
# @param expect 期望参数json对象
# @param inParam 输入参数json对象
def go_manager(driver,expect,inParam):
# 登录
SupportUtil.defaultLogin(driver);
# 业务逻辑
SupportUtil.smart_find_element(driver,By.XPATH,".//*[@id='tree']/li[3]/div/span[3]").click();
# 返回结果,json字符串格式
print "{'pass':true,'result':'234234'}"; #通过print返回结果
# 入口
SupportUtil.startLogic(go_manager)
因为我是通过应用调起的python脚本,所以有输入参数,有返回结果。如果不需要的话,这两者都可以去掉。