这篇文章主要介绍了大蟒自动化测试之滴滴涕数据驱动的实现代码,本文给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
时隔已久,再次冒烟,自动化测试工作仍在继续,自动化测试中的数据驱动技术尤为重要,不然咋去实现数据分离呢,对吧,这里就简单介绍下与传统单元测试自动化测试框架匹配的滴滴涕数据驱动技术。
话不多说,先撸一波源码,其实整体代码并不多
# -*-编码:utf-8 -*-
#本文件是滴滴涕(https://github.com/txels/ddt)的一部分
#版权所有2012-2015卡莱斯巴罗贝斯和滴滴涕撰稿人
#有关确切的贡献历史,请参见饭桶修订日志。
#滴滴涕根据麻省理工学院许可证获得许可,包含在
# https://github.com/txels/ddt/blob/master/LICENSE.md
进口检验
导入json
导入操作系统
进口关于
导入编解码器
从functools导入包装
尝试:
导入yaml
除了导入错误:# pragma:没有封面
_have_yaml=False
否则:
_have_yaml=True
__版本__='1.2.1 '
#这些属性不会与任何真正的大蟒属性冲突
#它们被添加到修饰的测试方法中,稍后进行处理
#由"滴滴涕"类装饰。
DATA_ATTR='%values' #存储测试运行时必须使用的数据
文件ATTR=' %文件路径' #存储JSON文件的路径
UNPACK_ATTR='%unpack' #记住我们必须解包值
index_len=5 #案例索引的默认最大长度
尝试:
trivial_types=(type(None),bool,int,float,basestring)
除了名称错误:
平凡类型=(类型(无),布尔,整型,浮点型,字符串)
定义是_平凡(值):
如果isinstance(值,平凡类型):
返回真实的
elif isinstance(值,(列表,元组)):
返回全部(地图(is _平凡,值))
返回错误的
定义解包(函数):
'''
添加解包特性的方法装饰器。
'''
setattr(func,UNPACK_ATTR,True)
返回功能
定义数据(*值):
'''
添加到测试方法中的方法装饰器。
应添加到“单元测试。测试案例"实例的方法中。
'''
全局索引_len
index_len=len(str(len(values)))
返回伊达(值)
定义数据(可重复):
'''
添加到测试方法中的方法装饰器。
应添加到“单元测试。测试案例"实例的方法中。
'''
定义包装器(函数):
setattr(func,DATA_ATTR,iterable)
返回功能
返回包装
定义文件_数据(值):
'''
添加到测试方法中的方法装饰器。
应添加到“单元测试。测试案例"实例的方法中。
"值"应该是相对于文件目录的路径
包含修饰的` `单元测试。测试用例'。文件
应该包含JSON编码的数据,可以是列表或
迪克特。
在列表的情况下,列表中的每个值对应一个值
测试用例,并且该值将被连接到测试方法
姓名。
在字典的情况下,关键字将被用作
测试用例,值将作为测试数据。
'''
定义包装器(函数):
setattr(函数,文件_ATTR,值)
返回功能
返回包装
定义测试名称(名称,值,索引=0):
'''
为测试用例生成一个新的名称。
它将采用原始的测试名称,并附加一个序号索引和一个
值的字符串表示形式,并将结果转换为有效的
大蟒标识符,方法是用`_ ` '替换无关字符。
如果处理非平凡值,我们避免使用字符串(值).
问题可能是不同运行的不同名称,例如
字典键的不同顺序(参见PYTHONHASHSEED)或处理
用模拟物体。
琐碎的标量值按原样传递。
"琐碎"值是一个简单的标量,或者是一个元组或列表
只有微不足道的价值。
'''
#在索引前添加零以保持顺序
index="{ 0:0 { 1 } } " .格式(索引1,index_len)
如果不是是_平凡(值):
返回"{0}_{1}"。格式(名称、索引)
尝试:
值=字符串(值)
除了UnicodeEncodeError错误:
python2的回退
value=value.encode('ascii ',' backslashreplace ')
test _ name="{ 0 } _ { 1 } _ { 2 } " .格式(名称、索引、值)
返回re.sub(r'\W|^(?=\d)',' _ ',测试名称)
def feed_data(func,new_name,test_data_docstring,*args,**kwargs):
'''
这个内部方法装饰器向测试提供测试数据项。
'''
@wraps(func)
定义包装(自身):
return func(self,*args,**kwargs)
包装纸。__名称__=新名称
包装纸__wrapped__=func
#设置文档字符串(如果存在)
如果测试数据文档字符串不为无:
包装纸__doc__=test_data_docstring
否则:
#尝试在文档字符串上调用格式
if func .__doc__:
尝试:
包装纸__doc__=func .__doc__ .格式(*args,**kwargs)
except (IndexError,KeyError):
#可能用户添加了一些格式化字符串
#无意中在文档字符串中。不要引发异常
#因为用户可能不知道
#格式化功能。
及格
返回包装
def add_test(cls,test_name,test_docstring,func,*args,**kwargs):
'''
向该类添加一个测试用例。
该测试将基于一个现有的函数,但会给它一个新的
姓名。
'''
setattr(cls,test_name,feed_data(func,test_name,test_docstring,
*args,**kwargs))
极好的进程_文件_数据(cls,name,func,file_attr):
'''
在"文件数据"装饰器中处理参数。
'''
cls _ path=OS。路径。ABS路径(检查。获取源文件(cls))
数据文件路径=OS。路径。加入(OS。路径。目录名(cls _ path),文件属性)
def create _ error _ func(message):# pylint:disable-msg=w 0613
定义函数(*args):
提高值错误(消息% file_attr)
返回功能
#如果文件不存在,请提供一个错误函数
如果不是os.path.exists(数据文件路径):
测试名称=mk测试名称(名称,'错误)
test_docstring=' ' '错误!'''
add_test(cls测试名称,测试文档字符串,
create_error_func('%s不存在),无)
返回
_ is _ YAML文件=数据文件路径。以(('结尾.yml ',' .yaml '))
#没有YAML但想用YAML文件。
if _is_yaml_file而not _have_yaml:
测试名称=mk测试名称(名称,'错误)
test_docstring=' ' '错误!'''
添加测试(
cls,
测试名称,
test_docstring,
create_error_func('%s是YAML文件,请安装py YAML’),
没有人
)
返回
with codecs.open(data_file_path,' r ',' utf-8') as f:
#从YAML或JSON加载数据
if _is_yaml_file:
data=yaml.safe_load(f)
否则:
data=json.load(f)
_添加_测试_来自_数据(类别,名称,函数,数据)
def _add_tests_from_data(cls,name,func,data):
'''
将从数据文件加载的数据中的测试添加到类中
'''
对于我,elem在列举(数据):
if isinstance(data,dict):
键,值=元素,数据[元素]
test_name=mk_test_name(name,key,I)
elif isinstance(数据,列表):
值=元素
测试名称=mk测试名称(名称,值,我)
if isinstance(value,dict):
add_test(cls测试名称,测试名称,函数,* *值)
否则:
add_test(cls测试名称,测试名称,函数,值)
def _is_primitive(obj):
''确定目标文件是否为"基本体"。它有点粗糙,但很有效。
'''
return not hasattr(obj,' __dict__ ')
def _ get _ test _ data _ docstring(func,value):
""基于以下解析策略返回文档字符串:
1.传递的值不是"基元"并且具有docstring,请使用它。
2.在所有其他情况下,返回没有,即使用测试名称。
'''
如果不是_是_原语(值)和值. doc__:
返回值. doc__
否则:
不返回
定义滴滴涕(cls):
'''
` `单元测试。测试用例“”的子类的类装饰器。
将这个装饰器应用到测试用例类,然后
用` `@数据` '修饰测试方法。
对于每个用` `@数据` '修饰的方法,这将有效地创建为
许多方法作为数据项作为参数传递给`` @数据`` .
测试方法的名称遵循这种模式
"原始测试名称_ {序号} _ {数据}"。"序数"是的位置
数据参数,从一开始。
对于数据,我们使用转换成
有效的大蟒标识符。如果` `数据__name__ ` `的存在,我们改用它。
对于每个用`` @file_data('test_data.json ')`修饰的方法
装饰者将尝试加载位于相对位置的测试_数据. json文件
添加到包含被修饰方法的大蟒文件中。会的,
对于每个“测试名称”,在值列表中创建尽可能多的方法
从"数据"键。
'''
对于名称,func in list(cls .__词典_ _。items()):
if hasattr(func,DATA_ATTR):
对于I,v in enumerate(getattr(func,DATA_ATTR)):
test_name=mk_test_name(name,getattr(v,' __name__ ',v),I)
test _ data _ docstring=_ get _ test _ data _ docstring(func,v)
if hasattr(func,UNPACK_ATTR):
如果是isinstance(v,tuple)或isinstance(v,list):
添加测试(
cls,
测试名称,
测试数据文档字符串,
func,
*五
)
否则:
#打开字典
添加测试(
cls,
测试名称,
测试数据文档字符串,
func,
* *五
)
否则:
add_test(cls,test_name,test_data_docstring,func,v)
delattr(cls,name)
elif hasattr(func,FILE_ATTR):
file_attr=getattr(func,file_attr)
进程文件数据(类别,名称,函数,文件属性)
delattr(cls,name)
返回cls
ddt源码
通过源码的说明,基本可以了解个大概了,其核心用法就是利用装饰器来实现功能的复用及扩展延续,以此来实现数据驱动,现在简单介绍下其主要函数的基本使用场景。
1.@ddt(cls),其服务于单元测试类装饰器,主要功能是判断该类中是否具有相应二氯二苯三氯乙烷装饰的方法,如有则利用自省机制,实现测试用例命名mk _测试名称,数据回填_add_tests_from_data并通过添加测试添加至单元测试的容器测试套件中去,然后执行得到测试结果,流程非常清晰。
定义滴滴涕(cls):
对于名称,func in list(cls .__词典_ _。items()):
if hasattr(func,DATA_ATTR):
对于I,v in enumerate(getattr(func,DATA_ATTR)):
test_name=mk_test_name(name,getattr(v,' __name__ ',v),I)
test _ data _ docstring=_ get _ test _ data _ docstring(func,v)
if hasattr(func,UNPACK_ATTR):
如果是isinstance(v,tuple)或isinstance(v,list):
添加测试(
cls,
测试名称,
测试数据文档字符串,
func,
*五
)
否则:
#打开字典
添加测试(
cls,
测试名称,
测试数据文档字符串,
func,
* *五
)
否则:
add_test(cls,test_name,test_data_docstring,func,v)
delattr(cls,name)
elif hasattr(func,FILE_ATTR):
file_attr=getattr(func,file_attr)
进程文件数据(类别,名称,函数,文件属性)
delattr(cls,name)
返回cls
2.@file_data(路径),其主要是通过过程_文件_数据方法实现数据解析,这里通过_add_tests_from_data实现测试数据回填,通过源码可以得知目前文件只支持Yaml和JSON数据文件,想扩展其它文件比如可扩展标记语言等直接改源码就行
极好的进程_文件_数据(cls,name,func,file_attr):
'''
在"文件数据"装饰器中处理参数。
'''
cls _ path=OS。路径。ABS路径(检查。获取源文件(cls))
数据文件路径=OS。路径。加入(OS。路径。目录名(cls _ path),文件属性)
def create _ error _ func(message):# pylint:disable-msg=w 0613
定义函数(*args):
提高值错误(消息% file_attr)
返回功能
#如果文件不存在,请提供一个错误函数
如果不是os.path.exists(数据文件路径):
测试名称=mk测试名称(名称,'错误)
test_docstring=' ' '错误!'''
add_test(cls测试名称,测试文档字符串,
create_error_func('%s不存在),无)
返回
_ is _ YAML文件=数据文件路径。以(('结尾.yml ',' .yaml '))
#没有YAML但想用YAML文件。
if _is_yaml_file而not _have_yaml:
测试名称=mk测试名称(名称,'错误)
test_docstring=' ' '错误!'''
添加测试(
cls,
测试名称,
test_docstring,
create_error_func('%s是YAML文件,请安装py YAML’),
没有人
)
返回
with codecs.open(data_file_path,' r ',' utf-8') as f:
#从YAML或JSON加载数据
if _is_yaml_file:
data=yaml.safe_load(f)
否则:
data=json.load(f)
_添加_测试_来自_数据(类别,名称,函数,数据)
3.@日期(*值),简单粗暴的直观实现数据驱动,直接将可迭代对象传参,进行数据传递,数据之间用逗号" , "隔离,代表一组数据,此时如果实现打开包装,则更加细化的实现数据驱动,切记每组数据对应相应的形参。
定义解包(函数):
'''
添加解包特性的方法装饰器。
'''
setattr(func,UNPACK_ATTR,True)
返回功能
定义数据(*值):
'''
添加到测试方法中的方法装饰器。
应添加到“单元测试。测试案例"实例的方法中。
'''
全局索引_len
index_len=len(str(len(values)))
返回伊达(值)
定义数据(可重复):
'''
添加到测试方法中的方法装饰器。
应添加到“单元测试。测试案例"实例的方法中。
'''
定义包装器(函数):
setattr(func,DATA_ATTR,iterable)
返回功能
返回包装
4.实例
# -*-编码:utf-8 -*-
__author__='暮辞'
导入时间,随机
从二氯二苯三氯乙烷导入滴滴涕,数据,文件数据,解包
导入单元测试
导入json
从HTMLTestRunner导入HTMLTestRunner
@ddt
课堂演示(单元测试。测试用例):
@file_data(' ./迁移/测试。JSON’)
def test_hello(self,a,**b):
'''
测试你好
'''
打印一份
打印b
#打印“你好”,a,类型(a)
如果是实例(a,列表):
self.assertTrue(True," 2 ")
否则:
self.assertTrue(True,' 3 ')
@data([1,2,3,4])
def test_world(self,*b):
'''
测试世界
'''
打印b
self.assertTrue(True)
@data({'test1':[1,2],' test2':[3,4]},{'test1':[1,2],' test2':[3,4]})
@解包
def test_unpack(self,**a):
'''
测试解除…的负担
'''
打印一份
self.assertTrue(True)
if __name__=='__main__ ':
套装=单元测试.测试套件()
测试=单元测试.TestLoader().loadTestsFromTestCase(演示)
suit.addTests(测试)
#suit.addTests(测试)
带开('。/migrations/Demo.html ',' w ')作为女:
result=HTMLTestRunner(stream=f,description=u'Demo测试报告,title=u'Demo测试报告)
结果。运行(套装)
测试结果:
至此关于二氯二苯三氯乙烷的数据驱动暂时告一段落了,后面还会介绍基于excel、sql等相关的数据驱动内容,并进行对比总结,拭目以待~
总结
以上所述是小编给大家介绍的大蟒自动化测试之滴滴涕数据驱动的实现代码,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。