unittest是Python单元测试框架,主要分为:
测试用例TestCase:一个完整的测试流程
测试套件TestSuite:多个测试用例集合在一起
执行/结果呈现TextTestRunner:用例运行和结果呈现,结果呈现常用HtmlTestRunner
前置后置Fixture:测试用例环境的搭建和销毁
一句话概括为:首先是要写好TestCase,然后由TestLoader加载TestCase到TestSuite,然后由TextTestRunner来运行TestSuite,运行的结果保存在TextTestResult中,整个过程集成在unittest.main模块中。
编写测试用例——收集用例——执行用例——生成报告
以下以简单登录用例进行测试。测试用例方法如下代码:
def test_login(username=None, password=None):
if username != None and password != None:
if username == 'python' and password == 'unittest':
return {"code": 0, "msg": "登录成功"}
else:
return {"code": 1, "msg": "账号或密码不正确"}
else:
return {"code": 1, "msg": "所有的参数不能为空"}
1.测试用例:TestCase
1.导入unittest模块
2.创建个测试类,并继承unittest.TestCase( )
3.定义测试方法,方法名必须以test_开头
import unittest
from myselfstudy.study_20210413 import test_login
class TestLogin(unittest.TestCase):
def test_login_1(self):
res = test_login("python27", "lemonban")
yuqi = {"code": 0, "msg": "登录成功"}
self.assertEqual(res, yuqi)
2.测试套件:TestSuite
2.1常用测试套件:unittest.TestLoader().discover()
unittest.TestLoader().discover(搜索目录),默认搜索test*.py文件中的测试用例
suit=unittest.TestLoader().discover(r"搜索目录")
print(type(suit))
print(suit)
输出结果为:搜索目录所有test*.py文件中的测试用例,此方法较常用
2.2不常用:unittest.TestSuite()
#1.实例化测试套件TestSuite
if __name__ == '__main__':
suit = unittest.TestSuite()
# 添加1个用例
suit.addTest(TestLogin("test_login_1"))
# 添加多个用例
suit.addTests([TestLogin("test_login_2"),TestLogin("test_login_3")])
print(suit)
执行输出为:3个测试用例
3执行/结果呈现:TextTestRunner/HtmlTestRunner/BeautifulReport
TextTestRunner不常用,不做讲解
3.1HtmlTestRunner
#运行测试用例结果输出Html
from HTMLTestRunner import HTMLTestRunner
#创建一个html文件,以写的模式打开,支持中文
with open("test_result.html","wb") as fs:
runner=HTMLTestRunner(fs,verbosity=1,title="unittest单元测试学习测试报告",description="第一份测试报告")
runner.run(suit)
执行后选择浏览器打开test_result.html文件如下:
如需修改test_result.html样式,需要修改HTMLTestRunner原文件,小白不建议随意修改。
3.2BeautifulReport
安装方法:pip install BeautifulReport
也可使用Pycharm安装Python第三方库,参考链接https://blog.csdn.net/qiannianguji01/article/details/50397046
from BeautifulReport import BeautifulReport
br = BeautifulReport(suit)
br.report("unittest单元测试报告","BeautifulReport.html")
执行后选择浏览器打开BeautifulReport.html文件如下:
4.前置后置:Fixture
测试用例环境的搭建和销毁,使用方式分类
测试方法为维度
setUp( ):单个用例执行前执行该方法
tearDown( ):单个用例执行之后执行该方法
以测试类为维度
setUpClass( ):类前执行
tearDownClass( ):类后(最后一个用例后)执行
1、学过unittest的都知道setup和teardown。前置和后置的意思。(在每个用例前后执行一次。)
举例:
import unittest
from myselfstudy.study_20210413 import test_login
class TestLogin(unittest.TestCase):
def setUp(self):
print("----------------------单个用例开始执行-------------------------")
def tearDown(self):
print("----------------------单个用例结束执行-------------------------"+"\n"+"\n")
def test_login_1(self):
res = test_login("python27", "lemonban")
yuqi = {"code": 0, "msg": "登录成功"}
self.assertEqual(res, yuqi)
print("test_login_1")
执行结果:
比之用的少一点的还有setupclass和teardownclass,需要配合@classmethod装饰器一起使用。(在所有用例前后总共各执行一次。)
import unittest
from myselfstudy.study_20210413 import test_login
class TestLogin(unittest.TestCase):
@classmethod
def setUpClass(cls):
print("----------------------开始执行登录用例-------------------------")
@classmethod
def tearDownClass(cls):
print("----------------------结束执行登录用例-------------------------")
def test_login_1(self):
res = test_login("python27", "lemonban")
yuqi = {"code": 0, "msg": "登录成功"}
self.assertEqual(res, yuqi)
print("test_login_1")
def test_login_2(self):
res = test_login("python", "lemonban")
self.assertEqual(res, {"code": 1, "msg": "账号或密码不正确"})
print("test_login_2")
执行结果:
2、pytest也有类似的语法。并且种类更多。按照用例运行级别可以分为以下几类:
*模块级(setup_module/teardown_module):开始于模块始末,作用于全局(总用各执行一次。)
*函数级(setup_function/teardown_function):仅对函数用例生效。(即不在类中。每个函数执行一次)
*类级(setup_class/teardown_class):只在类中前后运行一次。(在类中)
*方法级(setup_method/teardown_method):开始于方法始末(在类中。每个方法执行一次)
*类里面的(setup/teardown):运行在调用方法的前后(每个方法执行一次)
注:类里面按优先级排序的话:setup_class > setup_method > setup >用例> teardown > teardown_method > teardown_class(即执行顺序)
6.ddt数据驱动测试-参数化
1.导入ddt
2.类名前@ddt.ddt
3.测试函数前@ddt.date(*列表),在测试函数中定义一个参数来接收date数据
import unittest
from study_20210413 import test_login
import ddt
dates = [{"user": "python", "password": "unittest", "check": {"code": 0, "msg": "登录成功"}},
{"user": "python111", "password": "unittest", "check": {"code": 1, "msg": "账号或密码不正确"}},
{"user": "python", "password": "unittest111", "check": {"code": 1, "msg": "账号或密码不正确"}},
{"user": None, "password": "unittest", "check": {"code": 1, "msg": "所有的参数不能为空"}},
{"user": "python", "password": None, "check": {"code": 1, "msg": "所有的参数不能为空"}}]
@ddt.ddt
class TestLogin(unittest.TestCase):
@ddt.data(*dates)
def test_login(self,case):
res = test_login(case["user"], case["password"])
self.assertEqual(res, case["check"], "PASS")
@classmethod
def setUpClass(cls):
print("----------------------开始执行登录用例-------------------------")
@classmethod
def tearDownClass(cls):
print("----------------------结束执行登录用例-------------------------")
def setUp(self):
print("-----单个用例开始执行-----")
def tearDown(self):
print("-----单个用例结束执行-----")
执行结果会执行五条用例: