unittest对.py文件类没有命名要求,只需要函数是以test为开头的就可以
二.运行顺序不同于pytest(从上往下)的是,unittest运行顺序是按照从0-9,A-Z,a-z的先后顺序运行的
三.五大组件 1.testcase(测试用例)(1)运行时可点击类/函数左侧绿色(当前类继承unittest.TestCase才会出现)的开关。点击函
数左侧的表示运行当前函数,点击类左侧的表示运行当前类下的所有case
(2)运行时可将光标停留在类/函数冒号右侧,鼠标右击点击run运行。光标停留在类名右侧表示
运行当前类下所有case,停留在具体函数名右侧,表示运行当前函数
(3)运行时可在main方法中unittest.main()来运行,运行顺序按照:0-9,A-Z,a-z先后运行
class unittest_demo(unittest.TestCase): def test_one(self): print("我是one") def test_two(self): print("我是two")2.testfixture(测试固件)
unittest中固件有两种。setup和teardown每个函数运行前后会各运行一次。setupclass和teardownclass
表示每个类运行前后会各运行一次。
(1)setup和teardown
这里set_tear继承了TestCase,然后又重写了setup和teardown两个前后置方法。我们在做自动化的时候
可用做前置准备工作和后置结束阶段
class set_tear(unittest.TestCase): def setUp(self) -> None: print("进入www.baidu.com页面") def tearDown(self) -> None: print("操作完毕,关闭浏览器页面")
(2)setup_class和teardown_class
这个用法和上面相同,重写时需要加上@classmethod,因为setupclass,和tearDownClass在testcase类
中为类方法
class set_tear(unittest.TestCase): @classmethod def setUpClass(cls) -> None: print("进入www.baidu.com页面") @classmethod def tearDownClass(cls) -> None: print("操作完毕,关闭浏览器页面")3.testsuite(测试套件)
测试套件的作用简单理解就是把你想要运行的case加到套件里面去,然后通过运行器去运行。这样可以选择性
的运行case,可以改变case运行的顺序。
(1)指定函数运行
运行的顺序是按照你加入套件的先后顺序来运行的
import unittest class unittest_suite(unittest.TestCase): def test_01(self): print("test_01") def test_02(self): print("test_02") def test_03(self): print("test_03") suite = unittest.TestSuite() # 创建一个套件 suite.addTest(unittest_suite("test_01")) # 添加case到套件中 suite.addTest(unittest_suite("test_02")) suite.addTest(unittest_suite("test_03"))
这里也可以使用addtests方法添加一个数组到套件中
suite = unittest.TestSuite() # 创建一个套件 caseList = [unittest_suite("test_01"), unittest_suite("test_01"), unittest_suite("test_01")] suite.addTests(caseList)
(2)指定类运行
import unittest class unittest_suite(unittest.TestCase): def test_01(self): print("test_01") def test_02(self): print("test_02") def test_03(self): print("test_03") suite = unittest.TestSuite() # 创建一个套件 load = unittest.TestLoader() # 创建一个加载器 loadClass = load.loadTestsFromTestCase(unittest_suite) # 调用加载类的方法并传入一个类 suite.addTest(loadClass) # 添加到套件中
运行顺序按照原有类里面的顺序进行运行
(3)指定模块(.py)运行
import testcase.demo_02 #导入要运行的.py suite = unittest.TestSuite() # 创建一个套件 load = unittest.TestLoader() # 创建一个加载器 loadClass = load.loadTestsFromModule(testcase.demo_02) #调用加载模块的方法 suite.addTest(loadClass)
suite.countTestCases()#统计case个数
(4)指定路径运行
suite = unittest.TestSuite() # 创建一个套件 load = unittest.TestLoader() # 创建一个加载器 suite.addTest(load.discover("./testcase", pattern="*02.py")) #调用discover方法指定路径运行
pattern中匹配符*表示通配符,可写成test*.py表示以test为开头,*xx.py表示以xx为结尾的都满足。
需要注意的是这里的路径不能具体到某个.py模块,模块的匹配规则必须写在pattern中
4.testrunner(运行器)一般与testsuite一起用,来运行套件的
if __name__ == '__main__': runner = unittest.TextTestRunner() # 创建个运行器 runner.run(suite) # suite为套件集5.testreport(测试报告)
这里不多介绍了,感兴趣的可以学习allure:https://www.cnblogs.com/lihongtaoya/p/15778263.html
四.spik用法 1.spik表示跳过该条case不执行
class unittest_suite(unittest.TestCase): def test_01(self): print("test_01") @unittest.skip def test_02(self): print("test_02") def test_03(self): print("test_03")2.spikif()
判断条件4>2,为true时不运行,打印标签reason。为false运行该条case
class unittest_suite(unittest.TestCase): def test_01(self): print("test_01") @unittest.skipIf(4 > 2, reason="猪头") def test_02(self): print("test_02") def test_03(self): print("test_03")3.skipUnless()
和skipif()效果相反,判断条件为true运行,为false不运行
class unittest_suite(unittest.TestCase): def test_01(self): print("test_01") @unittest.skipUnless(4 > 2, reason="猪头") def test_02(self): print("test_02") def test_03(self): print("test_03")五.ddt数据驱动(第三方的需要pip install ddt下载)
python装饰器可参考:https://www.cnblogs.com/lihongtaoya/p/16368111.html
unittest中@ddt为类装饰器,其它三个都是函数装饰器。ddt
1.@ddtimport unittest from ddt import ddt @ddt class unittest_ddt(unittest.TestCase): def testOne(self): pass
@ddt作用于类,表示当前类使用ddt框架
2.@data()@data()主要用来传值的(可传int,str,list,set,dict,tuple)
(1)传单个int/str值和多个int/str值
import unittest from ddt import ddt, data @ddt class unittest_ddt(unittest.TestCase): #@data(1, 2, 3) @data("1","2","3") def testOne(self, a): print(a)
这里的a是用于接收传递过来的参数,打印结果为1,2,3
(2)传单个set/list/tuple/
import unittest from ddt import ddt, data @ddt class unittest_ddt(unittest.TestCase): # @data((1,2,3))
# @data({1,2,3}) @data([1, 2, 3]) # 传递单个list def testOne(self, a): print(a)
运行结果:[1, 2, 3]||(1, 2, 3)
以上可以看出的是传参时会把[1, 2, 3]和(1, 2, 3)当作一个整体传给a,那么如果我们想要单个值分别
传递给a。只需要在[1,2,3]前加上一个*号即可
@ddt class unittest_ddt(unittest.TestCase): # @data((1,2,3)) @data(*[1, 2, 3]) # 传递单个list def testOne(self, a): print(a)
运行结果:1 2 3
这里*的作用就是去掉最外层的壳,既:[ ]和()
3.@unpack()
当传递的参数含有多个值的时候,需要用的unpack来进行解包
@unpack()主要用来解包(去外壳)
(1)传递多个list/set/tuple
@ddt class unittest_ddt(unittest.TestCase): # @data((1,2,3)) # @data(*[1, 2, 3]) # 传递单个list @data((1,2,3),(4,5,6)) @unpack def testOne(self, a,b,c): print(a)
打印结果:1 4
这里需要注意的是接收数据的参数个数(a,b,c)要和list/set/tuple中的数量相等
(2)dict类型
@ddt class unittest_ddt(unittest.TestCase): # @data((1,2,3)) # @data(*[1, 2, 3]) # 传递单个list @data({"name": "liming", "age": 123}, {"name": "lihua", "age": 123}) @unpack def testOne(self, name, age): print(name)
打印结果:liming lihua
传递dict数据类型的时候要保证接收数据的变量(name,age)要和dict中的key值一模一样(数量和key值)
(3)传递嵌套的类型结构
import unittest from ddt import ddt, data, unpack datalist = [ { "name": "liming", "age": 12 }, { "name": "lihua", "age": 13 },{ "name": "lisan", "age": 18 } ] @ddt class unittest_ddt(unittest.TestCase): @data(*datalist) # 加*后数据结构变成:{},{} @unpack # 解包去外壳 def testOne(self, name, age): print(name)4.@file_data()
当yaml和json中的数据结构为[{},{},{}]时,@file_data()的作用就相当于@data()+@unpack()
@file_data()可直接读取yaml和json文件
(1)首先我们先创建一个yaml文件
- username: liming password: 123456 - username: lifei password: 2
(2)在@file_data()中直接引用yaml文件即可
from ddt import ddt, data, unpack, file_data @ddt class unittest_ddt(unittest.TestCase): @file_data("../params/demo_01.yaml") def testOne(self,username,password): print(username)
这里username和password也是要和yaml中的key值(数量)相等。json用法也是一样,这里不多介绍了。
5.csv做数据驱动创建一个csv文件
liming,123
lifei,1234
导入csv,reader()方法读取后加入list里
with open("../params/demo_01.csv", mode="r", encoding="utf8")as a: da=csv.reader(a) data_list=[] for i in da: data_list.append(i)
当前data_list打印结果:[['liming', '123'], ['lifei', '1234']],然后再用data和unpack装饰器即可
六.实例
下一章再写吧,
注:网上已经一大堆教程了,不要转载