unittest测试框架
前置: 下面测试的代码
def Login(username=None, pwd=None):
if username is not None and pwd is not None:
if username == "python666" and pwd == "python":
return {"code": 0, "msg": "登录成功"}
else:
return {"code": 1, "msg": "账号或者密码不正确"}
else:
return {"code": 1, "msg": "所有参数不能为空"}
编写简单测试用例
- 测试模块(.py)文件以test_开头
- 导入unittest,并且测试类继承unittest.TestCase
- 测试类里面的函数命名以test_开头,一个函数表示一个测试用例
import unittest
from login_func import Login
class TestLogin(unittest.TestCase):
def test_login_success(self):
act_result = Login("python666", "python")
if act_result["code"] == 0 and act_result["msg"] == "登录成功":
print("测试用例通过")
else:
print("测试用例不通过")
def test_login_error(self):
act_result = Login("python666", "python11")
if act_result["code"] == 1 and act_result["msg"] == "账号或者密码不正确":
print("测试用例通过")
else:
print("测试用例不通过")
断言
注: 断言在TestCase类中
为什么用断言?
答: 以上实例代码方式判断测试用例是否通过,需要测试人员手动查看执行输出才能判断该测试用例是否通过,未通过的标志不明显,断言判断方式测试未通过标志明显,容易分辨
import unittest
class TestAssert(unittest.TestCase):
# 期望相等
def test_assert_equal(self):
self.assertEqual("hello", "world")
def test_assert_not_equal(self):
self.assertNotEqual("hello", "world")
# 期望true
def test_assert_true(self):
self.assertTrue(False)
def test_assert_false(self):
self.assertFalse(False)
# 期望两者内存地址相同(是同一个)
def test_assert_is(self):
a = 10
b = 20
self.assertIs(a, b)
def test_assert_is_not(self):
a = 10
b = 20
self.assertIsNot(a, b)
# 期望None
def test_assert_is_none(self):
self.assertIsNone(None)
def test_assert_is_not_node(self):
self.assertIsNotNone(None)
# 期望a在b里面 使用字符串/字典/列表/元组
def test_assert_in(self):
a = "hello"
b = "hello hello"
self.assertIn(a, b)
def test_assert_not_in(self):
a = "hh"
b = "aaaaa"
self.assertNotIn(a, b)
# 期望a是某类型(比如int)
def test_assert_is_instance(self):
a = 10
self.assertIsInstance(a, int)
def test_assert_not_is_instance(self):
a = 10
self.assertNotIsInstance(a, int)
修改示例代码
class TestLogin(unittest.TestCase):
def test_login_success(self):
act_result = Login("python666", "python")
# if act_result["code"] == 0 and act_result["msg"] == "登录成功":
# print("测试用例通过")
# else:
# print("测试用例不通过")
'''
以上方式判断测试用例是否通过,需要测试人员手动查看执行输出才能判断该测试用例是否通过,未通过的标志不明显
断言判断方式测试未通过标志明显,容易分辨
'''
expect_result = {"code": 0, "msg": "登录成功"}
self.assertEqual(expect_result, act_result, "测试不通过")
fixture(测试环境的创建和销毁)
- 测试用例级别夹具: steup()/teardown()
夹住每一个测试用例
steup
测试用例
teardown
- 测试类级别夹具: setUpClass()/tearDownClass
夹住一个测试类
setUpClass
测试类
tearDownClass
注意: 在方法名上加上@classmethod setUpClass()/tearDownClass是类方法 - 可以通过实例属性或者类属性在前置中进行数据传递
注意: steup()/teardown()或者setUpClass()/tearDownClass不用成对出现
import unittest
from login_func import Login
class TestLogin(unittest.TestCase):
@classmethod
def setUpClass(cls):
print("准备工作")
cls.a = "类属性-数据"
@classmethod
def tearDownClass(cls):
print("清理工作")
def setUp(self):
print("准备工作")
self.b = "实例属性-数据"
def tearDown(self):
print("清理工作")
def test_login_success(self):
act_result = Login("python666", "python")
expect_result = {"code": 0, "msg": "登录成功"}
self.assertEqual(expect_result, act_result, "测试不通过")
def test_login_error(self):
act_result = Login("python666", "python11")
expect_result = {"code": 1, "msg": "账号或者密码不正确"}
self.assertEqual(expect_result, act_result, "测试不通过")
TestSuite/TestLoader
TestSuite类: 测试用例的集合(不同测试模块的测试用例集合)
TestLoader类: 收集测试用例
常用方式: unittest.TestLoader().discover(搜索目录) # 默认在搜索目录下的test*.py中搜索测试用例
import unittest
load = unittest.TestLoader()
# suite:TestSuite
suite = load.discover(r"D:\PythonCode\pythonProject\unittestStudy")`
for e in suite:
print(e)
html报告
下载第三方库: unittestreport
pip install unittestreport -i https://mirrors.aliyun.com/pypi/simple
使用案例:
import unittest
from unittestreport import TestRunner
load = unittest.TestLoader()
suite = load.discover(r"D:\PythonCode\pythonProject\unittestStudy")
runner = TestRunner(suite)
runner.run()
使用文档连接:
link