使用Selenium与Unittest搭建UI自动化测试用例四层架构
本人在学习搭建UI自动化架构时,发现网上讲解的搭建过程不是很详细。便写下该篇文章,便于记录及后续本人与读者使用。(附开源地址)
本人在学习搭建UI自动化架构时,发现网上讲解的搭建过程不是很详细。便写下该篇文章,便于记录及后续本人与读者使用。
开源地址
Gitee:Selenium+Unittest测试UI自动化框架
四层目录
Base(基本动作层)
Case(用例层)
Data(数据层)
Page(业务层)
Base基本动作层
该层用于存放UI基本操作步骤,例:点击、输入、按键
action.py(里面有我常用的基本动作含动作用法注释,欢迎大家评论区补充)
import time
from selenium import webdriver
from selenium.webdriver import ActionChains, Keys
from selenium.webdriver.common.by import By
class Bases:
# driver = webdriver.Chrome()
def __init__(self, driver):
self.driver = driver
# OpenChrome打开浏览器
def open(self, url):
self.driver.get(url)
self.driver.maximize_window()
self.wait(10)
# 打开新标签页
def open_new(self):
self.driver.switch_to.new_window('tab')
# 获取当前窗口页面的窗口句柄
def NewHandles(self):
time.sleep(3)
first_window = self.driver.current_window_handle[0]
new_window = self.driver.current_window_handle
print('旧页面:' + first_window + ';切换定位新页面:' + new_window)
time.sleep(2)
# Find Element寻找元素定位
def local(self, sid, value):
self.wait(10)
return self.driver.find_element(sid, value)
# Click Element点击元素定位
def click(self, sid, value):
self.local(sid, value).click()
print('点击元素:' + value)
# 双击元素定位
def double_click(self, sid, value):
ActionChains(self.driver).double_click(self.local(sid, value)).perform()
print('双击元素:' + value)
# Input Element输入元素定位
def input(self, sid, value, txt):
b = self.local(sid, value)
# 清除只读属性
self.driver.execute_script('arguments[0].removeAttribute(\"readonly\")', b)
b.clear()
b.send_keys(txt)
print('元素:' + value + ',输入:' + txt)
# edit web excel编辑表格
def edit(self, sid, value, txt):
self.local(sid, value)
time.sleep(1)
ActionChains(self.driver).send_keys(txt).perform()
print('元素:' + value + ',输入:' + txt)
# imitate keyboard键盘操作
def KeyBoard(self, sid, value, keys):
self.local(sid, value).send_keys(keys)
print('元素:' + value + ',键盘操作:' + keys)
# find txt in page寻找指定文本是否在页面
def wait_page(self, txt):
time.sleep(2)
if txt in self.driver.page_source:
print(txt + ',等待5秒后再操作')
time.sleep(5)
else:
print('检测不到:' + txt + ',自动化继续操作')
# choice to pull down下拉框内容下移与回车
def PullOption(self, sid, value):
self.KeyBoard(sid, value, Keys.DOWN)
self.KeyBoard(sid, value, Keys.ENTER)
# pull to input text下拉框输入内容下移与回车
def PullToInput(self, sid, value, txt):
self.input(sid, value, txt)
self.PullOption(sid, value)
# Wait Element等待元素
def wait(self, times):
return self.driver.implicitly_wait(times)
# 跳转上个页面
def LastPage(self):
self.driver.switch_to.window(self.driver.window_handles[0])
# QuitChrome关闭浏览器
def quit(self):
self.driver.quit()
Case用例层
该层存放自动化用例并用于执行
Testcase.py(setUpClass初始化类级别的资源和环境,tearDownClass测试方法执行完毕后自动执行一些清理操作,test01登录操作,test02用例执行)
注:每新增一个用例得在setUpClass定义 如cls.t03 = test031(cls.driver)
import unittest
from ddt import ddt, file_data
from selenium import webdriver
from Page.Login import Login
from Page.test01 import test011
@ddt
class ContractCase(unittest.TestCase):
@classmethod
def setUpClass(cls) -> None:
cls.driver = webdriver.Chrome()
cls.driver.maximize_window()
cls.lg = Login(cls.driver)
cls.sc = test011(cls.driver)
@classmethod
def tearDownClass(cls) -> None:
pass
def test01(self):
self.lg.login55()
@file_data("../Data/test01.yaml")
def test02(self, Number):
self.sc.test0111(Number)
Data数据层
该层用于存储业务层数据变量,方便后续维护与调整。如:数据不适用能更快速找到位置更改
注:一个用例配一个yaml
test01.yaml
-
Number: 0001
Page业务层
该层用于编写业务操作步骤,用于Testcase调用。
Login.py(登录单独写出公用方法,便于后续不同Testcase统一调用,增强代码的简洁性与实用性)
import time
from selenium.webdriver.common.by import By
from Base.action import Bases
class Login(Bases):
# 登录环境链接
Url55 = 'https://test.kritycat.com'
Url81 = 'https://uat.kritycat.com'
# 登录账号与密码
user = ''
password = ''
# 登录55环境
def login55(self):
# 打开环境链接
self.open(self.Url55)
# 登录操作引用
self.LoginKeyBoard()
time.sleep(5)
# 登录81环境
def login81(self):
# 打开环境链接
self.open(self.Url81)
# 登录操作引用
self.LoginKeyBoard()
time.sleep(5)
# 登录操作
def LoginKeyBoard(self):
# 账号
self.input(By.ID, 'user', self.user)
# 密码
self.input(By.ID, 'password', self.password)
# 点击登录
self.click(By.ID, 'login')
test01.py(用例01业务操作步骤)
from selenium.webdriver.common.by import By
from Base.action import Bases
class test011(Bases):
def test0111(self, Number):
# 业务步骤
self.click(By.ID, "Type")
self.input(By.XPATH, '//*[@id="Type"]/div/div/input', Number)
附分层意义的解答:
分层的目的用于代码可维护性,可行性,可持续性,简洁性。下面我列举几个例子,大家就会知道分层的意义。
例:四个层级合并在一个用例写,当登录环境地址切换 你需每个用例都调整,分层只需调整Login.py
四个层级合并在一个用例写,当变量数据全部需要调整时,你得找到每个步骤修改数据,分层只需调整test02.yaml
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)