unittestreport 数据驱动 (DDT) 的实现源码解析

前言

在做自动化过程中,通过数据驱动主要是为了将用例数据和用例逻辑进行分离,提高代码的重用率以及方便用例后期的维护管理。很多小伙伴在使用 unittest 做自动化测试的时候,都是用的 ddt 这个模块来实现数据驱动的。也有部分小伙伴对 ddt 内部实现的源码比较感兴趣,前段时间小编在开发 unttestreport 的时候也写了一版数据驱动,使用的入口和 ddt 差不多,今天就给大家分析一下 unittestreport 中数据驱动(ddt),源码实现的过程!

一、快速使用

在给大家分析源码之前先给大家讲解一下 unittestreport 中的 ddt 如何使用!unittestreport.dataDriver 模块中实现了三个使用方法,支持使用列表(可迭代对象)、JSON 文件、YAML 文件来生成测试用例,这边给大家介绍一下使用方法:

二、源码分析

在上面的使用案例中我们使用了一个 ddt 的装饰器去装饰测试用例类,一个 list_data 的装饰器去装饰测试用例方法。

1、ddt

在上面的用例类前面我们用了一个@ddt 这行代码的作用到底是什么呢?

# @ddt这个是装饰器的语法,这行代码的作用等同于 TestClass = ddt(TestClass)

我们来看一下 ddt 里面的源码

def ddt(cls):
    for name, func in list(cls.__dict__.items()):
        if hasattr(func, "PARAMS"):
            for index, case_data in enumerate(getattr(func, "PARAMS")):
                # 生成用例名称,
                new_test_name = _create_test_name(index, name)
                # 生成用例描述
                if isinstance(case_data, dict) and case_data.get("title"):
                    test_desc = case_data.get("title")
                elif isinstance(case_data, dict) and case_data.get("desc"):
                    test_desc = case_data.get("desc")
                else:
                    test_desc = func.__doc__
                func2 = _update_func(new_test_name, case_data, test_desc, func)
                setattr(cls, new_test_name, func2)
            else:
                delattr(cls, name)
    return cls

从上面的源码我们可以看出来,把测试类当成参数传入 data 之后,在内部做了一系列操作之后将测试类返回了出来。这一系列操作其实就是根据测试用例数据,创建测试用例方法添加到测试类中,代码中重要步骤如下图描述所示。

1599469150826.png

对于上面遍历,判断方法是否拥有 PARAMS 属性,这个 PARAMA 属性是怎么来的呢?PARAMA 属性是@list_data(cases)的时候添加的,接下来我们来看一下 list_data 的源码

2、list_data

上面案例中@list_data(cases)这行代码的作用等同于 test_case = list_data(cases)(test_case),我们来看一下源码。

def list_data(datas):
    """
    :param datas: 测试数据
    :return:
    """

    def wrapper(func):
        setattr(func, "PARAMS", datas)
        return func

    return wrapper

通过源码我们可以发现执行@list_data(cases)的时候只做了一件事情,就是给测试用例方法添加了一个 PARAMS 属性。

1599469823480.png

通过上面的源码分析,我们来简单的讲一下,关于 ddt 实现的具体流程。

3、其他的内部实现方法

在 ddt 这个函数中我们调用了 _create_test_name 方法和 _update_func 这两个内部方法,那么这两个内部方法中分别做了什么事情呢?接下来分别来看一下

4、实现流程的分析

关于数据驱动实现的源码就给大家介绍到这里了,另附 unittestreport 模块详细的使用文档,里面有关于更多的 uniitestreport 扩展使用功能哦。又兴趣的小伙伴可以去看一下: unittestreport 详细功能使用文档(V1.1.1)


  1. 关于什么是装饰器大家可以扩展学习,这边不做过多的讲解

回帖
请输入回帖内容 ...