引言
在编写接口自动化用例时,我们一般针对一个接口建立一个.py文件,一条接口测试用例封装为一个函数(方法),但是在批量执行的过程中,如果其中一条出错,后面的用例就无法执行,还有在运行大量的接口测试用例时测试数据如何管理和加载。针对测试用例加载以及执行控制,python语言提供了unittest单元测试框架,将测试用例编写在unittest框架下,使用该框架可以单个或者批量加载互不影响的用例执行及更灵活的执行控制,对于更好的进行测试数据的管理和加载,这里我们引入数据驱动的模块:ddt,测试数据和测试脚本的分离,通过ddt数据驱动来加载测试数据到测试用例脚本中,通常在接口自动化测试中会将unittest和ddt结合起来使用,从而实现测试用例脚本和测试数据的载入来完成测试的执行。下面来看看unittest框架和ddt这两个模块具体的应用。
一、unittest测试框架
unittest单元测试框架是python语言的一套标准模块,封装提供了诸多操作测试用例和用例加载、测试前置和场景恢复以及测试结果输出等一系列类和方法。
1.unittest框架中最核心四个组件概念:
(1)TestCase:测试用例类,编写测试用例脚本时需要继承该类,从而具有该类的属性和方法,一个TestCase实例就是一个测试用例,其中测试用例方法都以test开头。
(2)TestSuite:测试集,也就是测试用例的集合,用来组织用例。
(3)testrunner:用来执行测试用例,并返回测试用例的执行结果,可以用图形或者文本将测试结果形象地展现出来,HTMLTestRunner用来生成图形化的报告,TextTestRunner用来生成简单的文本测试结果。
(4)testfixure:测试夹件,主要用于测试用例的前置初始化和执行后的销毁。
2.testcase----测试用例
- 新建一个的.py测试用例文件必须是test开头,如test_login.py,主要后续用于识别测试用例文件编写测试用例的类,必须继承unittest.TestCase,做为测试类
- 测试类中用例的方法名称必须以test开头,用于识别测试用例数
- 测试类中的用例执行顺序,按照以test开头的方法后的Ascill码顺序执行(0~9,A~Z,a~z)
3.testfixure----测试夹件
- 也叫测试夹具,主要是用例前置的初始化以及执行后的销毁
- 测试夹件提供两种方法,一种是类级别的:setup()和teardown(),一种是方法级别的:setUpClass()和tearDownClass()
- 类级别的测试夹件,每一条测试用例执行之前与之后都要运行一次setup()和teardown();方法级别的测试夹件,所有测试用例执行之前到执行完成只运行一次setUpClass()和tearDownClass()
下面通过简单的代码示例看看TestCase与TestFixure的使用
(1)使用setup()和teardown(),创建test_666.py文件编辑如下代码:
import unittest class test_unittest(unittest.TestCase): def setUp(self): print("测试环境初始化,开始执行setup") def tearDown(self): print("测试执行完成,运行teardown") print("------------------------------") def test_a(self): print("开始执行test_a用例") def test_A(self): print("开始执行test_A用例") def test_1(self): print("开始执行test_1用例") def notest_1(self): print("不执行notest_1用例") if __name__ == "__main__": unittest.main()
执行后,输出如下:
在代码中我们编写了4个def用例方法,只执行了3个def,因为最后一个def不是test开头。可以看到每执行一个def用例,setup()和teardown()都会执行一次,其中按照执行顺序:test_1最先执行,test_A其后,test_a最后执行
(2)使用setUpClass()和tearDownClass()
对于setUpClass()和tearDownClass()我们只需将上面代码,稍微修改即可
import unittest class test_unittest(unittest.TestCase): @classmethod def setUpClass(cls): print("测试环境初始化,开始执行setup") @classmethod def tearDownClass(cls): print("测试执行完成,运行teardown") print("------------------------------") def test_a(self): print("开始执行test_a用例") def test_A(self): print("开始执行test_A用例") def test_1(self): print("开始执行test_1用例") if __name__ == "__main__": unittest.main()
运行效果如下:
可以看到所有用例都执行完后,setUpClass()和tearDownClass()只运行了一次。因此在编写一个测试脚本时,里面写了多个测试用例,
这时我们希望的是所有用例执行完成后再销毁环境,这时使用setUpClass()
和tearDownClass()
就比较好了。
3.TestSuite----测试集
unittest框架下提供了unittest.TestSuite()和unittest.TestLoader()类,这两个类下封装了加载用例的方法,用于加载测试用例到测试集中
(1)unittest.TestSuite()提供单个用例加载方法
addTest():单个用例加载,当然也可以将多个用例的方法名放入列表中添加到addTest()中,加载多条测试用例
(2)unittest.TestLoader()提供批量加载或发现用例的方法
loadTestsFromTestCase(测试类名):添加一个测试类
loadTestsFromModule(模块名):添加一个模块
discover(测试用例的所在目录):指定目录去加载,会自动寻找这个目录下所有符合命名规则的测试用例
4.testrunner----测试运行
testrunner就是用来执行测试用例的,并且可以生成相应的测试报告。测试报告有两种展示形式,一种是text文本,一种是html格式。
"htmlcode">
import unittest from test.test_666 import test_unittest # 单个用例加载 suite = unittest.TestSuite() case1 = test_unittest('test_1') case2 = test_unittest('test_a') suite.addTest(case1) suite.addTest(case2) print(suite) print("------------------") # 批量用例加载 case_path = r"E:\api_test\test" # 按文件路径加载,注意该文件为包文件即文件下有__init__.py all_case = unittest.defaultTestLoader.discover(case_path,pattern="test_666*.py",top_level_dir=None) all_case1 = unittest.defaultTestLoader.loadTestsFromTestCase(test_unittest) # 按类名称加载 print(all_case) print("------------------") print(all_case1)
输出结果如下:
E:\api_test\Scripts\python.exe E:/api_test/test_bak/run_case.py
<unittest.suite.TestSuite tests=[<test.test_666.test_unittest testMethod=test_1>, <test.test_666.test_unittest testMethod=test_a>]>
------------------
<unittest.suite.TestSuite tests=[<unittest.suite.TestSuite tests=[<unittest.suite.TestSuite tests=[<test_666.test_unittest testMethod=test_1>, <test_666.test_unittest testMethod=test_A>, <test_666.test_unittest testMethod=test_a>]>]>]>
------------------
<unittest.suite.TestSuite tests=[<test.test_666.test_unittest testMethod=test_1>, <test.test_666.test_unittest testMethod=test_A>, <test.test_666.test_unittest testMethod=test_a>]>
Process finished with exit code 0
通过unittest框架下提供的加载用例的诸多方法,我们就可以单个或者批量加载用例,后续可以将加载的用例集引入到HTMLTestRunner.py模块生成可视化的测试报告
5.assert----测试断言
无论是什么样的测试用例,最后都需要有用例执行后的验证,在接口自动化测试中我们执行完接口用例也需要验证断言用例执行是否满足我们的预期。unittest提供了丰富的断言方法,常见的断言如下表:
二、ddt数据驱动
- @ddt:类的装饰器,继承的是TestCase类
- @data():@data装饰符可以把参数当成测试数据,参数可以是单个值、列表、元祖、字典这些类型,用于输入测试数据
- @unpack:分解数据标志,主要是把元祖和列表解析成多个参数
- @file_data():输入文件,如json或者yaml类型文件
(1)输入简单的参数:单个值、列表、元祖、字典
import unittest from ddt import data,unpack,ddt @ddt class myddt(unittest.TestCase): @data("123") # 单个值 def test1(self,testdata1): print(testdata1) print("------------------") @data([1,2,3],[4,5,6]) # 列表 def test2(self,testdata2): print(testdata2) print("------------------") """ @data((1, 2, 3)) # 元组 def test2(self, testdata3): print(testdata3) print("------------------") @data({'zhangshan':1,'wangwu':2,'lisi':3}) # 字典 def test2(self, testdata4): print(testdata4) print("------------------") """ if __name__ == '__main__': unittest.main()
(2)使用@unpack对复杂数据结构,如元组、列表数据进行分解
代码示例:
import unittest from ddt import data,unpack,ddt @ddt class myddt(unittest.TestCase): @data([1,2],[3,4]) # 列表 @unpack def test2(self, testdata1,testdata2): print("拆解的第一个参数:",testdata1) print("拆解的第二个参数:", testdata2) print("------------------") if __name__ == '__main__': unittest.main()
运行后输出如下:
(3)使用@file_data()输入文件格式测试数据
编辑一个data.json的文件,代码示例:
import unittest from ddt import file_data,ddt @ddt class myddt(unittest.TestCase): @file_data(r"E:\api_test\test\data.json") def test1(self, *value): print(value) if __name__ == '__main__': unittest.main()
通过ddt和unittest框架的结合就可以实现测试用例脚本编写、测试执行控制以及测试数据的批量加载,从而完成不同接口测试用例的批量执行和覆盖测试不同测试场景。
《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线
暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。
艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。
《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。
更新动态
- 凤飞飞《我们的主题曲》飞跃制作[正版原抓WAV+CUE]
- 刘嘉亮《亮情歌2》[WAV+CUE][1G]
- 红馆40·谭咏麟《歌者恋歌浓情30年演唱会》3CD[低速原抓WAV+CUE][1.8G]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[320K/MP3][193.25MB]
- 【轻音乐】曼托凡尼乐团《精选辑》2CD.1998[FLAC+CUE整轨]
- 邝美云《心中有爱》1989年香港DMIJP版1MTO东芝首版[WAV+CUE]
- 群星《情叹-发烧女声DSD》天籁女声发烧碟[WAV+CUE]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[FLAC/分轨][748.03MB]
- 理想混蛋《Origin Sessions》[320K/MP3][37.47MB]
- 公馆青少年《我其实一点都不酷》[320K/MP3][78.78MB]
- 群星《情叹-发烧男声DSD》最值得珍藏的完美男声[WAV+CUE]
- 群星《国韵飘香·贵妃醉酒HQCD黑胶王》2CD[WAV]
- 卫兰《DAUGHTER》【低速原抓WAV+CUE】
- 公馆青少年《我其实一点都不酷》[FLAC/分轨][398.22MB]
- ZWEI《迟暮的花 (Explicit)》[320K/MP3][57.16MB]