Python中怎么将一个类方法变为多个方法(python,编程语言)

时间:2024-05-08 11:00:24 作者 : 石家庄SEO 分类 : 编程语言
  • TAG :

1、ddt 如何实现参数化?

先回顾一下上篇文章中 ddt 库的写法:

importunittestfromddtimportddt,data,unpack@ddtclassMyTest(unittest.TestCase):@data((3,1),(-1,0),(1.2,1.0))@unpackdeftest(self,first,second):pass

ddt 可提供 4 个装饰器:1 个加在类上的 @ddt,还有 3 个加在类方法上的 @data、@unpack 和 @file_data(前文未提及)。

先看看加在类方法上的三个装饰器的作用:

#ddt版本(win):1.2.1defdata(*values):globalindex_lenindex_len=len(str(len(values)))returnidata(values)defidata(iterable):defwrapper(func):setattr(func,DATA_ATTR,iterable)returnfuncreturnwrapperdefunpack(func):setattr(func,UNPACK_ATTR,True)returnfuncdeffile_data(value):defwrapper(func):setattr(func,FILE_ATTR,value)returnfuncreturnwrapper

它们的共同作用是在类方法上 setattr() 添加属性。至于这些属性在什么时候使用?下面看看加在类上的 @ddt 装饰器源码:

Python中怎么将一个类方法变为多个方法

Python中怎么将一个类方法变为多个方法

第一层 for 循环遍历了所有的类方法,然后是 if/elif 两条分支,分别对应 DATA_ATTR/FILE_ATTR,即对应参数的两种来源:数据(@data)和文件(@file_data)。

elif 分支有解析文件的逻辑,之后跟处理数据相似,所以我们把它略过,主要看前面的 if 分支。这部分的逻辑很清晰,主要完成的任务如下:

  • 遍历类方法的参数键值对

  • 根据原方法及参数对,创建新的方法名

  • 获取原方法的文档字符串

  • 对元组和列表类型的参数作解包

  • 在测试类上添加新的测试方法,并绑定参数与文档字符串

Python中怎么将一个类方法变为多个方法

分析源码,可以看出,@data、@unpack 和 @file_data 这三个装饰器主要是设置属性并传参,而 @ddt 装饰器才是核心的处理逻辑。

这种将装饰器分散(分别加在类与类方法上),再组合使用的方案,很不优雅。为什么就不能统一起来使用呢?后面我们会分析它的难言之隐,先按下不表,看看其它的实现方案是怎样的?

2、parameterized 如何实现参数化?

先回顾一下上篇文章中 parameterized 库的写法:

importunittestfromparameterizedimportparameterizedclassMyTest(unittest.TestCase):@parameterized.expand([(3,1),(-1,0),(1.5,1.0)])deftest_values(self,first,second):self.assertTrue(first>second)

它提供了一个装饰器类 @parameterized,源码如下(版本 0.7.1),主要做了一些初始的校验和参数解析,并非我们关注的重点,略过。

Python中怎么将一个类方法变为多个方法

我们主要关注这个装饰器类的 expand() 方法,它的文档注释中写到:

A"bruteforce"methodofparameterizingtestcases.Createsnewtestcasesandinjectsthemintothenamespacethatthewrappedfunctionisbeingdefinedin.Usefulforparameterizingtestsinsubclassesof'UnitTest',whereNosetestgeneratorsdon'twork.

关键的两个动作是:“creates new test cases(创建新的测试单元)”和“inject them into the namespace…(注入到原方法的命名空间)”。

关于第一点,它跟 ddt 是相似的,只是一些命名风格上的差异,以及参数的解析及绑定不同,不值得太关注。

Python中怎么将一个类方法变为多个方法

最不同的则是,怎么令新的测试方法生效?

parameterized 使用的是一种“注入”的方式:

Python中怎么将一个类方法变为多个方法

inspect 是个功能强大的标准库,在此用于获取程序调用栈的信息。前三句代码的目的是取出 f_locals,它的含义是“local namespace seen by this frame”,此处 f_locals 指的就是类的局部命名空间。

说到局部命名空间,你可能会想到 locals(),但是,我们之前有文章提到过“locals() 与 globals() 的读写问题”,locals() 是可读不可写的,所以这段代码才用了 f_locals。

3、pytest 如何实现参数化?

按惯例先看看上篇文章中的写法:

importpytest@pytest.mark.parametrize("first,second",[(3,1),(-1,0),(1.5,1.0)])deftest_values(first,second):assert(first>second)

首先看到“mark”,pytest 里内置了一些标签,例如 parametrize、timeout、skipif、xfail、tryfirst、trylast 等,还支持用户自定义的标签,可以设置执行条件、分组筛选执行,以及修改原测试行为等等。

用法也是非常简单的,然而,其源码可复杂多了。我们这里只关注 parametrize,先看看核心的一段代码:

Python中怎么将一个类方法变为多个方法

根据传入的参数对,它复制了原测试方法的调用信息,存入待调用的列表里。跟前面分析的两个库不同,它并没有在此创建新的测试方法,而是复用了已有的方法。在 parametrize() 所属的 Metafunc 类往上查找,可以追踪到 _calls 列表的使用位置:

Python中怎么将一个类方法变为多个方法

最终是在 Function 类中执行:

Python中怎么将一个类方法变为多个方法

好玩的是,在这里我们可以看到几行神注释……

Python中怎么将一个类方法变为多个方法

 </div> <div class="zixun-tj-product adv-bottom"></div> </div> </div> <div class="prve-next-news">
本文:Python中怎么将一个类方法变为多个方法的详细内容,希望对您有所帮助,信息来源于网络。
上一篇:怎么炫酷的使用Python下一篇:

6 人围观 / 0 条评论 ↓快速评论↓

(必须)

(必须,保密)

阿狸1 阿狸2 阿狸3 阿狸4 阿狸5 阿狸6 阿狸7 阿狸8 阿狸9 阿狸10 阿狸11 阿狸12 阿狸13 阿狸14 阿狸15 阿狸16 阿狸17 阿狸18