前言
单元测试是一种提高软件质量非常有效的方法,但很重要的是我们要去实践和体会。在现代的敏捷软件开发方法论中,都非常强调单元测试的重要性。为什么呢?因为对于多次的迭代开发,我们需要通过测试来看是否新的迭代对于原有的功能是否有影响。还有就是,我们可能需要做重构,通过单元测试我们能发现重构后的代码是否对原有的功能进行了改变,而这是我们做重构后所不希望看到的。单元测试在现实实践中存在的一个不可忽视的问题是:测试用例的维护成本比较的高。往往对其维护的工作量并不比被测代码的开发量小,对于这一点我们需要有足够的认识。
单元测试框架
python常见的单元测试框架:
- unittest是Python内置的标准类库。
- pytest是Python最流程的单测框架之一。
- …
区别:
- unittest提供了assertEqual、assertIn、assertTrue、assertFalse
pytest直接使用assert 表达式 - unittest使用HTMLTestRunnerNew库。
pytest有pytest-HTML、allure插件。 - unittest需依赖ddt库,
pytest直接使用@pytest.mark.parametrize装饰器。 - unittest默认执行全部用例,也可以通过加载testsuit,执行部分用例。
pytest可以通过@pytest.mark来标记类和方法,pytest.main加入参数("-m")可以只运行标记的类和方法。
本文主要介绍unittest的使用:
unittest框架介绍
- TestCase(测试用例): 所有测试用例的基类,它是软件 测试中最基本的组成单元。
一个test case就是一个测试用例,是一个完整的测试流程,包括测试前环境的搭建setUp,执行测试代码(run),以及测试后环境的还原(tearDown)。测试用例是一个完整的测试单元,可以对某一问题进行验证。 - TestSuite(测试套件):多个测试用例test case集合就是TestSuite,TestSuite可以嵌套TestSuite
- TestLoder:是用来加载TestCase到TestSuite中,其中有几个loadTestsFrom_()方法,就是从各个地方寻找TestCase,创建他们的实例,然后add到TestSuite中,再返回一个TestSuite实例
- TextTestRunner:是来执行测试用例的,其中的run(test)会执行TestSuite/TestCase中的run(result)方法。
- TextTestResult:测试结果会保存到TextTestResult实例中,包括运行了多少用例,成功与失败多少等信息
- TestFixture:又叫测试脚手,测试代码的运行环境,指测试准备前和执行后要做的工作,包括setUp和tearDown方法
核心工作原理
安装
在单元测试中需要mock数据,所以需要安装mock库
pip install mock
检测代码是否符合Pep8编码规范
pip install flake8
命名规范
- 所有的单测文件名都需要满足test_.py格式或_test.py格式。
- 在单测文件中,可以包含test_开头的函数,也可以包含Test开头的类。
- 在单测类中,可以包含一个或多个test_开头的函数。
此时,在执行pytest命令时,会自动从当前目录及子目录中寻找符合上述约束的测试函数来执行。
测试
- 简单小测试:
setUp() 和 tearDown() 两个方法(其实是重写了TestCase的这两个方法),这两个方法在每个测试方法执行前以及执行后执行一次,setUp用来为测试准备环境,tearDown用来清理环境,已备之后的测试。
直接上代码:
tools.py
# -*- coding: utf-8 -*-
# @Time : 2019/3/23 14:56
# @File : tools.py
class Tools(object):
def __init__(self):
pass
def test_1(self):
result = {
"name": 'test',
"phone": 123
}
return result
def test_2(self):
response = self.test_1()
return response
test_tools.py
# -*- coding: utf-8 -*-
# @Time : 2019/3/23 14:56
# @File : test_tools.py
from unittest import TestCase
from mock import MagicMock
from tools import Tools
class TestTools(TestCase):
def setUp(self):
# 测试前需执行的操作
self.tools = Tools()
def tearDown(self):
pass
def test_check_cmd_response(self):
mock_data = {
"name": "james",
"phone": 23
}
Tools.test_1 = MagicMock(return_value=mock_data)
result = self.tools.test_2()
self.assertEqual(result, mock_data)
然后执行命令:
pytest test_tools.py
结果
然后使用flake8检测一下代码是否符合pep8编码规范。提示我结尾少一行,加上之后再试,?了。
结束
unittest框架提供的功能还有
- 通过skip,skipIf,skipUnless装饰器跳过某个case,或者用TestCase.skipTest方法。
- 参数中加stream,可以将报告输出到文件:可以用TextTestRunner输出txt报告,以及可以用HTMLTestRunner输出html报告。
等等。
其他功能还在研究中,敬请期待!