一、DDT数据驱动
1、DDT安装
windows、mac os系统,在CMD或者终端内输入:pip install ddt
2、DDT使用实例
import ddt
import unittest
@ddt.ddt
class TestDDT(unittest.TestCase):
def setUp(self):
pass
def tearDown(self):
pass
@ddt.data(1,2,3)
def test_01(self, a):
self.assertEqual(a,2)
运行结果如图:
3、DDT中data所可以使用的数据类型
单参数可以传int, str
@ddt.data('1','2','3')
def test_01(self, a):
self.assertEqual(a,2)
运行结果如图:
多参数可以传tuple, list, dict
@ddt.data([1,2], [2, 3])
@ddt.unpack
def test_01(self, a, b):
self.assertEqual(a,b)
@ddt.data({
'a':'1', 'b':'2'}, {
'a':'1', 'b':'2'}, {
'a':'1', 'b':'2'})
@ddt.unpack
def test_02(self, a, b):
self.assertEqual(b, a)
运行结果如图:
我们通过观察上面单参数和多参数,可以总结出一些特点和步骤:
步骤:
第一步:需要使用ddt的文件,先要导入ddt包,import ddt
第二步,在测试类上面,使用ddt装饰器,
第三步,在需要大量数据进行验证的测试方法上面使用@ddt.data()
注意:ddt.data()这个方法是紧挨着要使用数据的测试用例的。
特点:
(1)DDT传递数据类型,与测试用例中有几个参数密切相关
(2)测试用例特点,单参数、列表、元组用例类型类似,字典参数需要单独记录,如:
单参数:方法名_编号_参数1
多参数:方法名_编号_参数1_参数2_… …
字典类型参数: 方法名_编号
(3)unpack使用时机:当参数为多个的时候,需要使用@ddt.unpack, 可以理解为将数据包拆分
4、如何批量传递数据,并自动生成希望的变量格式
以excel批量传递测试数据为例:
(1)读取excel方法
# 引入一个新包,pip install pandas
import pandas as pd
class readExcelMethod():
"""
:fileName: 文件路径
:sheetName: sheet页的名称
"""
def __init__(self, fileName: str, sheetName='Sheet1'):
self.fileName = fileName # 文件路径
self.sheetName = sheetName # excel sheet页的名称
super(readExcelMethod, self).__init__()
def readExcel(cls):
df = pd.read_excel(cls.fileName, sheet_name=cls.sheetName)
df = df.T
testData = []
for i in range(len(df)):
testData.append(list(df[i]))
return testData
excel表格内容如图:
代码运行结果如图:
(2)如何将数据放入ddt.data()中,非常简单,代码如图:
data = readExcelMethod(fileName='').readExcel()
@ddt.data(*data)
仅需要在读取出的excel数据前增加一个【*】,便可以了。
二、unittest用例关联
为什么单独讲一下unittest的用例关联,是因为unittest没有现成的用例关联模块可以进行调用,另外,用例与用例之间往往存在较强关联性,举例:登录与退出的用例,退出用例的前提便是需要先要登录成功才会验证退出,结果登录已经失败了,其实很多情况便没有必要在去执行退出的操作了。
因此需要单独设计用例依赖的方法
其实用例设计依赖的核心思想,在于将依赖用例的执行状态存起来
因此这个存,便非常有讲究了
1、存在哪里?怎么存?
(1)借助辅助工具,如数据库,excel,redis等媒介进行存储
(2)存在本地缓存,python 有现成的缓存方法,在functools包下,如:lru_cache, 引入方法:from functools import lru_cache
(3)存在迭代器中,如List, dict中
知道了往哪里存, 怎么存了,但是存什么那?
2、存什么?怎么处理?
精细存:存具体用例失败的原因,比如:异常原因,或者失败的原因,根据具体异常,去存储对应的信息
粗略存:捕捉失败原因,正确存True,错误存False, 根据异常存储True or False
3、如何管理用例
首先跳过测试的方法需要用到unittest.TestCase().SkipTest(),该方法为unittest框架中,内部跳过测试用例的方法
(1)第一种:如果A与D是有关联的,这时候,执行A,A通过与否都去执行D用例,不需要等到D用例执行,跳过B,C用例,直接执行D用例
(2)第二种:如果A与D是有关联的,这时候,执行A用例,只需要将A用例的测试结果存在临时地方,然后待D执行的时候,在去获取A的结果,来判断D是否执行
1)通过辅助工具
2)通过缓存
3)利用迭代器
4、本博主原创设计的2种用例关联的方法:
(1)利用迭代器的做法,效果可以自己体验
from functools import wraps
import unittest
testCaseName = {
}
class decRelation:
"""
:name:被依赖的用例名称
:depend:依赖的用例名称
=======example=======
@decRelation(name='test_01')
def test_01(self):
self.assertEqual(2, 2)
@decRelation(depend='test_01')
def test_02(self):
self.assertEqual(1, 2)
"""
def __init__(self, name=None, depend=None):
self.depend = depend
self.name = name
super(decRelation, self).__init__()
def __call__(self, func):
@wraps(func)
def decoration(*args, **kwargs):
try:
if self.name:
if self.depend and testCaseName[self.depend] is True:
func(*args, **kwargs)
testCaseName[self.name] = True
elif self.depend is None:
func(*args, **kwargs)
testCaseName[self.name] = True
if self.depend and testCaseName[self.depend] is not True:
unittest.TestCase().skipTest(reason="%s 测试用例执行失败,相关依赖用例跳过!!!" % (self.depend))
testCaseName[func.__name__] = 'Skip'
else:
result = func(*args, **kwargs)
testCaseName[func.__name__] = True
return result
except Exception as e:
if self.name and self.name not in testCaseName.keys():
testCaseName[self.name] = False
if self.depend and self.depend not in testCaseName.keys():
testCaseName[self.depend] = False
raise e
return decoration
(2)利用excel做中间器的方式,适合excel存放大批量测试用例的方式
读取excel与保存excel方法封装
class dealExcelMethod():
"""
:fileName: 文件路径
:sheetName: sheet页的名称
"""
def __init__(self, fileName:str, sheetName='Sheet1'):
self.fileName = fileName # 文件路径
self.sheetName = sheetName # excel sheet页的名称
super(dealExcelMethod, self).__init__()
# 读取数据
def readExcelDDt(cls):
df = pd.read_excel(cls.fileName, sheet_name=cls.sheetName, keep_default_na=False)
listNum = len(df)
df = df.T
testData = []
for i in range(listNum):
testData.append(list(df[i]))
return testData
# 写入数据
def saveExcel(cls, testMethod:str, statusCode:str, testCaseNum:int):
df = pd.read_excel(cls.fileName, sheet_name=cls.sheetName, keep_default_na=False)
df.loc[testCaseNum, 'testName'] = testMethod
df.loc[testCaseNum, 'result'] = statusCode
writer = pd.ExcelWriter(cls.fileName)
df.to_excel(excel_writer=writer, index=False)
writer.save()
return df
这里的字段,需要根据自己实际所需要的字段进行填写,我只是这个作为例子,进行演示一下excel设计的方法
实际测试用例使用部分代码
from inspect import stack
# 通过辅助工具做用例关联
# example: excel
from webUI.readExcel import dealExcelMethod
import unittest
def readExcel():
fileName = ''
data = dealExcelMethod(fileName=fileName, sheetName='Sheet1').readExcelDDt()
return data
def saveExcel(testMethod,statusCode,testCaseNum):
fileName = ''
dealExcelMethod(fileName=fileName, sheetName='Sheet1').saveExcel(testMethod,statusCode,testCaseNum)
class TestExcel(unittest.TestCase):
def test_01(self):
try:
self.assertEqual(1,2)
saveExcel(testMethod=stack()[0][3], statusCode='True', testCaseNum=0)
except Exception as e:
saveExcel(testMethod=stack()[0][3], statusCode='False', testCaseNum=0)
raise e
def test_02(self):
try:
print(readExcel())
if readExcel()[1][1]:
self.assertEqual(2,2)
else:
self.skipTest(reason='该条测试用例跳过')
except Exception as e:
raise e
excel的方法,仅作为抛转引玉,为大家提供一个思路。
其实第一种方法,那个方法在很多情况,可以解决当前所需要的用例关联问题,并且代码简洁清晰,若是大家需要做用例关联的话,建议用第一种方法。另外,希望大家觉得我的方法还可以,希望大家能给点个赞,加个关注,后续我有好的方法,我会继续分享的~
转载:https://blog.csdn.net/weixin_46198734/article/details/109805772