单元测试概述
对软件中的最小可测试单元进行检查和验证。说的直白一点,就是用于判断某个特定条件(或者场景)下某个特定函数的行为。目前来看某些公司都不会做,做也是开发做的比较多一些。关于概念这块,大家可以搜一下。
单元测试我们要知道,我们的程序预期的输入和输出,预期结果一定要针对需求、设计逻辑去写,不能简单的了为了程序的实现去写,如果单元测试用例都是错的,做这个单元测试其实也就没有意义了。
单元测试覆盖率
说到单元测试就不得不提覆盖率了。 代码覆盖率是用来度量自动化测试和手工测试是否全面的指标之一。 主要有一下几个类型:
语句覆盖
保证被测的方法每一行代码都会被执行一遍。 运行测试用例的时候被击中的代码行即称为被覆盖的语句
def test(a, b, x):
if(a > 1 and b ==0):
x = x / a
if(a == 2 or x >1):
x = x + 1
rerurn x
根据上面的代码简单举例 测试用例
a=3,b=o,x=4
这一条用例其实就实现了语句覆盖,它让每一行代码都执行了一遍,但是这里有一个bug,如果第一个if中的and写成了or,仅凭这一条用例是测不出来的。我们这里也仅仅是举这个例子来理解一下语句覆盖,行覆盖是一个最基础的覆盖方式,也是最薄弱的,不能完全依赖行覆盖。
判断覆盖
运行测试用例的过程中被击中的判断语句
用例 | a b x | (a>1)&&(b==0) | a==2||x>1 |
---|
CASE1 | 2 0 3 | TRUE | TRUE | CASE2 | 1 0 1 | FALSE | FALSE | CASE3 | 3 0 3 | TRUE | FALSE | CASE4 | 2 1 1 | FALSE | TRUE |
我们还用上面那一段代码来举例,两个判断语句,我们要分别判断每一个判定条件分别为true和false的情况。这里其实也有bug,如果第二个if判断逻辑修x>1改成x<1,只依赖上面的用例,也是测不出来的。
条件覆盖
条件覆盖和判断覆盖是类似的,判断覆盖关注的是整个判断语句的true或false,条件覆盖关注的是某个判断条件的true或false。
用例 | a>1 | b==0 |
---|
CASE1 | TRUE | TRUE | CASE2 | TRUE | FALSE | CASE3 | FALSE | TRUE | CASE4 | FALSE | FALSE |
我们只用了第一个判断条件举例,虽然测试的很全面,但是我们的用例也成倍的增加了。
路径覆盖
路径覆盖就是覆盖所有可能执行的路径 不管判断语句有多少,都要覆盖他可能要走的一个路径,根据不同的路径设计不同的用例。
unittest框架介绍
单元测试其实有很多框架,比如Python的unittest、Java的Junit、c++的CppUnit、.net的Nunit。
unittest是Python内置的标准类库。 Nose是对unittest的扩展 unittest.mock是用来测试Python的库。是一个标准库,出现在python3.3版本以后 pytest 现在比较主流,做接口自动化用的比较多。 …… 具体详细的介绍可以去官网看下 官网: https://docs.python.org/3/library/unittest.html#unittest.TextTestRunner 是python自带的单元测试框架,常用在单元测试,在自动化测试中提供用例组织和执行,提供了丰富的断言方法,验证函数等功能,也可以结合HTMLTestRunner生成html报告 主要以下几部分组成: test fixture:测试的装置,测试前和测试后要完成那些操作 test case:测试用例 test suite:组装测试用例 test runner:批量的执行用例 官网上提供了一个demo 我们可以放到pycharm中看一下。
unittest编写与规范
- 首先测试模块要先导入import unittest
- 从上面的截图我们也可以看出来,测试类继承了unittest.TestCase,测试类必须继承unittest.TestCase类,测试方法也必须以“test_”开头,类名没有强制要以Test开头,但是我们最好还是以Test开头。
- 我们可以整体运行,也可以点击绿色的小箭头,单独运行某一个方法。
- 我们还可以添加一些装置,比如setUp用来测试准备环境,在所有case执行之前运行,我们可以用setUpClass();tearDown用来清理环境,在执行case之后执行,我们可以用tearDown(),比如数据库连接和销毁,登录获取token和退出。
- 如果我们想要跳过某些方法,还可以用@unittest.skip
def setUp(self):
print("执行方法前调用")
def tearDown(self):
print("执行方法后调用")
会在每个方法执行前和方法后都调用一次,如果是setUpClass则是在每个类条用前执行,tearDown是每个类调用后执行
断言
unittest断言的方法有很多,比较常用的有assertEqual、assertIn、assertTrue。 基本的断言方法提供了测试结果是True还是False。所有的断言方法都有一个msg参数,如果指定了msg参数的值,则将该信息作为信息返回。
执行测试用例
1.执行全部
if __name__ == '__main__':
unittest.main()
2.还有一种是加入到容器中执行,批量执行测试方法
suite=unittest.TestSuite() suite.addTest(TestMethod(“test_01”)) unittest.TextTestRunner().run(suite)
3.批量测试类,创建类的测试套件有所不同
suite = unittest.TestLoader().loadTestsFromTestCase(TestStringMethods)
suite_list = unittest.TestSuite([suite])
unittest.TextTestRunner(verbosity=2).run(suite_list)
4.匹配某个目录下所有以test开头的py文件,执行这些文件的所有用例
test_dir = "/opt/data/test/unitcase"
discover = unittest.defaultTestLoader.discover(test_dir, pattern="test*.py")
discover可以一次调用多个脚本 test_dir用例的目录 pattern名称匹配规则 整个过程如下图 整个过程是集中在unittest.main模块中 1.写好用例,可以是多个 2.由TestLoader加载到TestSuite 3.TextTestRunner运行suite,suite可以有多个 4.执行结果保存到result中 关于测试结果我们还可以结合第三方的插件,生成一个可视化的报告,可以参考一下pytest
|