unittest 核心是通过文件夹等模式把一个个测试对象给添加到测试套件里面,然后进行驱动。
unittest 框架性提供了一些便利,会导致平时写代码根据函数和函数调用顺序,触发的对象在其他测试对象 (成员函数内) 是不可识别的。
context 是上下文,这里先不考虑使用 db 例如 Redis 做缓存和全局对象这种方式,先看看普通类的实现。
# 加了类名Test,除非用命令行执行,ide里面会判断是一个测试类对象
class Demo():
def test_login(self):
self.user = "maomao"
def test_start_task(self):
print(f"{self.user}开始任务")
if __name__ == '__main__':
t = Demo()
t.test_login()
t.test_start_task()
可见,只要先调用了 test_login(),等于激活了 self.user,下面的 test_start_task 里面的 self.user 就等于 maomao。
把上面的 Demo 改成 TestDemo,支持 unittest 来测试下。
import unittest
class Demo(unittest.TestCase):
def test_login(self):
self.user = "maomao"
def test_start_task(self):
print(f"{self.user}开始任务")
if __name__ == '__main__':
unittest.main()
这个会输出 AttributeError: 'Demo' object has no attribute 'user'
熟悉 unittest 的都知道他有每个模块,每个类,每个方法 (最小测试对象) 的前后置函数,每个方法之间的对象是隔离的。
只要是语言在计算机原理没有变化的情况下,白话来说,往上访问对于当前来说都是共享内存的区域,在方法层面往上访问就是类,共享区域就是类变量,类变量是晚于 classmethod 需要注意。
类层面往上访问就是模块,模块共享区域就是模块的init.py。
unittest 的函数对象访问顺序是遵循 ascii 码规则,函数对象名称前面 test_a_xxx,test_b_xxx...依次往下就行。
如果想让 test_start_task 可以识别到 user,就需要把 user 添加到类变量区域。
class Demo(unittest.TestCase):
temp = []
def test_a_login(self):
self.user = "maomao"
self.temp.append(self.user)
def test_b_start_task(self):
# 不推荐使用print(f"{self.temp[0]}开始任务1")
self.user = self.temp.pop()
print(f"{self.user}开始任务1")
print(self.temp) #长度为0
不推荐的原因是 [0] 毕竟是魔术,可读性低,是不是觉得 pop() 返回并且清除列表内部的,更像一锤子买卖。
pop 的源码描述,remove and return item at index (default last) 默认是删除最后一个并且返回
# 上面代码下添加这个
def test_c_replay_start_task(self):
print(f"{self.temp[0]}开始任务2")
结果会发现依然可以识别,由此可见 temp 在经过 test_login() 被添加后,temp 里面就有了 user。
下标 [0] 是不符合可读性的,那么 Python 的字典具备可读性,查询是 O(1) 的行为,是最合适的,这里完成修改下代码。
以后包含上下文的都可以用以下代码使用。
class Demo(unittest.TestCase):
# 如果上下文需要用到的
temp = {}
def test_a_login(self):
self.user = "maomao"
self.temp["user"] = self.user
def test_b_start_task(self):
print(f'{self.temp["user"]}开始任务1')
def test_c_replay_start_task(self):
print(f'{self.temp["user"]}开始任务2')
if __name__ == '__main__':
unittest.main()
PS:unittest 也是支持命令行的,-m 代表 import 导入,后面跟着 unittest 就是导入 ut。
py -3 -m unittest xxx.py