Python的selenium自动化测试脚本
本次主题是测试新版的一个web版的数据库客户端,适用于各种主流数据库,测试的目的:主要测试各种sql的执行情况,后根据结果针对性的优化;附上运行录屏地址;
总体思路步骤:
1.加载不同数据库类型的测试案例,组成不同list;
2.登录系统,由于无法点击到执行sql页面,所以指定输入网址到达指定页面;
3.清空所有执行窗口,由于系统自动保存执行窗口,所以输入窗口刷新到统一的状态;
4.循环点击数据库标签,打开这个数据库的sql执行窗口,根据数据库类型选择测试案例;
5.循环sql执行:循环测试案例,其中重复操作为—点击编辑框,输入sql,点击运行,获取结果,清空输入的sql,刷新窗口;
6.结果处理:获取的结果和测试案例信息组成新的list,写入结果文件,异常结果截图保存文件目录;
7.循环测试所有的数据源,循环结束,sql结束;
本次开发总结,会在代码块做注释:
1.在有些标签无法点击或者无法获取时,可以绕开点击,如果有固定网址一样可以输入网址到达指定页面;
2.在菜单栏固定区域的标签获取时,可以用循环判断标签内容,后期变动或者修改简单;
3.如果一个功能按钮可能出现在多个标签位置时,可以尝试用try捕捉,但是如果是3个位置时,还未想到办法;
4.对于需要显示等待的事件或者结果,也可以判断反馈结果,如果有结果就跳出while True,如果没有结果循环等待;
5.对于变化的标签时,如果我们每次操作固定,那就可以让变化的便签都刷新成统一状态,这样便于操作,因为我们的目的是测试sql的执行结果,要的是结果而不是这个页面变化而产生的BUG;
# -*- coding: utf-8 -*-
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
from lxml.html import fromstring, tostring
from lxml import etree
import time
import xlrd
from xlrd import xldate_as_tuple
import csv
import numpy as np
import os
from datetime import datetime, date, timedelta
def check_executesql(screenshot_path,mysql_testsqllist,oracle_testsqllist,db2_testsqllist):
#在执行平台,查询各个sql结果,有结果的获取结果存入excel文档,异常信息进行截图及获取信息;
sqllist=[]
sqltoday=str(time.strftime('%Y-%m-%d-%h:%m',time.localtime()))
sqlday=str(time.strftime('%Y-%m-%d',time.localtime()))
# input()
filename='tablespace-'+sqltoday
sqllist=["sql",filename]
driver=webdriver.Chrome()
# driver=webdriver.Firefox()
driver.get("http://9.1.10.129:8888/login/")
#将浏览器最大化显示
driver.maximize_window()
# 填充用户名 密码 验证码
# driver.find_element_by_id("username").send_keys("pengwu")
# driver.find_element_by_id("password").send_keys("123456")
driver.find_element_by_xpath('//input[@placeholder="请输入用户名"]').send_keys('test')
driver.find_element_by_xpath('//input[@placeholder="请输入密码"]').send_keys('123456')
# 点击登录 登陆成功
# driver.find_element_by_class_name("ant-btn ant-btn-primary ant-btn-lg").click()
driver.find_element_by_xpath("//button").click()
time.sleep(2)
#这个用到1,由于无法点击到目标标签,没辙只能数据网址跳转到指定页面
driver.get("http://9.1.10.129:8888/hermes/workspace/")
time.sleep(3)
# 点击工作台,用循环式,利于后期迁移或修改
benchs=driver.find_elements_by_xpath('//ul[@role="menubar"]/div')
for bench in benchs:
benchvalue=bench.text
# 所有执行平台标签
# print('执行平台标签',benchvalue)
#获取文件
if '工作台'==benchvalue:
bench.click()
time.sleep(2)
#所有数据源标签名称
databases=driver.find_elements_by_xpath('//div[@class="tree_3hqfs"]/main/section[1]/div/div')
print('数据源个数:',len(databases))
sqllist=[]
for i in range(1,len(databases)+1):
# 每次选择新的数据源前,先把输入框全部删除
# 由于获取编辑框数量随着关闭减少,所以按照标签个数删除异常,所以永远删除标签为3的编辑框,直到编辑框个数为0;
sqlexecutes=driver.find_elements_by_xpath('//div[@class="ivu-tabs-nav-wrap"]/div/div')
print('清空sql执行区域个数:',len(sqlexecutes)-2)
for x in range(len(sqlexecutes)-2):
se=driver.find_elements_by_xpath('//div[@class="ivu-tabs-nav-wrap"]/div/div')
if len(se)>2:
driver.find_element_by_xpath('//div[@class="ivu-tabs-nav-wrap"]/div/div[3]').click()
driver.find_element_by_xpath('//div[@class="ivu-tabs-nav-wrap"]/div/div[3]/div/i').click()
dbname=driver.find_element_by_xpath('//div[@class="tree_3hqfs"]/main[%i]/section[1]//span' % i).text
print('数据源标签名称:',dbname)
time.sleep(2)
driver.current_window_handle
# 点击数据源,打开编辑框
driver.find_element_by_xpath('//div[@class="tree_3hqfs"]/main[%s]/section[1]' % i).click()
# 获取数据库类型
dbtype=driver.find_elements_by_xpath('//div[@class="ivu-split-vertical"]/div[1]/section/div/section[2]/span')
typels=[ d.text for d in dbtype]
print('数据库信息',typels)
# print(typels[-1].split(":")[-1].strip())
if typels[-1].split(":")[-1].strip()=='mysql':
sqllist=mysql_testsqllist
elif typels[-1].split(":")[-1].strip()=='oracle':
sqllist=oracle_testsqllist
elif typels[-1].split(":")[-1].strip()=='db2':
sqllist=db2_testsqllist
# 组装结果集文件名称及填充表头
result_filename=screenshot_path+dbname+'-'+typels[-1].split(":")[-1].strip()+'.csv'
print('保存结果集文件',result_filename)
writecsv([sqllist[0]],result_filename)
for i in range(1,len(sqllist)):
resultlist=[]
# 点击编辑框
driver.find_element_by_xpath('//div[@class="editor_2FiuW"]').click()
time.sleep(1)
# print('点击编辑框')
driver.find_element_by_xpath('//textarea[@autocorrect="false"]').send_keys(sqllist[i][2])
time.sleep(1)
try:
#由于执行按钮动态变化,所以需要设置2个,
# print('点击执行执行按钮')
driver.find_element_by_xpath('//div[@class="ivu-split-vertical"]/div[1]/section/div/section[1]/span/span/div[2]').click()
except Exception as e:
driver.find_element_by_xpath('//div[@class="ivu-split-vertical"]/div[1]/section/div/section[1]/div[1]').click()
time.sleep(1)
try:
# 不一定有二次确认的按钮
driver.find_element_by_xpath('//div[@role="tooltip" and @x-placement="bottom"]//button[2]').click()
time.sleep(2)
except Exception as e:
print('无二次确认按钮')
# pictures=driver.get_screenshot_as_file(screenshot_path+dbname+'-1.png')
#循环等待结果,
while True:
result=driver.find_element_by_xpath('//div[@class="bottom-tab_3KIIY"]/div/div[2]').text
if result:
result=result.replace("\n",' ').strip()
# print(result)
#判读关键字截图
tr='耗时' in result
if not tr:
pname=screenshot_path+dbname+'-'+typels[-1].split(":")[-1].strip()+'-'+str(int(sqllist[i][0]))+'.png'
print('异常执行结果截图:',pname)
pictures=driver.get_screenshot_as_file(pname)
break
# 填充结果集数据
resultlist.append([str(int(sqllist[i][0])),sqllist[i][1],sqllist[i][2],sqllist[i][3],result])
print(resultlist)
writecsv(resultlist,result_filename)
# 清理输入框中的sql信息
driver.find_element_by_xpath('//div[@class="editor_2FiuW"]').click()
driver.find_elements_by_xpath('//div[@class="ivu-split-vertical"]/div[1]/section/div/section[1]/div')[-2].click()
# 刷新获取焦点,清空结果集数据,将输入框刷新成统一状态便于操作
driver.refresh()
time.sleep(2)
#点击数据库的编辑框标签
driver.find_element_by_xpath('//div[@class="ivu-tabs-nav-wrap"]/div/div[3]').click()
break
print('工作台的所有sql测试完毕,关闭浏览器!')
driver.quit()
def readexl(filename):
print('加载测试文件',filename)
data=xlrd.open_workbook(filename)
table=data.sheets()[0]
# print(table.name,table.nrows,table.ncols)
x=table.nrows
y=table.ncols
print('文件行列,rows:',x,',cols:',y)
# print('标题:',table.cell(0,0).value)
resultlist=[]
for i in range(0,x):
ls=[]
for j in range(0,y):
type=table.cell(i,j).ctype
cell=table.cell_value(i,j)
# print(cell,end=" ")
ls.append(cell)
resultlist.extend([ls])
return resultlist
def readcsv_data(database_file):
#读取文件csv格式
# print('读取文件csv格式,加入数据筛选',database_file)
# filepath,tempfilename=os.path.split(database_file)
# filename,extension=os.path.splitext(tempfilename)
# filename,d=filename.split("-")
database_list=[]
#读取文件,获取id和系统名称字典
# print('读取文件',database_file,'\n')
with open(database_file,encoding='utf-8') as csvfile:
csv_reader = csv.reader(csvfile) # 使用csv.reader读取csvfile中的文件
birth_header = next(csv_reader) # 读取第一行每一列的标题
for row in csv_reader: # 将csv 文件中的数据保存到birth_data中
database_list.append(row)
print('读取文件',database_file,'获取数据文件行数:',len(database_list),'\n')
return database_list
def writecsv(lists,file):
#写入到csv文件中
with open(file,'a+', newline='') as csvwrite:
csv_write=csv.writer(csvwrite)
for ls in lists:
csv_write.writerow(ls)
def main():
# 截图保存位置
screenshot_path='D:\\SQLEXECUTE\\'
#获取各种数据库测试样例
mysql_testfile='D:\\SQLEXECUTE\\mysql测试样例.xlsx'
oracle_testfile='D:\\SQLEXECUTE\\oracle测试样例.xlsx'
db2_testfile='D:\\SQLEXECUTE\\db2测试样例.xlsx'
mysql_testsqllist=readexl(mysql_testfile)
oracle_testsqllist=readexl(oracle_testfile)
db2_testsqllist=readexl(db2_testfile)
check_executesql(screenshot_path,mysql_testsqllist,oracle_testsqllist,db2_testsqllist)
if __name__=='__main__':
main()