大家好,本文将围绕python selenium教程视频展开说明,pythonselenium环境搭建是一个很多人都想弄明白的事情,想搞清楚python+selenium+unittest需要先了解以下几个事情。
实战只想说一句:那就是结合你现在所在的项目,去写覆盖基本功能的用例吧。碰到一个问题,解决一个问题,坚持不懈,你终究完成python工程师怎么考。
背景:代码是携程网预定票的过程。
(1)文件目录,各目录代码
(2)代码优化、重构,代码层次框架介绍、
(3)异常处理、日志处理、智能等待
(1)请看代码:
基础代码层function.py
# coding=utf-8
from datetime import datetime,date,timedelta
from selenium import webdriver
import logging,os,xlrd,xlwt
import urllib3
# 以下为driver设置和打开携程火车票网站
# driver = webdriver.Chrome()
'''
函数return_driver()的功能是返回driver对象
'''
def return_driver():
return driver
'''
函数open_base_site(url)的功能是打开携程火车票首页面
'''
def open_base_site(url):
driver.get(url)
'''
函数date_n(n)将返回n天后的日期
'''
def date_n(n):
return str((date.today() + timedelta(days = +int(n))).strftime("%Y-%m-%d"))
'''
函数id将返回按照id属性来定位元素的语句
'''
def id(element):
return driver.find_element_by_id(element)
'''
函数css将返回css selector方式来定位元素的语句
'''
def css(element):
return driver.find_element_by_css_selector(element)
'''
函数xpath将返回xpath方式来定位元素的语句
'''
def xpath(element):
return driver.find_element_by_xpath(element)
'''
函数js通过selenium来执行java语句
'''
def js(element):
driver.execute_(f"document.getElementById(f'{element}').removeAttribute('readonly')")
'''
函数log()定义了日志的输出格式
'''
def log(str):
# 日志基础配置
logging.basicConfig(
level=logging.INFO, # 定义了日志的输出级别
datefmt='%a,%d,%b,%Y,%H:%M:%S', # 定义了日志输出的时间格式
filename='D:\\ui_date\\log-selenium.log', # 定义了日志输出路径文件
filemode='a', #日志以追加的形式进入log-selenium.log
format='%(asctime)s%(filename)s%(levelname)s%(message)s' # 定义了日志的输出形式
)
# 定义streamhandler格式的日志
console = logging.StreamHandler()
# 设置日志格式
console.setFormatter(logging.INFO)
console.setFormatter(logging.Formatter('%(name)-12s:%(levelname)-8s %(message)s'))
# 给日志添加定义后的handler
logging.getLogger('').addHandler(console)
logging.info(str)
'''
函数read_excel是输出第几列的内容,如果不给cloumn的值,默认是以列表的形式输出所有内容
filename:文件路径一直到文件
index:索引值第几页
cloumn:第几列
'''
def read_excel(filename,index,cloumn):
# 打开excel文件,filename是绝对路径或者相对路径下的文件
xls = xlrd.open_workbook(filename)
# 打开第几个sheet页
sheet = xls.sheet_by_index(index)
# print(sheet.nrows) 行
# print(sheet.ncols) 列
# 内容以字典的形式输出,不给cloum值,默认是输出所有表哥的所有内容
dic={}
for j in range(sheet.ncols):
date=[]
for i in range(sheet.nrows):
date.append(sheet.row_values(i)[j])
dic[j]=date
return dic
if __name__ == "__main__":
logging.log(logging.DEBUG,"我是dbug级别的")
logging.log(logging.INFO,"我是info级别的")
logging.log(logging.WARNING,"我是warning级别的")
logging.log(logging.ERROR,"我是error级别的")
logging.log(logging.CRITICAL,"我是critical级别的")
业务代码层search_tickets.py
'''
此页面的功能是测试火车票查询的页面元素
'''
from selenium.webdriver.common.action_chains import ActionChains
from functions import date_n,id,css,xpath,js,return_driver,open_base_site
from selenium import webdriver
import time
'''
函数名:search_tickets
参数:
from_station:出发站
to_station:到达站
n:是一个数字,如1表示选择明天的车票,2表示选择后天的车票
'''
def search_tickets(from_station,to_station,n):
driver = return_driver()
open_base_site('https://trains.ctrip.com/')
driver.maximize_window()
driver.implicitly_wait(10)
# from_station = '上海'
from_station = from_station
# to_station = '杭州'
to_station = to_station
# 以下为tommorrow变量
tomorrow = date_n(n)
# 以下为定位出发城市和到达城市的页面元素,设置其值为以上定义值
css('[placeholder="出发城市"]').send_keys(from_station)
id("arriveCityName").send_keys(to_station)
# 移除出发时间的“readonly”属性
js("date0bj")
time.sleep(2)
# 清除出发时间的默认值
id('dateObj').clear()
time.sleep(2)
# 以下定位为搜索车次日期
id('dateObj').send_keys(tomorrow)
# 以下步骤是为了解决日期控件弹出框在输入日期后无法消失的问题,以防影响测试的进行,原理是鼠标点击空白处
ActionChains(driver).move_by_offset(0,0).click().perform()
# 单击“车次搜索”按钮
id('searchbtn').click()
# 实例化类,run才有结果
if __name__ == '__main__':
search_tickets("上海","杭州",1)
测试代码层test_booking_tickets.py
import time
from functions import date_n,id,css,xpath,js,return_driver,open_base_site
from search_tickets import search_tickets
# 搜索网站火车票列表
search_tickets("上海","杭州",1)
driver = return_driver()
time.sleep(2)
# 点击预订按钮
xpath("/html/body/div[7]/div/div[5]/div[3]/div/div[1]/div[6]/div[1]/a").click()
# 输入乘客姓名
css('[placeholder="姓名,请与所持证件上的一致"]').send_keys("小张")
(2)代码优化、重构
代码优化有2点:
1、减少代码量提高复用率、提高健壮性(大数据情况下)、可读性、扩展性
2、提高代码可读性,代码重构可以用定义函数来实现。如:
# coding=utf-8
from selenium import webdriver
import time
from selenium.webdriver.common.keys import Keys
# 定义函数部分,减少代码量的且提高复用率,如果定义函数的部分必须放在测试代码前面。
def id(element):
return driver.find_element_by_id(element)
def css(element):
return driver.find_element_by_css_selector(element)
def xpath(element):
return driver.find_element_by_xpath(element)
def js(element):
return driver.execute_("document.getElementById(" + "'" + element + "'" + ").removeAttribute('readonly')")
driver = webdriver.Chrome()
driver.get("https://www.hao123.com/")
driver.maximize_window()
# 百度网站的id值
id("kw").click()
css([adsads="sdfs"]).click()
代码重构
随着代码增多,函数和测试代码放一个文件,扩展难、维护难,所以适当给函数添加变量而避免硬编码。最终目的是使测试代码越简洁、越清晰。
项目代码分为三层架构:自动化初期更需要好好规划代码结构和思路,不然后期重构代码越来越大。
1、测试代码层
2、业务代码层
3、基础代码层
基础代码层:封装了selenium、webdriviver的相关配置,如function.py的内容
# coding=utf-8
from selenium import webdriver
import time
from selenium.webdriver.common.keys import Keys
# 定义函数部分,减少代码量的且提高复用率
# coding=utf-8
from selenium import webdriver
import time
# 以下为driver设置和打开测试网站
driver = webdriver.Chrome()
# def return_driver():
# return driver
# 打开网页
# def open_base_site(url):
# driver.get(url)
# 定义函数部分,减少代码量的且提高复用率
def id(element):
return driver.find_element_by_id(element)
def css(element):
return driver.find_element_by_css_selector(element)
def xpath(element):
return driver.find_element_by_xpath(element)
def js(element):
return driver.execute_("document.getElementById(" + "'" + element + "'" + ").removeAttribute('readonly')")
业务代码层:
"""
函数名:lang
参数:
a是url
b是用户名
c是密码
"""
def land(a,b,c):
driver = webdriver.Chrome()
driver.get(f"{a}")
driver.find_element_by_id("kw").send_keys(f"{b}")
driver.find_element_by_id('mn').send_keys(f"{c}")
driver.find_element_by_id('submit').click()
time.sleep(1)
driver.maximize_window()
测试代码层:
实现了测试用例。
所谓的重构、优化,也就是随着项目的进行,我们需要变动基础代码层、业务代码层,从而使我们的测试代码层能更好的进行。
一、异常处理
1、selenium异常处理,参考接口自动化的异常处理,那个非常不错,常见异常如下:
# coding=utf-8
import selenium
import logging
# 操作数据库的方法
class OperationDbInterface(object):
# 初始化数据库连接
def __int__(self, a):
try:
if 0 == 0:
pass
else:
print("i")
# 打开游标
print("ok")
except error as e:
print('创建数据库失败|Mysql Error %d: %s' % (e.args[0], e.args[1]))
# 配置日志格式
logging.basicConfig(filename=config.src_path + 'E:/log/syserror.log', level=logging.DEBUG,
format='%(asctime)s %(filename)s[line:%(lineno)d]%(levelname)s %(message)s')
# 获取日志
logger = logging.getLogger(__name__)
# 输出日志
logger.exception(e)
# selenium常见的9种异常。
# (1)NoSuchElementException:选择器返回元素失败时,抛出异常
# (2)ElementNotVisibleException:定位的元素在DOM中存在,在页面不显示,不能交互时
# (3)ElementNotSelectableException:选择了不可选的元素
# (4)NoSuchFrameException:要切换的frmae不存在
# (5)NoSuchWindowException:要切换的新窗口不存在
# (6)TimeoutException:当代码执行时间超出时
# (7)NoSuchAttributeException:元素的属性找不到
# (8)UnexpectedTagNameException:当支持类没有获得预期的web元素时
# (9)NoAlertPresentException:一个意外的警告
二、日志模块简单介绍
# coding=utf-8
import logging
'''
函数log()定义了日志的基础配置
'''
def log(str):
# 日志基础配置
logging.basicConfig(
level=logging.INFO, # 定义了日志的输出级别
datefmt='%a,%d,%b,%Y,%H:%M:%S', # 定义了日志输出的时间格式
filename='D:\\ui_date\\log-selenium.log', # 定义了日志输出路径文件
filemode='a', #日志以追加的形式进入log-selenium.log
format='%(asctime)s%(filename)s%(levelname)s%(message)s' # 定义了日志的输出形式
)
# 定义streamhandler格式的日志
console = logging.StreamHandler()
# 设置日志格式
console.setFormatter(logging.INFO)
console.setFormatter(logging.Formatter('%(name)-12s:%(levelname)-8s %(message)s'))
# 给日志添加定义后的handler
logging.getLogger('').addHandler(console)
logging.info(str)
if __name__ == "__main__":
logging.log(logging.DEBUG,"我是dbug级别的")
logging.log(logging.INFO,"我是info级别的")
logging.log(logging.WARNING,"我是warning级别的")
logging.log(logging.ERROR,"我是error级别的")
logging.log(logging.CRITICAL,"我是critical级别的")
三、智能等待
因为在每一个定位元素的操作之前都加上等待时间太麻烦了,所以加上全局的智能等待时间:driver.implicitly_wait(10)
意思就是:所有的定位操作当中,浏览器最多等10秒,超过10秒就报错了
# coding=utf-8
from selenium import webdriver
import time
from selenium.common import exceptions as ex
driver = webdriver.Chrome()
driver.get("https://www.hao123.com/")
driver.maximize_window()
driver.implicitly_wait(10)
版权归原作者 YYmmsss 所有, 如有侵权,请联系我们删除。