(仅作为个人笔记,如有雷同,请联系删除。。)
1、支持参数化,支持case的skip和xfail处理,可以很好的和Jenkins集成,可以直接运行unittest的case
2、插件:pytest-selenium、pytest-html、pytest-allure-adaptor、pytest-rerunfailures、pytest-xdist、pytest-ordering、pytest-timeout
3、支持的report格式:html、allure、xml
4、执行方式:
- 测试类主函数:
if __name__ == "__main__":
pytest.main("-s testxx.py") | pytest.main(['-s', '-q', 'test_xx.py'])
- 命令行:
pytest -sq test_xx.py
5、命名方式:
测试脚本:test.py | *_test.py
测试类名:TestXxx,无__init__方法
测试case:test_xxx
6、pytest控制执行:【-q:极简结果显示,-s:输出print的调试信息,-v:详细模式】
- 指定模块:pytest test_xx.py
- 指定目录:pytest ./abc/
- 指定case:pytest test_xx.py::TestAClass::test_01_abc
- 标记执行:pytest -m demo,运行所有被“@pytest.mark.demo”装饰的case
- 关键字表达式过滤执行:pytest -k "MyClass and not method",匹配文件名、类名、方法名,执行所有带“MyClass”的,不执行带“method”的
- 第n个case失败后,结束执行:
pytest -x:出现1个失败就结束执行
pytest --maxfail=2:出现2个失败就结束测试
7、多进程/分布式运行case:【并发,多个CPU或主机执行】
插件:pip install pytest-xdist
运行:pytest ./test_01.py -n NUM 【NUM:并发的进程数】
8、pytest重跑策略:
插件:pip install pytest-rerunfailures
运行:pytest ./test_01.py --reruns NUM 【NUM:重试次数】
9、setup和teardown:
- 模块级:setup_module() | teardown_module()
- 类级别:setup_class(self) | teardown_class(self)
- 函数级:setup() | teardown()
10、配置文件 - pytest.ini:放在测试目录下,命令行执行pytest时使用此配置。(配置好之后,进入当前目录,执行pytest命令即可开始运行)。配置mark标签也在这个文件中。
[pytest]
markers =
demo: a test demo marks # “:”之后是描述信息,可有可无
...
url = "www.baidu.com"
addops = -s -q -n 5 --reruns 2... # 空格分隔,可添加多个命令行参数,所有的参数均为插件包的参数
testpaths = ./testcase # 配置测试搜索的路径 | 需
python_files = test_*.py # 配置测试搜索的文件名称 | 向
python_classes = Test_* # 配置测试搜索的类名 | 上
python_functions = test_* # 配置测试搜索的方法名 | 兼容
# 匹配当前目录下testcase文件夹中的,test_*.py文件中的,Test_*类中的,test_*方法
11、配置mark标签:在pytest.ini文件中配置
使用:@pytest.mark.xxx
打标范围:测试case、测试类、模块文件[ import pytest,pytestmark=pytest.mark.xxx ]
执行:pytest -m "demo1 or demo2 and not demo3"
12、配置文件conftest.py:所有同目录测试文件执行前都会执行该文件。无需import,pytest自动识别,多个目录下可有多个此文件。
用途1:存放多个fixture工厂函数,被同目录的case引用。
用途2:给pytest添加参数[ 注册命令行参数 ]:
def pytest_addoption(parser): # 注册自定义参数cmdopt到配置对象
paeser.addoption("--cmdopt", action="store", defoult=None, help="my option: type1 or type2")
parser.addoption("--env", action="store", default="dev", help="env:表示测试环境,默认dev环境")
parser.addini('url', type=None, default="http://49.235.92.12:8200/", help='添加url访问地址参数')
@pytest.fixture()
def cmdopt(pytestconfig): # 从配置对象获取cmdopt的值
return pytestconfig.getoption('--cmdopt')
@pytest.fixture()
def env(request): # pytestconfig 实际上就是 request.config 的快捷方式,被称为“pytest 配置对象”
return request.config.getoption("--env")
@pytest.fixture()
def url(pytestconfig):
return pytestconfig.getini("url") # 获取pytest.ini配置文件中url参数的值
# 然后任何case中都可以调用cmdopt / env 获取传入命令行传入的值
13、pytest测试报告——html:
插件:pip install pytest-html
运行:pytest --html=xxx/report.html 【Jenkins插件:HTML Publisher】
pytest --junitxml=./log.xml 【生Junitxml格式的测试报告,方便CI集成】
14、pytest测试报告——allure:
插件:pip install pytest-allure-adaptor
运行:pytest --alluredir=./allure-results
注意:不需要allure命令转换测试报告,直接集成在Jenkins中,Jenkins插件:Allure Jenkins Plugins
—— 需要包含两个目录:
allure-results:存放测试结果数据
allure-report:存放转换后的测试报告
15、fixture修饰器:标记固定的工厂函数,在其他模块、类、函数调用它时会被优先执行
方法:fixture(scope="function", params=None, autouse=False, ids=None, name=None)
scope:被标记方法的作用域 [ function (默认)、class、module、session ]
params:(list类型)提供参数数据,供调用标记方法的函数使用
autouse:是否自动运行,默认为False不运行,设置为True自动运行
用法:
# 用法1:fixture修饰的函数,作为一个参数,传入另一个函数中,被优先执行
@pytest.fixture()
def before(): ...
def test_a(before): # ️ test_a方法传入了被fixture标识的函数,以变量的形式
...
# 用法2:作为一个函数,被测试类引用,被优先执行
@pytest.mark.usefixtures("before")
class TestAbc: # 作用于整个类,每个class的所有test只运行一次
def ...
# 用法3:设置为默认运行,在测试类/测试方法之前优先执行
@pytest.fixture(autouse=True)
def before(): ...
class Test_ABC: # before会自动优先于测试类运行
def ...
# 用法4:设置作用域为function,优先于每个case的setup运行
@pytest.fixture(scope='function',autouse=True) # 作用域设置为function,自动运行
def before(): ...
class Test_ABC:
def setup(self): ...
def test_a(self): # before会优先于每个case的setup自动运行
...
# 用法5:设置作用域为class,优先于测试类运行
@pytest.fixture(scope='class',autouse=True)
def before(): ...
class Test_ABC: # 优先于每个测试类,自动执行,每个测试类只一次
def ...
# 用法6:有返回值,在case中被调用执行[ params也可用于此 ]
@pytest.fixture(params=[1, 2, 3])
def need_data(request): # 传入参数request 系统封装参数
return request.param # 取列表中单个值,默认的取值方式
class Test_ABC:
def test_a(self, need_data): # params提供了3个只,case执行3次
assert need_data != 3
16、pytest跳过case:
方法:skipif(condition, reason=None):根据特定的条件,不执行标记的case
condition:跳过的条件
reason:跳过的原因
使用:@pytest.mark.skipif(condition=2>1, reason="跳过这个case")
17、pytest预期失败case:
方法:xfail(condition,reason=None,raises=None,run=True,strict=False):标记为预期失败case
condition:预期失败的条件
reason:原因
使用:@pytest.mark.xfail(2>1, reason="预期失败")
18、pytest参数化:
方法:parametrize(arg_names, arg_values)
arg_names:参数名, arg_values:参数值,list
使用:
@pytest.mark.parametrize("arg1", [3, 6])
def test_01(self, arg1):
@pytest.mark.parametrize("arg1, arg2", [(1, 2), (3, 4)])
def test_02(self, arg1, arg2):
19、pytest——pdb模式:
pytest --pdb:每次遇到失败都跳转到pdb
pytest -x --pdb:第一次失败就跳转pdb,结束case执行
pytest --pdb --maxfail=n:只有前n次失败跳转到pdb【前n次失败都会调用pdb】
20、pytest单元测试统计代码覆盖率:
插件:pip install pytest-cov 【pytest-cov会自动引入coverage.py:python推荐的覆盖率工具】
使用:pytest --cov=*/src --cov_report=html
--cov:指定要统计代码覆盖率的目录
--cov_report:当前路径才生成htmlcov/index.html
21、调整case的执行顺序:默认按字母顺序去执行的
插件:pip install pytest-ordering
使用:@pytest.mark.last:最后一个执行
@pytest.mark.run(order=n):第n个执行
22、pytest设置case限时:
插件:pip install pytest-timeout
使用:pytest --timeout=0.5
23、pytest + allure定制测试报告:import allure
@allure.feature("功能名称"):标记主要功能模块
@allure.story("子功能名称"):标记主功能模块下的分支功能
@allure.step("步骤细节"):标记功能模块下的具体步骤
@allure.attach(...): 附加文本、图片、网页
@allure.attach.file(...):同上
24、pytest可直接运行unittest的case