1.Pytest介绍
pytest是python的一种单元测试框架,与python自带的unittest测试框架类似,但更简洁并高效。
官方网站优点简介:
- 非常容易上手,入门简单,文档丰富,文档中有很多实例可以参考
- 能够支持简单的单元测试和复杂的功能测试
- 支持参数化
- 执行测试过程中可以将某些测试跳过,或者对某些预期失败的case标记成失败
- 支持重复执行失败的case
- 支持运行由nose, unittest编写的测试case
- 具有很多第三方插件,并且可以自定义扩展
- 方便的和持续集成工具集成
2. 安装pytest
下面两种安装方式二选一即可。
1 pip install -U pytest 2 easy_install -U pytest
安装完成查看安装的版本,若提示pyttest函数不存在,只需要将python目录下的Scripts目录配置到环境变量中即可解决问题
pytest --version
3. 执行用例
-
简单执行单个用例
1 # content of test_sample.py 2 3 4 def func(x): 5 return x + 1 6 7 8 def test_func(): 9 assert func(3) == 5
到该模块的目录下,输入pytest(模块的名字与执行函数必须是test开头或_test结尾,否则不会被执行,切记!),见该代码执行的结果,见截图:
-
执行class中的测试用例
1 # content of test_class.py 2 3 class TestClass: 4 def test_one(self): 5 x = "this" 6 assert 'h' in x 7 8 def test_two(self): 9 x = "hello" 10 assert hasattr(x, 'check')
-
执行目录下指定用例
在测试中,有N个测试用例,但是我们只是想执行其中的一个用例,其它的用例不想执行,那怎么办呢?使用下面命令就可以执行单个用例
1 # $pytest -q /path/用例名 2 pytest -q test_case2.py
4.编写测试样例与规范
-
python命名规范
1 一 包名、模块名、局部变量名、函数名 2 全小写+下划线式驼峰 3 example: this_is_var 4 二 全局变量 5 全大写+下划线式驼峰 6 example: GLOBAL_VAR 7 三 类名 8 首字母大写式驼峰,否则会报错提示语法错误 9 example: ClassName()
-
测试用例规则
1 - 测试文件以test_开头(以_test结尾也行) 2 - 测试类以Test开头,并且不能带有__init__方法 3 - 测试函数以test_开头 4 - 断言使用基本的assert即可
5. pytest高级进阶——Fixture
-
何为fixture
fixture是pytest的一个闪光点,fixture是pytest特有的功能,它用pytest.fixture标识,定义在函数前面。在你编写测试函数的时候,你可以将此函数名称做为传入参数,pytest将会以依赖注入方式,将该函数的返回值作为测试函数的传入参数。
fixture有明确的名字,在其他函数,模块,类或整个工程调用它时会被激活。
fixture是基于模块来执行的,每个fixture的名字就可以触发一个fixture的函数,它自身也可以调用其他的fixture。
fixture主要的目的是为了提供一种可靠和可重复性的手段去运行那些最基本的测试内容。比如在测试网站的功能时,每个测试用例都要登录和退出,利用fixture就可以只做一次,否则每个测试用例都要做这两步也是冗余。
-
Fixture入门实例
把一个函数定义为Fixture很简单,只能在函数声明之前加上“@pytest.fixture”。其他函数要来调用这个Fixture,只用把它当做一个输入的参数即可。
import pytest @pytest.fixture() def setup(): print(' setup') def test_1(setup): print('test_1()') def test_2(setup): print('test_2()') def test_3(): print("test3()")
下面是运行结果,test_1和test_2运行之前都调用了setup,test_3没有参数没有传fixture标识的函数所以不会调用setup。默认情况下,fixture是每个测试用例如果调用了该fixture就会执行一次的。
-
使用autos调用fixture
fixture decorator一个optional的参数是autouse, 默认设置为False。
当默认为False,就可以选择用上面方式来调用fixture标识的函数。
当设置为True时,在一个session内的所有的test都会自动调用这个fixture。
权限大,责任也大,所以用该功能时也要谨慎小心。
import time import pytest @pytest.fixture(scope="module", autouse=True) def mod_header(request): print(' -----------------') print('module : %s' % request.module.__name__) print('-----------------') @pytest.fixture(scope="function", autouse=True) def func_header(request): print(' -----------------') print('function : %s' % request.function.__name__) print('time : %s' % time.asctime()) print('-----------------') def test_one(): print('in test_one()') def test_two(): print('in test_two()')
从下面的运行结果,可以看到mod_header在该module内运行了一次,而func_header对于每个test都运行了一次,总共两次。该方式如果用得好,还是可以使代码更为简洁。
但是对于不熟悉自己组的测试框架的人来说,在pytest里面去新写测试用例,需要去了解是否已有一些fixture是module或者function级别的需要注意。
fixture scope
- function:每个test都运行,默认是function的scope
- module:每个module的所有test只运行一次
- class:每个class的所有test只运行一次
- session:每个session只运行一次
-
fixture 返回值
在上面的例子中,fixture返回值都是默认None,我们可以选择让fixture返回我们需要的东西。如果你的fixture需要配置一些数据,读个文件,或者连接一个数据库,那么你可以让fixture返回这些数据或资源。
如何带参数
fixture还可以带参数,可以把参数赋值给params,默认是None。对于param里面的每个值,fixture都会去调用执行一次,就像执行for循环一样把params里的值遍历一次。
import pytest @pytest.fixture(params=[1, 2, 3]) def test_data(request): return request.param def test_not_2(test_data): print('test_data: %s' % test_data) assert test_data != 2
可以看到test_not_2里面把用test_data里面定义的3个参数遍历了一次。
6. 使用IDEL执行测试用例
-
使用OS创建一个子shell执行测试用例
import os # 在当前进程中打开一个子shell(子进程)来执行系统命令。 cmd = os.system(r"pytest -s -v D:UserssangforAppDataLocalProgramsPythonPython37Scripts estcase") print(cmd)
运行结果如下
-
使用pytest.main()运行测试用例
import pytest # 注意()中使用list,多个参数用","隔开,path路径前用r
pytest.main(["-s", f"{case_path}\TestCase", "--alluredir=report"])
运行结果如下