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()