前言:本文100%原创,重点介绍实现方式,不过多赘述代码层。
实现以windows程序小工具中,集成UI自动化。对于项目团队有时能起到四两拨千斤的作用。
Windows程序由python3+tkinter实现,本文不多做赘述。
UI自动化由python3+selenium实现,本文不多做赘述。
运行目标环境:windows系统+谷歌或火狐浏览器
一. 框架设计
本框架本人花了3天时间各种调试,最终实现较为可行且合适的框架。
本框架本分为3个文件:
为了更让看文章的朋友思想不分散,我集合到一个文件下。(注:如果业务场景多,还是多个文件较好)
其中分为三个部分:
1.tkinter的Windows程序部分:
2.UI自动化部分:
注:driver需要声明全局变量且只有一个,本人是将此,放到类的全局变量里(__init__)
3.数据元素分离和封装自动化方法集合:
上面部分可以看下,其中可能可以学到不少东西。
二. 实践:业务层面写代码
如下一个业务:新建大转盘活动
新建一个活动,手动需要5分钟,在测试过程中,场景在20种以上(各种活动类型,各种场景验证等),那么测试过程建活动测试数据,至少需要100到500分钟时间。这样导致测试效率大大降低,如用自动化可节省时间,提升效率。UI自动化做在Windows程序里,其他项目同事也可以使用。
直接上效果:
https://v.youku.com/v_show/id_XNDYzMjMzMzczMg==.html
代码:(涉及到敏感信息删减了一些)
import os
import time
from selenium.webdriver.common.action_chainsimport ActionChains
from selenium.webdriver.supportimport expected_conditionsas EC
from selenium.webdriver.support.waitimport WebDriverWait
import tkinteras tk
from selenium.webdriver.common.byimport By
class LoginPageLoc:
"""登录"""
username= (By.ID, "username")
password= (By.ID, "password")
sign_in= (By.XPATH, "//button[@type='button']")
zyl_lo= (By.XPATH, "//img[@alt='自由里']")
zyl_logo= (By.XPATH, "//*[@src='/images/c11919cdcdfc3850351c21a22648d410.png']")
rzl_lo= (By.XPATH, "//img[@alt='日子里']")
rzl_logo= (By.XPATH, "//*[@src='/images/7894456ec5ff3d7229bc2f9224e78334.png.png']")
class CRMPageLoc:
"""CRM页面"""
redbuild_button= (By.XPATH, "//button[@class='ant-btn ant-btn-primary']")
redbuild_title= (By.ID, "title")
redbuild_star= (By.XPATH, "//*[@placeholder='开始日期']")
redbuild_stop= (By.XPATH, "//*[@placeholder='结束日期']")
from seleniumimport webdriver
from timeimport sleep
class new():
def __init__(self):
DRIVER= os.getcwd()+ '\chromedriver.exe'
self.driver= webdriver.Chrome(DRIVER)
def get(self, url, maximize_window=False, time_sync=30):
self.driver.get(url)
if maximize_window:
self.driver.maximize_window()
self.driver.implicitly_wait(time_sync)
def find_element(self, *loc):
try:
WebDriverWait(self.driver, 4).until(EC.visibility_of_element_located(loc))# 等待元素在页面可见
return self.driver.find_element(*loc)
except AttributeError:
print(u"%s 页面中未能找到 %s 元素" % (self, loc))
def click(self, *loc):
sleep(0.2)
self.find_element(*loc).click()
def send_keys(self, value, *loc):
sleep(0.3)
element= self.find_element(*loc)
element.click()
element.clear()
element.send_keys(value)
def create(self):
self.get("http:")
sleep(1)
nowTime= time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
self.send_keys("转盘%s"%time.strftime("%m%d %H:%M:%S", time.localtime()), *CRMPageLoc.redbuild_title)
ele= self.driver.find_element_by_xpath("//div[@class='probability']")
ActionChains(self.driver).move_to_element(ele).perform()
self.driver.find_elements_by_xpath("//input[@placeholder='请输入']")[1].send_keys("10")
self.click(*CRMPageLoc.redbuild_star)
sleep(0.3)
self.driver.find_elements_by_xpath("//*[@class='ant-calendar-date']")[4].click()
self.driver.find_elements_by_xpath("//*[@class='ant-calendar-date']")[30].click()
sleep(0.3)
self.driver.find_elements_by_xpath("//*[@placeholder='开始日期']")[0].send_keys(nowTime)
self.driver.find_elements_by_xpath("//*[@placeholder='结束日期']")[0].send_keys("2020-12-10 16:20:58")
self.send_keys("100", *CRMPageLoc.redbuild_limitnum)
def start(self):
win= tk.Tk()
win.title("大转盘-新建")
win.geometry("220x120")
tk.Label(win, text="优惠卷(份数)",fg="blue").grid(row=0, column=0)
self.juan= tk.StringVar()
self.juan_data_Text= tk.Entry(win, textvariable=self.juan,width=10)
self.juan_data_Text.grid(row=0, column=1, rowspan=1, columnspan=1, sticky='W')
self.juan.set(2)
self.juan_num= int(self.juan.get())
tk.Label(win, text="积分(份数)",fg="blue").grid(row=1, column=0)
self.jifen= tk.StringVar()
self.jifen_data_Text= tk.Entry(win, textvariable=self.jifen,width=10)
self.jifen_data_Text.grid(row=1, column=1, rowspan=1, columnspan=1, sticky='W')
self.jifen.set(7)
self.jifen_num= int(self.jifen.get())
tk.Label(win, text="---------------",fg="gray").grid(row=3, column=1)
tk.Button(win, text="开始新建!",bg="orange",command=self.xh).grid(column=0, row=4)
tk.Label(win, text="运行此工具,\n临时浏览器勿关!",fg="gray").grid(row=4, column=1)
win.mainloop()
def xh(self):
self.create()
i=0
while i<int(self.juan_data_Text.get()):
self.choose_yhj(2)
i+=1
j= 0
while j<int(self.jifen_data_Text.get()):
self.choose_jf()
j+=1
def choose_jf(self):
pass
def choose_yhj(self,n):
pass
if __name__== '__main__':
new().start()
驱动浏览器文件和此代码放在同一级:
三. 总结
此方法用过之后,效果及其显著,一方面可以节省很多的测试时间,另一方面,提升测试技术。
看到此文章的朋友,可以尝试在测试过程中应用,效率提升很大。
此方法实现依赖多种技术,解决某些特殊场景测试痛点,提升测试效率。