| assertNotIn(a, b) | a not in b |
| assertIsInstance(a, b) | isinstance(a, b) |
| assertNotIsInstance(a, b) | not isinstance(a, b) |
TestCase测试用例
编写测试用例前,我们需要创建一个类继承unittest里面的TestCase类,之后我们才能真正的使用unittest框架去编写测试用例.
步骤如下:
- 导入
unittest
模块 - 创建一个测试类,继承
unittest.TestCase
类 - 定义测试方法,方法名必须以
test_
开头 - 调用unittest.main()方法来运行测试用例。
unittest.main()
方法会搜索该模块下所有以test开头的测试用例和方法,并自动执行。
代码示例
# 注册功能代码
# users列表存储成功注册的用户
users = [{'username': 'testing', 'password': '123456'}]
def register(username, password1, password2):
if not all([username, password1, password2]):
return {'code': 0, 'msg': '所有参数不能为空.'}
# 注册
for user in users:
if username == user['username']:
return {'code': 0, 'msg': '用户名已存在!'}
else:
if password1 != password2:
return {'code': 0, 'msg': '两次密码输入不一致!'}
else:
if 6 <= len(username) <= 18 and 6 <= len(password1) <= 18:
# 追加到users列表
users.append({'username': username, 'password': password2})
return {'code': 0, 'msg': '注册成功.'}
else:
return {'code': 0, 'msg': '用户名和密码的长度必须在6~18位之间.'}
import unittest
from demo import register # 导入被测试代码
class RegisterTest(unittest.TestCase):
'''注册接口测试类'''
def test_register_success(self):
'''注册成功'''
data = ('palien', 'palien', 'palien') # 测试数据
result = register(*data) # 测试结果
expected = {'code': 0, 'msg': '注册成功.'} # 预期结果
self.assertEqual(result, expected) # 断言测试结果与预期结果一致
# pass
def test_username_exist(self):
'''注册失败-用户名已存在'''
data = ('testing', '123456', '123456')
result = register(*data)
expected = {'code': 0, 'msg': '用户名已存在!'}
self.assertEqual(result, expected)
def test_username_isnull(self):
'''注册失败-用户名为空'''
data = ('', 'palien', 'palien')
result = register(*data)
expected = {'code': 0, 'msg': '所有参数不能为空.'}
self.assertEqual(result, expected)
# pass
def test_username_lt18(self):
'''注册失败-用户名长度大于18位'''
data = ('palienpalienpalienpalien', 'palien', 'palien')
result = register(*data)
expected = {'code': 0, 'msg': '用户名和密码的长度必须在6~18位之间.'}
self.assertEqual(result, expected)
# pass
def test_password1_not_password2(self):
'''注册失败-两次输入密码不一致'''
data = ('palien', 'palien1', 'palien2')
result = register(*data)
expected = {'code': 0, 'msg': '两次密码输入不一致!'}
self.assertEqual(result, expected)
# pass
# 如果要直接运行这个测试类,需要使用unittest中的main函数来执行测试用例
if __name__ == '__main__':
unittest.main()
# Output
Windows PowerShell
版权所有 (C) Microsoft Corporation。保留所有权利。
尝试新的跨平台 PowerShell https://aka.ms/pscore6
PS D:\d_02_study\01_git> cd d:/d_02_study/01_git/papers/system/02automation
PS D:\d_02_study\01_git\papers\system\02automation> & C:/Users/TDH/AppData/Local/Programs/Python/Python310-32/python.exe d:/d_02_study/01_git/papers/system/02automation/demo.py
.....
----------------------------------------------------------------------
Ran 5 tests in 0.001s
OK
PS D:\d_02_study\01_git\papers\system\02automation>
TestFixture测试夹具
unittest的测试夹具有两种使用方式,一种是以测试用例的方法为维度的:setUp()
和 tearDown()
;另一种是以测试类为维度的:setUpClass()
和 tearDownClass()
。
代码示例:
# users列表存储成功注册的用户
users = [{'username': 'testing', 'password': '123456'}]
def register(username, password1, password2):
if not all([username, password1, password2]):
return {'code': 0, 'msg': '所有参数不能为空.'}
# 注册
for user in users:
if username == user['username']:
return {'code': 0, 'msg': '用户名已存在!'}
else:
if password1 != password2:
return {'code': 0, 'msg': '两次密码输入不一致!'}
else:
if 6 <= len(username) <= 18 and 6 <= len(password1) <= 18:
# 追加到users列表
users.append({'username': username, 'password': password2})
return {'code': 0, 'msg': '注册成功.'}
else:
return {'code': 0, 'msg': '用户名和密码的长度必须在6~18位之间.'}
import unittest
from demo import register # 导入被测试代码
class RegisterTest(unittest.TestCase):
'''注册接口测试类'''
@classmethod # 指明这是个类方法,以类为维度去执行的
def setUpClass(cls) -> None:
'''整个测试用例类中的用例执行之前,会先执行此方法'''
print('-----setup---class-----')
@classmethod
def tearDownClass(cls) -> None:
'''整个测试用例类中的用例执行完成后,会执行此方法'''
print('-----teardown---class-----')
def setUp(self):
'''每条测试用例执行前都会执行'''
print('用例{}开始执行...'.format(self))
def tearDown(self):
'''每条测试用例执行结束后都会执行'''
print('用例{}执行结束...'.format(self))
def test_register_success(self):
'''注册成功'''
data = ('palien', 'palien', 'palien') # 测试数据
result = register(*data) # 测试结果
expected = {'code': 0, 'msg': '注册成功.'} # 预期结果
self.assertEqual(result, expected) # 断言测试结果与预期结果一致
# pass
def test_username_exist(self):
'''注册失败-用户名已存在'''
data = ('testing', '123456', '123456')
result = register(*data)
expected = {'code': 0, 'msg': '用户名已存在!'}
self.assertEqual(result, expected)
def test_username_isnull(self):
'''注册失败-用户名为空'''
data = ('', 'palien', 'palien')
result = register(*data)
expected = {'code': 0, 'msg': '所有参数不能为空.'}
self.assertEqual(result, expected)
# pass
def test_username_lt18(self):
'''注册失败-用户名长度大于18位'''
data = ('palienpalienpalienpalien', 'palien', 'palien')
result = register(*data)
expected = {'code': 0, 'msg': '用户名和密码的长度必须在6~18位之间.'}
self.assertEqual(result, expected)
# pass
def test_password1_not_password2(self):
'''注册失败-两次输入密码不一致'''
data = ('palien', 'palien1', 'palien2')
result = register(*data)
expected = {'code': 0, 'msg': '两次密码输入不一致!'}
self.assertEqual(result, expected)
# pass
# 如果要直接运行这个测试类,需要使用unittest中的main函数来执行测试用例
if __name__ == '__main__':
unittest.main()
### Output
PS D:\d_02_study\01_git> cd d:/d_02_study/01_git/papers/system/02automation
PS D:\d_02_study\01_git\papers\system\02automation> & C:/Users/TDH/AppData/Local/Programs/Python/Python310-32/python.exe d:/d_02_study/01_git/papers/system/02automation/demo.py
-----setup---class-----
用例test_password1_not_password2 (__main__.RegisterTest)开始执行...
用例test_password1_not_password2 (__main__.RegisterTest)执行结束...
.用例test_register_success (__main__.RegisterTest)开始执行...
用例test_register_success (__main__.RegisterTest)执行结束...
.用例test_username_exist (__main__.RegisterTest)开始执行...
用例test_username_exist (__main__.RegisterTest)执行结束...
.用例test_username_isnull (__main__.RegisterTest)开始执行...
用例test_username_isnull (__main__.RegisterTest)执行结束...
.用例test_username_lt18 (__main__.RegisterTest)开始执行...
用例test_username_lt18 (__main__.RegisterTest)执行结束...
.-----teardown---class-----
----------------------------------------------------------------------
Ran 5 tests in 0.004s
OK
PS D:\d_02_study\01_git\papers\system\02automation>
TestSuit测试套件
unittest.TestSuit()
类用来表示一个测试用例集,把需要执行的用例类或模块集合在一起。
常用的方法:
- unittest.TestSuit()
addTest()
:添加单个测试用例方法addTest([...])
:添加多个测试用例方法,方法名存在一个列表
- unittest.TestLoader()
loadTestsFromTestCase(测试类名)
:添加一个测试类loadTestsFromMdule(模块名)
:添加一个模块discover(测试用例所在的目录)
:指定目录去加载,会自动寻找这个目录下所有符合命名规则的测试用例
代码示例:
'''
以下三个文件必须在同一文件夹下:
demo.py
test_demo.py
run_test.py
'''
import os
import unittest
import test_demo
# 第一步,创建一个测试套件
suit = unittest.TestSuite()
# 第二步,将测试用例加载到测试套件中
# # 方式一,添加单条测试用例
# case = test_demo.RegisterTest('test_register_success')
# '''
# 创建一个用例对象。
# 注意:通过用例类去创建测试用例对象的时候,需要传入用例的方法名(字符串类型)
# 这里不是像调用普通类中的方法那样通过类名.方法名调用,可以理解为unittest框架的特殊之处
# '''
# suit.addTest(case) # 添加用例到测试套件中
# # 方式二:添加多条用例
# case1 = test_demo.RegisterTest('test_username_exist')
# case2 = test_demo.RegisterTest('test_username_isnull')
# suit.addTest([case1, case2]) # 添加用例到测试套件中。注意这里使用的是suit.addTest()方法而不是suit.addTests()方法
# # 方式三:添加一个测试用例集
# loader = unittest.TestLoader() # 创建一个加载对象
# suit.addTest(loader.loadFromTestCase(test_demo.RegisterTest)) # 通过加载对象从测试类中加载用例到测试套件中
# '''
# 通产我们使用方式4、5比较多,可以根据实际情况来运用。
# 其中方式5还可以自定义匹配规则,默认是会寻找目录下的test*.py文件,即所有以test开头命名的py文件。
# '''
# # 方式四:添加一个模块(其实就是一个后缀名为.py文件,这里就是test_demo.py文件)
# loader = unittest.TestLoader() # 创建一个加载对象
# suit.addTest(loader.loadTestsFromModule(test_demo)) # 通过加载对象从模块中加载测试用例到测试套件中
# 方式五:指定测试用例的所在目录路径,进行加载
loader = unittest.TestLoader() # 创建一个加载对象
case_path = os.path.dirname(os.path.abspath(__file__)) # 文件路径
# print('用例所在的目录路径为:', case_path)
# suit.addTest(loader.discover(case_path)) # 通过加载对象从用例所在目录加载测试用例到测试套件
suit.addTest(loader.discover(start_dir=case_path, pattern='test_demo*.py')) # 两个参数:路径和匹配规则
TestRunner执行用例
testRunner
用来执行用例,并且可以生成相应的测试报告。测试报告有两种形式:一种是 text文本
;一种是 html格式
。
html格式是 HTMLTestRunner
插件辅助生成的,是Python标准库的unittest框架的一个拓展,可以生成一个清晰直观的html测试报告。使用的前提就是需要下载 HTMLTestRunner.py
,下载完成后放在python安装目录下的scripts目录下即可。
text文本相对于html来说过于简陋,与输出控制台没有什么区别,也几乎不适用。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上软件测试知识点,真正体系化!
的一个拓展,可以生成一个清晰直观的html测试报告。使用的前提就是需要下载 HTMLTestRunner.py
,下载完成后放在python安装目录下的scripts目录下即可。
text文本相对于html来说过于简陋,与输出控制台没有什么区别,也几乎不适用。
[外链图片转存中…(img-QTT8Q3Ld-1719240210739)]
[外链图片转存中…(img-q3jCKSUp-1719240210740)]
[外链图片转存中…(img-NzRcvVRM-1719240210740)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上软件测试知识点,真正体系化!