在Python自动化测试中,ddt
(Data-Driven Tests)是一个流行的库,允许开发人员通过装饰器轻松创建数据驱动的测试用例。@ddt
和 @data
装饰器是这个库中常用的工具。
ddt库的概念
ddt
库利用装饰器扩展了Python的unittest测试框架,使得可以在单个测试方法上应用多组参数进行测试。它避免了编写重复的测试代码,并增强了测试用例的可读性和维护性。
@ddt
装饰器
@ddt
装饰器应用于测试类。它是类装饰器,负责动态地向测试类添加测试方法。当你在测试类上应用 @ddt
装饰器时,它会寻找类中用 @data
或其他ddt提供的装饰器标记的测试方法,并为每一组数据生成一个独立的测试方法实例。
@data
装饰器
@data
装饰器用于测试方法。它允许你为一个测试方法提供多组测试数据。这些数据被用来生成随着数据变化而重复执行的测试方法。这意味着你可以仅编写一个测试方法,并通过不同的数据集多次运行这个方法。
源码解析
@ddt
和 @data
实际上是函数装饰器。在Python中,装饰器主要是依靠闭包来实现对函数或类的包装。
以下是一个简化的 @data
装饰器源码的逻辑示例:
def data(*values):
def test_decorator(func):
if not hasattr(func, "__test_params__"):
func.__test_params__ = []
func.__test_params__.extend(values)
return func
return test_decorator
@data(1, 2, 3)
def test_method(self, value):
# ...测试逻辑
在这个简化版本中,你可以看到 @data
实际上是一个包装函数的包装器。它添加一个特殊的属性 __test_params__
到被装饰的函数上,其中包含了所有的测试参数。
接着,@ddt
装饰器的源码逻辑大概如下:
def ddt(cls):
for name, func in list(cls.__dict__.items()):
if hasattr(func, "__test_params__"):
for idx, params in enumerate(func.__test_params__):
test_name = f"{name}_{idx}"
test_func = ddt_helper(func, **params)
setattr(cls, test_name, test_func)
return cls
def ddt_helper(func, **params):
def test(self):
return func(self, **params)
test.__name__ = func.__name__
return test
这里的 ddt
装饰器查找所有带有 __test_params__
属性的测试方法,并且对每一组参数创建一个新的测试方法。
综上所述,使用 @ddt
和 @data
可以大大简化写作测试用例的过程,让我们能专注于测试逻辑的本身,而无需编写重复的测试方法。通过讲解了 @ddt
和 @data
源码的关键部分,我们可以更深入地理解其背后的工作原理。