前言:
设计执行格式,封装PO模型工厂,实现PO模型脱离代码,一套代码执行所有项目的UI自动化,让UI自动化框架脱离高成本、低效率时代,将用例的重用性贯彻到极致,让烦人的PO模型变得无所谓,让一个测试小白都能编写并实现自动化
知识储备前提:熟悉python语言理论与实际运用,熟悉selenium库与自动化测试环境配置。对PO模型很熟悉。
《Python+Selenium WebUI自动化框架 — 统一入口自动化》:https://blog.csdn.net/weixin_40331132/article/details/105923262
这一篇算是我所有文章最长的一篇了,也是最核心的了,掌握了,写一套自动化框架,执行所有项目UI自动化,不需要再动代码。
1、读取用例及设计用例格式
#[{“a”: [{“A”: 2}, {“A”: 2}, {“A”: 2}, {“A”: 2}, {“A”: 2}, {“A”: 2}, {“A”: 2}, {“A”: 2}, {“A”: 2}]},{“a”: [5, 3, 2]}, {“a”: [10, 4, 6]}]
用例一般使用excel通过一定逻辑写出来,然后通过代码读取后转换成一个格式化的数据集。
格式正解:
一整个excel文件存放在列表里
列表里有很多字典,每一个字典是一个sheet页,字典的key是sheet页标题,字典的value是sheet页里的内容
sheet页的内容又是一个列表,里面有着很多字典,每一个字典代表着一条用例
读取用例格式化的代码如下
def readallcase(self): 此方法遍历excel文件中的所有sheet页
def readcase(self, sh): 此方法遍历sheet页中所有的row,将其组合成一条条用例case
class ReadCase(object):
def __init__(self):
self.sw = openpyxl.load_workbook(file)
print(self.sw)
def openxlsx(self, file):
"""
打开文件
:param dir:
:return:
"""
# self.sw = openpyxl.load_workbook(file)
#[{"a": [{"A": 2}, {"A": 2}, {"A": 2}, {"A": 2}, {"A": 2}, {"A": 2}, {"A": 2}, {"A": 2}, {"A": 2}]},{"a": [5, 3, 2]}, {"a": [10, 4, 6]}]
def readallcase(self):
"""
取所有sheet页
:return:list,返回sheet页里的数据
"""
sheet_list = []
for sh in self.sw:
if 'common' != sh.title.split('_')[0] and 'common' != sh.title.split('-')[0] and sh.title[0] is not '#' :
isOK, result = self.readcase(sh)
if isOK:
sheet_list.append(result)
if sheet_list is None:
return False, '用例集是空的,请检查用例'
return True, sheet_list
def readcase(self, sh):
"""
组合sheet页的数据
:param sh:
:return: list,返回组合数据
"""
if sh is None:
print('sheet页为空')
datas = list(sh.rows)
if datas == []:
return False, '用例[' + sh.title + ']里面是空的'
title = [i.value for i in datas[0]]
rows = []
sh_dict = {}
for i in datas[1:]:
data = [v.value for v in i]
row = dict(zip(title, data))
try:
if str(row['id'])[0] is not '#':
row['sheet'] = sh.title
rows.append(row)
except KeyError:
raise e
rows.append(row)
sh_dict[sh.title] = rows
return True, sh_dict
2、 实现不需要代码的PO模型
重点来了,这里应该会很难,首先说一个概念,“公共用例”,这应该是自动化界大多数人知道的。
公共用例的定义:可以是几个公共控件的操作,也可以是个登录首页,也可以是个中间过度页面,凡是多次用到的用例都可以写到公共用例里去,方便调用。
用了这种“公共用例” 代替PO模型。最开始我是在华为的自动化框架里见识这个概念,很强大,所以用自己的代码实现了并模仿了这个。
首先,我们设计一种用例规则,
‘调用用例’ 四个字为可以调用执行其他sheet页用例的命令,然后设计能被调用sheet页标题为common_或common-开头 ,回顾上面的设计用例格式的代码 def readallcase(self):方法里
有一行代码
if 'common' != sh.title.split('_')[0] and 'common' != sh.title.split('-')[0] and sh.title[0] is not '#' :
对,这行代码是在读取所有可执行用例时规避掉公共用例,因为公共用例是要在所有可执行用例里调用的,公共用例不能自己单独运行,
实现代码如下:
我们在工厂类里面定义两个方法
#初始化执行用例 def init_execute_case(self): 里面的内容:
一、读取了excel里所有可执行用例
二、调用用初始化公共用例
#初始化公共用例 def init_common_case(self, cases): 里面的内容:
一、判断是否有‘调用用例’命令,有则取公共用例合并成可执行用例
二、递归取公共用例里是否有‘调用用例’命令,有则继续取公共合并成可执行用例
注意:公共用例不能调用自已,递归死循环
from common.getconf import Config
from common.getcase import ReadCase
from basefactory.browseroperator import BrowserOperator
from basefactory.webdriveroperator import WebdriverOperator
class Factory(object):
#初始化公共用例
def init_common_case(self, cases):
"""
:param kwargs:
:return:
"""
cases_len = len(cases)
index = 0
for case in cases:
if case['keyword'] == '调用用例':
xlsx = ReadCase()
try:
case_name = case['locator']
except KeyError:
return False, '调用用例没提供用例名,请检查用例'
#取公共用例
isOK, result = xlsx.get_common_case(case_name)
if isOK and type([]) == type(result):
#递归检查公共用例里是否存在调用用例
isOK, result_1 = self.init_common_case(result)
elif not isOK:
return isOK, result
list_rows = result[case_name]
cases[index: index+1] = list_rows #将公共用例插入到执行用例中去
index += 1
if cases_len == index:
return False, ''
return True, cases
#初始化执行用例
def init_execute_case(self):
print("----------初始化用例----------")
xlsx = ReadCase()
isOK, result = xlsx.readallcase()
if not isOK:
print(result)
print("----------结束执行----------")
exit()
all_cases = result
excu_cases = []
for cases_dict in all_cases:
for key, cases in cases_dict.items():
isOK, result = self.init_common_case(cases) #将取的执行用例,去初始化一下公共用例
if isOK:
cases_dict[key] = result
else:
cases_dict[key] = cases
excu_cases.append(cases_dict)
print("----------初始化用例完成----------")
return excu_cases
然后在写好两个工厂方法后,我们还少了一个方法,那就是读取用例里的类里没有读取公共用例的方法,所以这里补上
这个方法在class ReadCase(object):读取用例的类下面,请回顾 1、读取用例及设计用例格式
def get_common_case(self, case_name):
"""
得到公共用例
:param case_name:
:return:
"""
try:
sh = self.sw.get_sheet_by_name(case_name)
except KeyError:
return False, '未找到公共用例[' + case_name + '],请检查用例'
except DeprecationWarning:
pass
return self.readcase(sh)
到这里这个框架所有的中心思想都出来了,希望大家能看懂。暂时没看懂的,拿着我这三篇文章,将里面的代码组合在一起,也能整出这个框架来。让我们一起学吧,谢谢
哦,把执行代码也放出来,因为是基础,所以不讲解了,基于unittest + ddt,详细请看下面代码:
用例执行类
import unittest
from common.factory import Factory
from library.ddt import ddt, data
@ddt
class Test_caserun(unittest.TestCase):
fac = Factory()
excu_cases = fac.init_execute_case()
@data(*excu_cases)
def test_run(self, acases):
for key, cases in acases.items():
for case in cases:
isOK, result = self.fac.execute_keyword(keyword=case['keyword'],
type=case['type'],
locator=case['locator'],
index=case['index'],
input=case['input'],
check=case['check'],
time=case['time']
)
if isOK:
print(result)
else:
raise Exception(result)
执行入口类
import os
import unittest
from library.HTMLTestRunnerNew import HTMLTestRunner
from common.getfiledir import CASEDIR, REPORTDIR
class Test_run(object):
def __init__(self):
self.suit = unittest.TestSuite()
self.load = unittest.TestLoader()
self.suit.addTest(self.load.discover(CASEDIR))
self.runner = HTMLTestRunner(
stream=open(os.path.join(REPORTDIR, 'report.html'), 'wb'),
title='魂尾自动化工厂',
description='唯a饭木领',
tester='HUNWEI'
)
def excute(self):
self.runner.run(self.suit)
if __name__=="__main__":
test_run = Test_run()
test_run.excute()
整个框架目录也奉上,这是最近写着玩的,所以发送邮件,打印日志什么的扩展,可以在common目录下自行添加
getconf.py与getfiledir.py中的一个是读配置文件,一个是读本框架所有目录,
最后看执行结果:
替代PO模型:一切公用的执行用例都可以放到以common开头的sheet页里,其他非common用例可以使用 调用用例 方法,在locator输入用例名可调用。细节处理(common用例可以调用common用例,但不可以调用自己,程序会死)
excel用例逻辑:
打开baidu, 等待页面出现,然后调用用例:common_input, common_input的用例在第二张图,执行结果看第三图、四图
执行用例:
common公共用例:
执行页面:
执行步骤打印:
结语:等手头上有空闲时间,自己再完善此框架,持续更新
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/5460.html