目录
(一)unittest上手
(二)unittest进阶
一、多次变一次
二、跳过
#1.跳过
#2.输出优化
三、TestSuite套件
四、TestLoader批量加载
五、disover批量加载
总结:
unittest是python的一个单元测试框架,其常用内容包括:TestFixture、TestCase、TestSuite、TestRunner。
unittest框架的基础使用流程:
1. 用import引入unittest模块
2.测试的类都是继承于TestCase类的
3.setUp()是测试执行前的初始化工作
4.tearDown()是测试执行后的清楚工作 (此两方法在每个测试方法运行时都会被调用)
# -*- coding:UTF-8 -*-
# mytestcase_1.py
import unittest
class MyTestCase1(unittest.TestCase):
def setUp(self):
print("setUp, before each test")
def tearDown(self):
print("tearDown, after each test")
def testcase1(self):
# code case1's logic in here
print("test case1")
def testcase2(self):
# code case2's logic in here
print("test case2")
def testcase3(self):
# code case3's logic in here
print("test case3")
if __name__ == '__main__':
unittest.main()
代码注释:
1.所有类中方法的入参都为self,且方法中变量的使用是“self.变量”的方式
2.所有用例方法都需以test开头来命名
3.unittest.main()会自动搜索该模块下以test开头的方法,并执行它们
setUp()、tearDown()执行每个用例时都会执行,太啰嗦。故使用执行所有用例只执行一次的函数:setUpClass()、tearDownClass()。
文上代码片段则变成:
# coding = utf-8
# mytestcase_1.py
import unittest
class MyTestCase1(unittest.TestCase):
@classmethod
def setUpClass(cls):
print("setUpClass, before all test")
@classmethod
def tearDown(cls):
print("tearDownClass, after all test")
def testcase1(self):
# code case1's logic in here
print("test case1")
def testcase2(self):
# code case2's logic in here
print("test case2")
def testcase3(self):
# code case3's logic in here
print("test case3")
if __name__ == '__main__':
unittest.main()
代码注释:
1.@classmethod为修饰器,表示标注该方法为类方法,此为python使用规则
2.两个函数传参为cls
代替原因注释:
1.每执行一个用例都要调用一次setUp、tearDown方法,在项目较大、用例数够多,且涉及到操作数据库的情况下,无疑会过多的消耗资源、浪费时间。
使用skip()可以跳过执行指定的testcase()方法。
文上代码片段变成:
# coding = utf-8
# mytestcase_1.py
import unittest
class MyTestCase1(unittest.TestCase):
@classmethod
def setUpClass(cls):
print("setUpClass, before all test")
@classmethod
def tearDown(cls):
print("tearDownClass, after all test")
def testcase1(self):
# code case1's logic in here
print("test case1")
@unittest.skip("skip this case")
def testcase2(self):
# code case2's logic in here
print("test case2")
def testcase3(self):
# code case3's logic in here
print("test case3")
if __name__ == '__main__':
unittest.main()
跳过原因注释:
1.当你编写过程中,需要进行调试时,可以跳过不需要调试的case
2.当项目实现过程中,业务暂不需要此用例功能
3.当项目发生改动不需要此用例功能,但因内部逻辑可借鉴而不愿删除代码时
执行unittest.main()方法后,可以查看执行结果是否正常通过。其实main()还有个传入的参数可以改变输出结果的样式。
文上所有main()代码片段可变成:
if __name__ == '__main__':
unittest.main(verbosity=2)
传参注释:
1.main()方法默认参数verbosity为1,成功输出. 失败输出F
2.verbosity=0 为最简洁样式,不输出每个用例执行结果
verbosity=2 为详细样式,输出用例名及执行结果
套件套件,即使用TestSuite()方法把所有的方法组装到一个套件suite中去一起执行。不仅可以把本case文件中的所有方法组装到一起,还可以把其它case文件中的方法组装到一起。
文上代码片段变成:
# coding = utf-8
# mytestcase_1.py
import unittest
from mytestcase_2 import MyTestCase2 # Ⅰ
class MyTestCase1(unittest.TestCase):
@classmethod
def setUpClass(cls):
print("setUpClass, before all test")
@classmethod
def tearDown(cls):
print("tearDownClass, after all test")
def testcase1(self):
# code case1's logic in here
print("test case1")
@unittest.skip("skip this case")
def testcase2(self):
# code case2's logic in here
print("test case2")
def testcase3(self):
# code case3's logic in here
print("test case3")
if __name__ == '__main__':
suite = unitttest.TestSuite() # Ⅱ
suite.addTest(MyTestCase1("testcase1")) # Ⅲ
suite.addTest(MyTestCase2("testcase1")) # Ⅲ
suite.addTests([MyTestCase1("testcase1"),MyTestCase2("testcase1")]) # Ⅳ
runner = unittest.TextTestRunner(verbosity=2) # Ⅴ
runner.run(suite) # Ⅵ
代码注释:
1.#Ⅰ简化表示引入第二个模块文件,自己可另写一个文件
2.#Ⅱ实例化TestSuite()对象
3.#Ⅲ单个加载用例的方式:一个是加载本case文件中的指定方法,另一个是加载其它case文件中的指定方法
4.#Ⅳ批量加载用例的方式,传参是数组形式,写入需要加载的类名指定方法即可
5.#ⅤTextTestRunner()方法为文本测试用例运行器,进行实例化对象
6.#Ⅵ该方法其下的run()是可以运行suite组装的用例,入参即为suite套件
套件使用注释:
1.在一、二中,用例的执行是有一定顺序的:按照方法名进行ASCII码进行排序的。当我们需要自定义排序时进行使用
2.当测试文件较多,方法不在一个文件中时,需要进行组织。
TestLoader()方法是用例加载器,通过把用例存放进去,再使用suite进行批量执行。
文上代码片段另增加:
# coding = utf-8
# userlogintestcase.py
import unittest
from mytestcase_1 import MyTestCase1 # 引入两个文件
from mytestcase_2 import MyTestCase2
class UserLoginTestCase(unittest.TestCase):
def setUp(self):
print("setUp, before each test")
def tearDown(self):
print("tearDown, after each test")
def testcase1(self):
# code case1's logic in here
print("test case1")
def testcase2(self):
# code case2's logic in here
print("test case2")
def testcase3(self):
# code case3's logic in here
print("test case3")
if __name__ == '__main__':
suite = unittest.TestSuite() # 实例化TestSuite对象
loader = unittest.TestLoader() # 实例化TestLoader对象
# 先使用loader分别加载两个文件中的所有方法
case1 = loader.loadTestsFromTestCase(MyTestCase1))
case2 = loader.loadTestsFromTestCase(MyTestCase2))
# 再将其放入suite中,注意这里是批量方法addTests()
suite.addTests(case1)
suite.addTests(case2)
# 运行器
runner = unittest.TextTestRunner(verbosity=2)
runner.run(suite)
代码注释:
1.已有两个.py文件:mytestcase_1.py、mytestcase_2.py,各表示一个功能模块,里边的方法即是该模块下的用例
2.此代码片段为userlogintestcase.py文件,以此方法来验证:TestLoader()方法可加载其它模块中的用例、可批量加载所有用例
3.(有待补充,或提问提醒)
discover()方法用例批量加载文件夹下的所有用例,需要传入所规定的参数格式。
增加代码片段如下:
# coding = utf-8
# run.py
import unittest
import os
def MyDiscover():
# 首先打印当前路径,以便自我检查
print(os.getcwd())
# 拼接用例所在的文件夹路径
case_path = os.path.join(os.getcwd(),"case")
print(case_path) # 再次打印检查拼接路径是否正确
# 使用discover()加载文件夹下的所有用例,且传入对应参数
# 参数:文件夹路径、匹配文件夹下case文件、top_level_dir顶层目录一般为None
# defaultTestLoader叫做测试用例加载器
discover = unittest.defaultTestLoader.discover(case_path,pattern="*Case*.py",top_level_dir=None)
# 可以打印看一下,这个是什么东西
print(discover)
if __name__ == '__main__':
runner = unittest.TextTestRunner()
runner.run(MyDiscover())
代码注释:
1.这是run.py,以此作为启动文件,在实际中不可能去挨个点击运行各个模块,故需要一个入口文件;并且验证了discover()方法可批量加载文件夹下的方法
2.(有待补充,或提问提醒)
至此,使用unittest进行接口自动化的基础操作就完成了,剩余的需要多练多理解多积累多补充。我一段时间不用也忘了不少。
内容整体缺少细枝末节的知识点、注释点,但并不影响整体的学习及复盘。