Python之unittest框架的介绍及使用
目录
unittest介绍
unittest是Python自带的一个单元测试框架, 它可以做单元测试, 也能用于编写和运行重复的测试工作.
它给自动化测试用例开发和执行提供了丰富的断言方法, 判断测试用例是否通过, 并最终生成测试结果.
TestCase编写
- TestCase指的就是测试用例
- 测试类必须继承unittest.TestCase
- 测试方法名称命名必须以test开头
- 测试方法的执行顺序有Case序号决定, 并非由代码顺序决定
一个简单的例子:
# 1. 导入unittest
import unittest
# 2. 创建类继承unittest.TestCase
class Test(unittest.TestCase):
# 3. 创建测试用例方法, 方法要以test开头
# 执行顺序是根据case序号来的, 并非代码的顺序
def test_add_01(self):
print(3+2)
def test_add_02(self):
print(10+5)
TestSuite与TextTestRunner
在上面提到, 测试用例的执行顺序默认是由case序号决定的,但也可以使用TestSuite控制用例的执行顺序。
- TestSuite(测试套件)可以组织多个测试用例
- TextTestRunner测试用例运行器
- run()方法是测试用例的执行, 入参为suite测试套件
一个简单的例子
# 1. 导入unittest
import unittest
# 2. 创建类继承unittest.TestCase
class Test(unittest.TestCase):
# 3. 创建测试用例方法, 方法要以test开头
# 执行顺序是根据case序号来的, 并非代码的顺序
def test_add_01(self):
print(3+2)
def test_add_02(self):
print(10+5)
if __name__ == '__main__':
suite = unittest.TestSuite() # 实例化TestSuite
suite.addTest(Test("test_add_02")) # 添加测试用例
suite.addTest(Test("test_add_01"))
runner = unittest.TextTestRunner() # 实例化TextTestRunner
runner.run(suite) # 传入suite并执行测试用例
但是要注意, 如果在Pychram中直接右键运行, 它是不会执行main下面的内容, 需要修改pychram的运行方式
然后重新运行, 就会执行main下面的内容了.
重点,通常测试用例都是多个的,因此测试用例可以存放到列表中一次性添加到测试套件。这里可以使用suite.addTests()
case_list = ['Test("test_add_02")', Test("test_add_01")]
suite.addTests(case_list)
TestLoader
如果有多个测试文件时, 可以使用TestLoader加载测试用例
-
unittest.defaultTestLoader
, 使用discover()去加载测试用例- 找到指定目录下所有测试模块,并可递归查到子目录下的测试模块,只有匹配到文件名才能被加载
- discover(start_dir, pattern=‘test*.py’, top_level_dir=None)
- start_dir:要测试的模块名货测试用例目录
- pattern=“test*.py”: 表示用例文件名的匹配原则。 此处匹配文件名以“test”开头的“.py”类型的文件,*表示任意字符
- top_level_dir=None:测试模块的顶层目录, 如果没有顶层目录, 默认为None
一个小例子, 再目录下创建多个test开头的py文件, 并且写入测试方法
然后使用discover()方法读取测试用例并执行
import unittest
# dicsover方法查找用例
suite = unittest.defaultTestLoader.discover("unittest_test", "test*.py")
# 2.TextTestRunner运行用例
runer = unittest.TextTestRunner()
runer.run(suite)
TestFixture
setUp和tearDown
setUp()方法
- 主要是用来初始化测试环境, 它在每条测试用例执行前都会调用
tearDown()方法
- 主要作用是测试用例执行完毕后恢复测试环境, 即使出现异常也会调用此方法,每条用例执行结束后都会运行
一个简单的例子
import unittest
class Test(unittest.TestCase):
def setUp(self) -> None: # 调用setUp
super().setUp()
print("测试用例执行前操作")
def test_add_01(self):
print("num02")
def test_add_02(self):
print("num03")
def tearDown(self) -> None: # 调用tearDown
super().tearDown()
print("测试用例执行后操作")
# 返回结果
测试用例执行前操作
num02
测试用例执行后操作
测试用例执行前操作
num03
测试用例执行后操作
在上面的返回结果中可以明确的看出, 每条用例执行前都会先运行setUp,执行结束后都会运行tearDown
setUpClass和tearDownClass
setUpClass
- 初始化测试环境且只会执行一次。在类中需要加上@classmethod
tearDownClass
- 恢复测试环境且只会执行一次。在类中需要加上@classmethod
import unittest
class Test(unittest.TestCase):
@classmethod
def setUpClass(cls) -> None:
super().setUpClass()
print("测试前的操作")
@classmethod
def tearDownClass(cls) -> None:
super().tearDownClass()
print("测试后的操作")
def test_add_01(self):
print(3+2)
def test_add_02(self):
print(10+5)
# 返回结果
测试前的操作
15
5
测试后的操作
从返回结果可以看到setUpClass和tearDownClass都只是执行了一次,与setUp和tearDown的结果有很明显的区别。
注意,setUpClass和tearDownClass执行一次是针对当前的测试类而言的,如果当前的py文件有多个测试类, 那么它每个测试类都会执行一次。
如下:
# 1. 导入unittest
import unittest
# 2. 创建类继承unittest.TestCase
class Test(unittest.TestCase):
@classmethod
def setUpClass(cls) -> None:
super().setUpClass()
print("测试前的操作")
@classmethod
def tearDownClass(cls) -> None:
super().tearDownClass()
print("测试后的操作")
# 3. 创建测试用例方法, 方法要以test开头
# 执行顺序是根据case序号来的, 并非代码的顺序
def test_add_01(self):
print(3+2)
def test_add_02(self):
print(10+5)
class Test2(unittest.TestCase):
@classmethod
def setUpClass(cls) -> None:
super().setUpClass()
print("测试前的操作2")
@classmethod
def tearDownClass(cls) -> None:
super().tearDownClass()
print("测试后的操作2")
def test_add_03(self):
print(20)
def test_add_04(self):
print(40)
if __name__ == '__main__':
suite = unittest.TestSuite() # 实例化TestSuite
suite.addTests([Test("test_add_02"), Test("test_add_01"), Test2("test_add_03"), Test2("test_add_04")]) # 添加测试用例
runner = unittest.TextTestRunner() # 实例化TextTestRunner
runner.run(suite) # 传入suite并执行测试用例
断言(重点)
常用的断言
方法 | 检查 |
---|---|
assertEqual(a, b) | a == b |
assertNotEqual(a, b) | a != b |
assertTrue(x) | x的布尔值为真 |
assertFalse(x) | x的布尔值为假 |
assertIn(a, b) | a in b |
assertNotIn(a, b) | a not in b |
assertEqual(a, b) 和 assertNotEqual(a, b)
# 1. 导入unittest
import unittest
# 2. 创建类继承unittest.TestCase
class Test(unittest.TestCase):
def setUp(self) -> None:
super().setUp()
print("测试开始")
def test_add_01(self):
print("1 == 1")
self.assertEqual(1, 1) # 成功
def test_add_02(self):
print("1 == 2")
self.assertEqual(1, 2) # 失败
def test_add_03(self):
print("1 !=2 ")
self.assertNotEqual(1, 2) # 成功
def test_add_04(self):
print("1 != 1")
self.assertNotEqual(1, 1) # 失败
def tearDown(self) -> None:
super().tearDown()
print("测试结束")
assertTrue(x)和assertFalse(x)
class Test(unittest.TestCase):
@classmethod
def setUpClass(cls) -> None:
super().setUpClass()
print("测试前的操作2")
@classmethod
def tearDownClass(cls) -> None:
super().tearDownClass()
print("测试后的操作2")
def test_05(self):
self.assertTrue(1 < 2) # 成功
def test_06(self):
self.assertTrue(1 > 2) # 失败
def test_07(self):
self.assertFalse(1 > 2) # 成功
def test_08(self):
self.assertFalse(1 < 2) # 失败
assertIn(a, b)和assertNotIn(a, b)
import unittest
class Test(unittest.TestCase):
@classmethod
def setUpClass(cls) -> None:
super().setUpClass()
print("测试前的操作2")
@classmethod
def tearDownClass(cls) -> None:
super().tearDownClass()
print("测试后的操作2")
def test_09(self):
self.assertIn("a", "abc") # 成功
def test_10(self):
self.assertIn("a", "bcd") # 失败
def test_11(self):
self.assertNotIn("a", "bcd") # 成功
def test_12(self):
self.assertNotIn("a", "abc") # 失败
测试报告
文件方式的测试报告
import unittest
# dicsover方法查找用例
suite = unittest.defaultTestLoader.discover("unittest_test", "test*.py")
# 打开文件对象
with open("test_report.txt", "a") as f:
# TextTestRunner运行用例
runer = unittest.TextTestRunner(stream=f, verbosity=2) # verbosity=2 输出详细日志
runer.run(suite)
HTML方式的测试报告
HTML报告需要导入HTMLTestRunner.py,这个文件原本只支持python2,python3需要修改部分代码才能使用。
然后我发现CSDN这里已经有人上传过这个资源了, 不过貌似要收费, 我这里也传一个网盘吧, 这是已经修改好支持python的, 直接使用就行。
链接:https://pan.baidu.com/s/171jiRp9lw8Gtrl140g0uJw
提取码:64db
回到正题,HTMLTestRunner的用法其实和TextTestRunner的差不多, 代码如下:
import unittest
from lib.HTMLTestRunner import HTMLTestRunner
# dicsover方法查找用例
suite = unittest.defaultTestLoader.discover("unittest_test", "test*.py")
with open("test_report.html", "wb") as report:
runner = HTMLTestRunner(stream=report, verbosity=2, title="HTML测试报告", description="这是练习的测试报告")
runner.run(suite)
运行结束后在本地就会看到多了一个HTML文件,打开就能看到测试报告了
skip跳过用例
在遇到不想执行的测试用例时,可以使用skip方法
-
@unittest.skip(reason)
:无条件跳过用例, reason是说明原因 -
@unittest.skipIf(condition, reason)
:condition为true时跳过用例 -
@ unittest.skipUnless(condition, reason)
:condition为False的时候跳过
实例代码:
# 1. 导入unittest
import unittest
class Test(unittest.TestCase):
@classmethod
def setUpClass(cls) -> None:
super().setUpClass()
print("测试前的操作2")
@classmethod
def tearDownClass(cls) -> None:
super().tearDownClass()
print("测试后的操作2")
@unittest.skip("无条件跳过")
def test_09(self):
self.assertIn("a", "abc")
@unittest.skipIf(2>1, "因为2>1所以跳过")
def test_10(self):
self.assertIn("a", "bcd")
@unittest.skipUnless(1>2, "因为1>2为假,所以跳过")
def test_11(self):
self.assertNotIn("a", "bcd")
def test_12(self):
self.assertNotIn("a", "abc")
然后执行用例并生成测试报告
import unittest
from lib.HTMLTestRunner import HTMLTestRunner
# dicsover方法查找用例
suite = unittest.defaultTestLoader.discover("unittest_test", "test*.py")
with open("test_report.html", "wb") as report:
runner = HTMLTestRunner(stream=report, verbosity=2, title="HTML测试报告", description="这是练习的测试报告")
runner.run(suite)
测试报告,只剩下了一个测试用例了
上一篇: day14_0710课堂笔记
下一篇: 场景法测试用例设计详解
推荐阅读
-
python 接口自动化测试框架-unittest框架的基本使用
-
Python之unittest框架的介绍及使用
-
python unittest框架的使用&解析
-
python unittest 极简自动化测试框架:二、 BeautifulReport的使用简解,生成漂亮的报告
-
Python之Scrapy爬虫框架安装及使用详解
-
Python ORM框架SQLAlchemy学习笔记之映射类使用实例和Session会话介绍
-
Python ORM框架SQLAlchemy学习笔记之映射类使用实例和Session会话介绍
-
Python的Bottle框架的一些使用技巧介绍
-
使用Python编写爬虫的基本模块及框架使用指南
-
python——虚拟环境之pipenv的安装及使用(windows10,64位)