一、命名原则
- 测试用例文件名必须以
test_*.py
和*_test.py
开头或结尾 - 测试类必须以Test开头,并且不能有init方法,测试方法必须以
test_
开头的函数 - 没有类,那么以函数为单位的函数名必须以
test_
开头 - 文件夹(包名)名可以随意命名
二、命令参数
使用下面的参数可以让测试在第 1(N) 次测试失败后停止:
pytest ‐x # 第 1 次测试失败后停止测试
pytest ‐‐maxfail=num # 第 2 次测试失败后停止测试
if __name__ == '__main__': pytest.main(['-s', '-x', 'test_02.py'])
-q, --quiet 极简结果显示
-V 可以输出用例更加详细的执行信息,比如用例所在的文件及用例名称等
-s 输出用例中调试信息,如print的打印信息
-v --verbose 详细结果
--junit-xml=path 输出xml格式文件,与jenkins做集成时使用
--result-log=path 将最后的结果保存到本地文件中
三、指定测试
1、在模块中运行测试
pytest test_mod.py
2、在目录中运行测试
pytest testing/
3、按关键字表达式运行测试
pytest -k "01" test_02.py
会执行 test_02.py 下 test_01 的方法,不运行02
4、通过节点 id 来进行测试
参数化的类名、函数名和参数,用::
分隔。
规则 pytest 目录 / py文件 :: 类名 : 方法名
例子 pytest testcase/test_02.py::TestDemo02:test_01
5、通过标记来执行 (只能运行有相应标识的测试用例)
- pytest -m "tag01 or tag02" # 运行tag01和tag02的标记用例
这种方式会运行所有通过装饰器 @pytest.mark.mark
进行装饰的测试用例
@pytest.mark.tag01 def test_01(self): assert self.func(3) == 4 @pytest.mark.tag02 def test_02(self): assert self.func(3) == 4
- pytest -m tag # 执行test_01.py内所有@pytest.mark.tag的标记用例
四、pytest fixture
- 模块形式----使用setup_module/teardown_module
- 函数形式----使用setup_function/teardown_function
- 类形式----使用setup_class/teardown_class
- 方法形式---使用setup_method/teardown_method
-
fixture scope的范围参数
@pytest.fixture(scope='module')来定义框架,scope的参数有以下几种
function 每一个用例都执行
class 每个类执行
module 每个模块执行(函数形式的用例)
session 每个session只运行一次,在自动化测试时,登录步骤可以使用该session
-
调用fixture的三种方法
2.1函数或类里面方法直接传fixture的函数参数名称
from __future__ import print_function import pytest @pytest.fixture(scope='module') #范围是module def resource_a_setup(request): #前置器 print('\n resources_a_setup()') def resource_a_teardown(): #后置器 print('\n resources_a_teardown()') request.addfinalizer(resource_a_teardown) def test_1(resource_a_setup): print('test_1()') def test_2(): print('\ntest_2()') def test_3(resource_a_setup): print('\ntest_3()')
2.2使用装饰器@pytest.mark.usefixtures()修饰需要运行的用例
@pytest.fixture() def test1(): #套件名test1 print('\n开始执行function') @pytest.mark.usefixtures('test1') #方法使用套件test1 def test_a(): print('---用例a执行---') @pytest.mark.usefixtures('test1') #类使用套件test1 class TestCase: def test_b(self): print('---用例b执行---') def test_c(self): print('---用例c执行---') if __name__ == '__main__': pytest.main(['-s', 'test_fixture1.py'])
2.3叠加usefixtures
如果一个方法或者一个class用例想要同时调用多个fixture,可以使用@pytest.mark.usefixture()进行叠加。注意叠加顺序,先执行的放底层,后执行的放上层
@pytest.fixture() def test1(): #套件test1 print('\n开始执行function1') @pytest.fixture() def test2(): #套件test2 print('\n开始执行function2') @pytest.mark.usefixtures('test1') @pytest.mark.usefixtures('test2') def test_a(): #方法使用套件test1和test2 print('---用例a执行---') #或 @pytest.mark.usefixtures('test2') @pytest.mark.usefixtures('test1') class Testcase: #类使用套件test1和test2 def test_c(self): print('---用例c执行---') if __name__ == '__main__': pytest.main(['-s', 'test_fixture1.py'])
3.fixture和usefixture区别
如果fixture有返回值,那么usefixture就无法获取到返回值
五、conftest全局处理器
conftest.py作用全局,不可跨模块调用,作用范围只能在该层级以及以下目录生效
六、参数化
@pytest.mark.parametrize(args_name,args_value)
args_name:参数名
args_value:参数值(支持列表、元组、字典列表、字典元组)有多少值用例就执行多少次
class Testapi @pytest.mark.parametrize('name,arg',[['赵四','24'],['张三','25']]) def test_01(self,name,arg): print(name,arg) if __name__ == '__main__': pytest.main