unittest是python单元测试框架,类似于JUnit框架
意义:
- 灵活的组织ui接口测试自动化用例
- 让用例高效的执行
- 方便验证测试用例的结果
- 集成html形式测试报告
- 一个class继承unittest.TestCase类,即是一个个具体的TestCase(类方法名称必须以test开头,否则不能被unittest识别)
- 每一个用例执行的结果的标识,成功是. ,失败为F,出错是E
- 每一个测试以test01、test02…依次写下去,unittest才可按照编号执行
- versity参数控制输出结果,0是简单报告、1是一般报告、2是详情报告。
- 用setUp()、terUpClass()以及tearDownClass()可以在用例执行前布置环境,以及在用例执行后清理环境。
- 参数中加stream,可以讲报告输出到文件:可以用HTMLTestRunner输出html报告。
- 多个单元的测试用例集合在一起,就是TestSuite。
案例1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | from selenium import webdriver import requests def test01(): ''' 用例1 :return: ''' url = "http://www.ynhousedata.cn/house/assessment/assess_public?token=9a5008072cfd7336350306fdd9ea9485×tamp=2022-04-22 09:20:33&layer=1&total_layer=8&total_area=120&pre_id=4450" re = requests.get(url) print (re.status_code, re.text, re.headers, re.encoding) def test02(): ''' 用例1 :return: ''' driver = webdriver.Chrome() driver.get( 'https://www.baidu.com/' ) search = input ( '输入搜索内容\n' ) driver.find_element_by_xpath( '//*[@id="kw"]' ).send_keys(search) driver.find_element_by_xpath( '//*[@id="su"]' ).click() test01() test02() |
以上测试,一旦test01出错,后边的代码无法执行,而且测试报告,不便于查阅。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | import unittest class TestCases(unittest.TestCase): @classmethod def setUpClass( cls ) - > None : print ( '所有用例的前置' ) @classmethod def tearDownClass( cls ) - > None : print ( '所有用例的后置' ) def setUp( self ) - > None : print ( '每个用例前置' ) def tearDown( self ) - > None : print ( '每个用例的后置' ) def test01( self ): print ( '执行用例1' ) def test02( self ): print ( '执行用例2' ) if __name__ = = '__main__' : unittest.main() |
运行结果
Ran 2 tests in 0.001s
OK
所有用例的前置
每个用例前置
执行用例1
每个用例的后置
每个用例前置
执行用例2
每个用例的后置
所有用例的后置
Process finished with exit code 0
若某个类下用例非常多,但又只想执行某一个,可以用以下方法
1 2 3 4 5 6 7 8 | if __name__ = = '__main__' : # 创建套件对象 suit = unittest.TestSuite() # 添加指定用例 suit.addTest(TestCases( "test02" )) run = unittest.TextTestRunner() run.run(suit) |
运行结果
所有用例的前置
每个用例前置
执行用例2
每个用例的后置
.所有用例的后置
----------------------------------------------------------------------
Ran 1 test in 0.000s
OK
<unittest.runner.TextTestResult run=1 errors=0 failures=0>
若某个类下用例非常多,以下运行方式可以执行多个用例
1 2 3 4 5 6 7 | if __name__ = = '__main__' : # 创建套件对象 suit = unittest.TestSuite() # 添加指定用例,多条 suit.addTests([TestCases( "test01" ), TestCases( "test02" )]) run = unittest.TextTestRunner() run.run(suit) |
运行结果
所有用例的前置
每个用例前置
执行用例1
每个用例的后置
.每个用例前置
执行用例2
每个用例的后置
.所有用例的后置
----------------------------------------------------------------------
Ran 2 tests in 0.000s
OK
<unittest.runner.TextTestResult run=2 errors=0 failures=0>
当一个py文件下有多个类,需要执行某个类的时候,可以用以下方法执行
1 2 3 4 5 6 7 8 | if __name__ = = '__main__' : # 创建套件对象 suit = unittest.TestSuite() # 加载类 load = unittest.TestLoader() suit.addTest(load.loadTestsFromTestCase(TestCases)) #TestCases为 run = unittest.TextTestRunner() run.run(suit) |
运行结果
所有用例的前置
每个用例前置
执行用例1
每个用例的后置
.每个用例前置
执行用例2
每个用例的后置
.所有用例的后置
----------------------------------------------------------------------
Ran 2 tests in 0.000s
OK
<unittest.runner.TextTestResult run=2 errors=0 failures=0>
当有多个测试类的时候,可以用以下方法执行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | from selenium import webdriver import requests import unittest class TestCases1(unittest.TestCase): @classmethod def setUpClass( cls ) - > None : print ( '所有用例的前置' ) @classmethod def tearDownClass( cls ) - > None : print ( '所有用例的后置' ) def setUp( self ) - > None : print ( '每个用例前置' ) def tearDown( self ) - > None : print ( '每个用例的后置' ) def test01( self ): print ( '执行用例1' ) def test02( self ): print ( '执行用例2' ) class TestCases2(unittest.TestCase): @classmethod def setUpClass( cls ) - > None : print ( '所有用例的前置' ) @classmethod def tearDownClass( cls ) - > None : print ( '所有用例的后置' ) def setUp( self ) - > None : print ( '每个用例前置' ) def tearDown( self ) - > None : print ( '每个用例的后置' ) def test04( self ): print ( '执行用例4' ) def test03( self ): print ( '执行用例3' ) if __name__ = = '__main__' : # 创建类加载对象 load = unittest.TestLoader() # 分别加载两个类 suit1 = load.loadTestsFromTestCase(TestCases1) suit2 = load.loadTestsFromTestCase(TestCases2) # 放在套件里 suits = unittest.TestSuite([suit1, suit2]) run = unittest.TextTestRunner() run.run(suits) |
运行结果
所有用例的前置
每个用例前置
执行用例1
每个用例的后置
.每个用例前置
执行用例2
每个用例的后置
.所有用例的后置
所有用例的前置
每个用例前置
执行用例3
每个用例的后置
.每个用例前置
执行用例4
每个用例的后置
.所有用例的后置
----------------------------------------------------------------------
Ran 4 tests in 0.000s
OK
<unittest.runner.TextTestResult run=4 errors=0 failures=0>
当需要执行多个py文件下的类的用例的时候可以用以下方法
文件结构
➜ unitTest pwd
/Users/lidong/Desktop/zhouyu/BILIBILI/笔记/unitTest,假设main.py执行testCase文件夹下的test*.py里的类
➜ unitTest tree
.
├── unitTest.md
├── __init__.py
├── main.py
└── testCase
├── test01.py
└── test02.py
1 directory, 5 files
test01.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | import unittest class TestCases1(unittest.TestCase): @classmethod def setUpClass( cls ) - > None : print ( '所有用例的前置' ) @classmethod def tearDownClass( cls ) - > None : print ( '所有用例的后置' ) def setUp( self ) - > None : print ( '每个用例前置' ) def tearDown( self ) - > None : print ( '每个用例的后置' ) def test01( self ): print ( '执行用例1' ) def test02( self ): print ( '执行用例2' ) |
test02.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | import unittest class TestCases2(unittest.TestCase): @classmethod def setUpClass( cls ) - > None : print ( '所有用例的前置' ) @classmethod def tearDownClass( cls ) - > None : print ( '所有用例的后置' ) def setUp( self ) - > None : print ( '每个用例前置' ) def tearDown( self ) - > None : print ( '每个用例的后置' ) def test04( self ): print ( '执行用例4' ) def test03( self ): print ( '执行用例3' ) |
main.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | # -*- coding: utf-8 -*- # @File : main.py # @Author : 李东 # @Time : 2022/04/25 10:42:20 import unittest test_dir = "/Users/lidong/Desktop/zhouyu/BILIBILI/笔记/unitTest" report_path = dis = unittest.defaultTestLoader.discover(test_dir, pattern = "test*.py" ) # 创建套件 suit = unittest.TestSuite() # 添加套件用例 suit.addTest(dis) run = unittest.TextTestRunner() run.run(suit) |
运行如下:
所有用例的前置
每个用例前置
执行用例1
每个用例的后置
.每个用例前置
执行用例2
每个用例的后置
.所有用例的后置
所有用例的前置
每个用例前置
执行用例3
每个用例的后置
.每个用例前置
执行用例4
每个用例的后置
.所有用例的后置
----------------------------------------------------------------------
Ran 4 tests in 0.000s
OK
<unittest.runner.TextTestResult run=4 errors=0 failures=0>
2、生成测试报告
进入网站,下载HTMLTestRunner文件
下载HTMLTestRunner链接
下载后修改文件,建议全部修改,如果报错,将不需要修改的地方还原即可。
1 2 3 4 5 6 7 8 9 | 94行,import StringI0 ||| import io 118行,self.fp.write(s) ||| self.fp.write(bytes(s,'UTF-8')) 539行,self.outputBuffer = StringI0.StringI0() ||| self.outputBuffer = io.BytesI0() 631行,print >>sys .stderr, '\nTime ELapsed: %s' % (self.stopTime-seLf.startTime) ||| print('\nTime Elapsed: %s' % (self.stopTime-self.startTime)) 642行,if not rmap.has_key(cls): ||| if not cls in rmap: 766行,uo = o.decode('latin-1') ||| uo = o 768行,uo = o ||| Uo = o.decode('utf-8') 772行,ue = e.decode('latin-1') ||| ue=e 774行,ue = e ||| ue = e.decode('utf-8') |
修改完成之后,将文件放入到python环境的lib目录下(windows)。mac 用户可以放在****/lib/python3.9/site-packages目录下。
创建报告存放的文件夹report,报告目录结构如下
main.py定义如下
1 2 3 4 5 6 7 8 9 10 11 12 13 | import unittest import HTMLTestRunner test_dir = "/Users/lidong/Desktop/zhouyu/BILIBILI/笔记/unitTest/testCase" # 报告存放的位置 report_path = "/Users/lidong/Desktop/zhouyu/BILIBILI/笔记/unitTest/report/" # 打开目录,生成html文件 file = open (report_path + 'result.html' , 'wb' ) # 文件格式生成 run = HTMLTestRunner.HTMLTestRunner(stream = file , title = '这是报告标题' , description = '这是报告描述' ) # 加载用 dis = unittest.defaultTestLoader.discover(test_dir, pattern = "test*.py" ) # 运行用例 run.run(dis) |
6、运行main.py之后,会在report目录下生成html报告
7、 使用浏览器打开,可以看到如下报告
断言基本操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | import unittest import requests class Tess(unittest.TestCase): def setUp( self ): res = requests.get( 'http://www.baidi.com' ) return res.status_code def test1( self ): # 判断获取的状态是否等于200 self .assertEqual( self .setUp(), 200 ) if __name__ = = '__main__' : unittest.main() |
数据驱动 ddt data
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | import unittest from ddt import ddt, data @ddt class TestCases2(unittest.TestCase): @classmethod def setUpClass( cls ) - > None : print ( '所有用例的前置' ) @classmethod def tearDownClass( cls ) - > None : print ( '所有用例的后置' ) def setUp( self ) - > None : print ( '每个用例前置' ) def tearDown( self ) - > None : print ( '每个用例的后置' ) @data ( 'username01' , 'username02' ) def test04( self , username): """冒烟用例""" print ( '执行用例4,' ,username, '登陆成功' ) def test03( self ): """爆炸用例""" print ( '执行用例3' ) if __name__ = = '__main__' : # 创建类加载对象 load = unittest.TestLoader() # 分别加载两个类 suit2 = load.loadTestsFromTestCase(TestCases2) # 放在套件里 suits = unittest.TestSuite([suit2]) run = unittest.TextTestRunner() run.run(suits) |
运行结果
所有用例的前置
每个用例前置
执行用例3
每个用例的后置
.每个用例前置
执行用例4, username01 登陆成功
每个用例的后置
.每个用例前置
执行用例4, username02 登陆成功
每个用例的后置
.所有用例的后置
----------------------------------------------------------------------
Ran 3 tests in 0.000s
OK
<unittest.runner.TextTestResult run=3 errors=0 failures=0>
巩固
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | # -*- coding: utf-8 -*-, # @File : test_module.py, # @Author : lidong, # @IDEA: PyCharm # @Time : 2022/4/25 16:57 import unittest class TestStringMethods(unittest.TestCase): a = 67 # 跳过被此装饰器装饰的测试。 reason 为测试被跳过的原因。 @unittest .skip( '取消测试' ) def test_upper( self ): print ( 'test_upper' ) # 当condition为真时,跳过被装饰的测试。 @unittest .skipIf(a> 5 , '取消测试' ) def test_upper2( self ): print ( 'test_upper2' ) # 跳过被装饰的测试,condition 为假 @unittest .skipUnless(a > 88 , '跳过被装饰的测试' ) def test_upper3( self ): print ( 'test_upper3' ) def test_upper5( self ): self .assertEqual( 'foo' .upper(), 'FOO' ) def test_isupper( self ): self .assertTrue( 'FOO' .isupper()) self .assertFalse( 'Foo' .isupper()) def test_split( self ): s = 'hello world' self .assertEqual(s.split(), [ 'hello' , 'world' ]) # check that s.split fails when the separator is not a string with self .assertRaises(TypeError): s.split( 2 ) if __name__ = = '__main__' : unittest.main() |
运行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = [SKIPPED] 取消测试 unitTest.testCase.test_module.TestStringMethods.test_upper unitTest.testCase.test_module.TestStringMethods.test_upper2 = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = [SKIPPED] 跳过被装饰的测试 unitTest.testCase.test_module.TestStringMethods.test_upper3 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Ran 6 tests in 0.093s PASSED (skips = 3 , successes = 3 ) Process finished with exit code 0 Skipped: 取消测试 Skipped: 取消测试 Skipped: 跳过被装饰的测试 |
最后感谢每一个认真阅读我文章的人,看着粉丝一路的上涨和关注,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走! 希望能帮助到你!【100%无套路免费领取】