接口自动化——初识pytest

|--------|---------|-----------------|
| 缩写 | 单词 | 含义 |
| . | passed | 通过 |
| F | failed | 失败(用例执行时报错) |
| E | error | 出错(fixture执行报错) |
| s | skipped | 跳过 |
| X | xpassed | 预期外的通过(不符合预期) |
| x | xfailed | 预期内的失败(符合预期) |


1.pytest 配置

1.查看pytest的所有配置项

在pycharm的terminal中 输入下面的代码,即可查看所有的配置项

pytest -h usage: pytest [options] [file_or_dir] [file_or_dir] [...]

部分配置项 :

python 复制代码
-v, --verbose         Increase verbosity   # 增加输出详细程度
-q, --quiet           Decrease verbosity   # 减少输出详细程度
 -x, --exitfirst       Exit instantly on first error or failed test   # 在第一个错误或测试失败时立即退出

markers (linelist):   Register new markers for test functions # 注册新标记
addopts (args):       Extra command line options  # add options:添加额外的命令行选项,在使用ini文件配置时使用 
2.配置:配置有两种方法:
  • 命令行参数
  • ini配置文件
3.命令行参数

命令行参数就是每次执行测试的时候在 pytest 命令后面添加 参数:下面是一个简单的测试代码:

python 复制代码
def test_pass():
    assert (10 == 10)

在terminal中执行 pytest 输出为

接下来在terminal中执行 pytest -v 命令,输出为:

可以看到 pytest -v 命令的输出比 pytest 命令的输出更详细,而且 -v 是可以叠加的,也就是可以使用多个v来尽可能的增加详细程度 ,-vv,-vvv,-vvvv都是可以的。同理,-q 也是一致,并且 -v -q 还可以同时使用,不过一个增加详细程度,一个减少详细程度,同时使用效果就抵消了。多个v 和多个q也可以同时使用,例如:pytest -vvv -qqqq 就看哪个多了。鉴于这里的用例比较简单,在减少/增加详细程度也不会有太大的变化,就不再放图了。

4.ini配置文件

每次都要在命令后加相应的配置项很麻烦,更加方便的方法是使用ini配置文件,将需要使用的配置项放进去,这样每次在执行的时候,由系统自动的将配置项加到命令后面,就不需要在手动添加了。

  1. 根目录中创建 pytest.ini 文件
  2. 创建 pytest 选择器 [pytest]
  3. 按行添加需要的配置项(addopts)
python 复制代码
[pytest]
addopts = -s -v

2.标记mark

mark的主要作用是让用例变得不同,实现用例的筛选。标记有两种,一种是pytest框架内置的标记,一种是用户自定义的标记

1.用户自定义的标记

1.注册:在ini配置文件中实现,例如

python 复制代码
markers =
  api
  ui
  ut

2.标记,标记是可以叠加的。

python 复制代码
import pytest


@pytest.mark.ut   # 标记
def test_pass():
    assert 1 == 1


@pytest.mark.api   标记
def test_fail():
    assert 1 == 2


@pytest.mark.ut   # 标记
@pytest.mark.ui   # 标记
def test_skip():
    assert 1 == 1

3.筛选

可以根据标记对用例进行筛选,terminal / ini配置文件中均可实现。例如, 只执行拥有api标记的用例

ini 文件配置

addopts = -s -v -m api

terminal中实现

pytest -m api # 只执行拥有api标记的用例

python 复制代码
D:\python_project\API_Auto\API1\venv\Scripts\python.exe D:\python_project\API_Auto\API1\run.py 
============================= test session starts =============================
platform win32 -- Python 3.10.6, pytest-8.3.5, pluggy-1.5.0 -- D:\python_project\API_Auto\API1\venv\Scripts\python.exe
cachedir: .pytest_cache
rootdir: D:\python_project\API_Auto\API1
configfile: pytest.ini
collecting ... collected 3 items / 2 deselected / 1 selected

test_mark.py::test_fail FAILED

================================== FAILURES ===================================
__________________________________ test_fail __________________________________

    @pytest.mark.api
    def test_fail():
>       assert 1 == 2
E       assert 1 == 2

test_mark.py:11: AssertionError
=========================== short test summary info ===========================
FAILED test_mark.py::test_fail - assert 1 == 2
======================= 1 failed, 2 deselected in 0.09s =======================

Process finished with exit code 0

可以看到,一共有三个用例,但是只执行了拥有api标记的用例,并且这个用例执行结果是失败的。

另外,标记支持逻辑运算。

pytest -m ("ut or api") # 执行标记为 ut 或者 api 的用例

python 复制代码
D:\python_project\API_Auto\API1\venv\Scripts\python.exe D:\python_project\API_Auto\API1\run.py 
============================= test session starts =============================
platform win32 -- Python 3.10.6, pytest-8.3.5, pluggy-1.5.0 -- D:\python_project\API_Auto\API1\venv\Scripts\python.exe
cachedir: .pytest_cache
rootdir: D:\python_project\API_Auto\API1
configfile: pytest.ini
collecting ... collected 3 items

test_mark.py::test_pass PASSED
test_mark.py::test_fail FAILED
test_mark.py::test_skip PASSED

================================== FAILURES ===================================
__________________________________ test_fail __________________________________

    @pytest.mark.api
    def test_fail():
>       assert 1 == 2
E       assert 1 == 2

test_mark.py:11: AssertionError
=========================== short test summary info ===========================
FAILED test_mark.py::test_fail - assert 1 == 2
========================= 1 failed, 2 passed in 0.11s =========================

Process finished with exit code 0

可以看到,三个用例都符合条件,所以三个用例都被执行了。

pytest -m ("ut and ui") # 执行同时具有标记为 ut 和 ui 的用例

python 复制代码
D:\python_project\API_Auto\API1\venv\Scripts\python.exe D:\python_project\API_Auto\API1\run.py 
============================= test session starts =============================
platform win32 -- Python 3.10.6, pytest-8.3.5, pluggy-1.5.0 -- D:\python_project\API_Auto\API1\venv\Scripts\python.exe
cachedir: .pytest_cache
rootdir: D:\python_project\API_Auto\API1
configfile: pytest.ini
collecting ... collected 3 items / 2 deselected / 1 selected

test_mark.py::test_skip PASSED

======================= 1 passed, 2 deselected in 0.01s =======================

Process finished with exit code 0

可以看到,只有一个用例符合要求,所以只执行了这一个用例

python 复制代码
@pytest.mark.ut   # 标记
@pytest.mark.ui   # 标记
def test_skip():
    assert 1 == 1
2.框架内置标记
  1. 不需要注册,直接使用
  2. 不仅用于筛选,还有特殊效果
  3. 不同的标记,拥有不同的效果
    1. skip:无条件跳过
    2. skipif:有条件跳过
    3. xfail:预期失败
    4. parametrize:参数化: 框架为用例传递参数
    5. usefixture:使用fixture
python 复制代码
import pytest


@pytest.mark.skip  # 跳过
def test_skip():
    assert 1 + 1 == 2


@pytest.mark.skipif(1 == 1, reason="1=1,结果为真,所以skip")  # 跳过
def test_skipif():
    assert 1 + 1 == 4


@pytest.mark.xfail   # 预期结果是失败,实际结是失败。是预期内的失败
def test_xfail():
    assert 1 + 1 == 3


@pytest.mark.xfail   # 预期结果是失败,实际结是成功。是预期外的成功
def test_xpass():
    assert 1 + 1 == 2


@pytest.mark.parametrize(   # 参数化
    "a, b, c",  # 列出参数
    [
        # 准备参数的值
        [1, 1, 2],
        [1, 1, 3]
    ]
)
def test_param(a, b,  c):
    assert (a + b) == c

|--------|---------|-----------------|
| 缩写 | 单词 | 含义 |
| . | passed | 通过 |
| F | failed | 失败(用例执行时报错) |
| E | error | 出错(fixture执行报错) |
| s | skipped | 跳过 |
| X | xpassed | 预期外的通过(不符合预期) |
| x | xfailed | 预期内的失败(符合预期) |

输出结果 :

python 复制代码
D:\python_project\API_Auto\API1\venv\Scripts\python.exe D:\python_project\API_Auto\API1\run.py 
============================= test session starts =============================
platform win32 -- Python 3.10.6, pytest-8.3.5, pluggy-1.5.0 -- D:\python_project\API_Auto\API1\venv\Scripts\python.exe
cachedir: .pytest_cache
rootdir: D:\python_project\API_Auto\API1
configfile: pytest.ini
collecting ... collected 6 items

test_mark.py::test_skip SKIPPED (unconditional skip)
test_mark.py::test_skipif SKIPPED (1=1,结果为真,所以skip)
test_mark.py::test_xfail XFAIL
test_mark.py::test_xpass XPASS
test_mark.py::test_param[1-1-2] PASSED
test_mark.py::test_param[1-1-3] FAILED

================================== FAILURES ===================================
______________________________ test_param[1-1-3] ______________________________

a = 1, b = 1, c = 3

    @pytest.mark.parametrize(   # 参数化
        "a, b, c",  # 列出参数
        [
            # 准备参数的值
            [1, 1, 2],
            [1, 1, 3]
        ]
    )
    def test_param(a, b,  c):
>       assert (a + b) == c
E       assert (1 + 1) == 3

test_mark.py:32: AssertionError
=========================== short test summary info ===========================
FAILED test_mark.py::test_param[1-1-3] - assert (1 + 1) == 3
======== 1 failed, 1 passed, 2 skipped, 1 xfailed, 1 xpassed in 0.10s =========

Process finished with exit code 0
相关推荐
数据智能老司机12 小时前
精通 Python 设计模式——分布式系统模式
python·设计模式·架构
数据智能老司机13 小时前
精通 Python 设计模式——并发与异步模式
python·设计模式·编程语言
数据智能老司机13 小时前
精通 Python 设计模式——测试模式
python·设计模式·架构
数据智能老司机13 小时前
精通 Python 设计模式——性能模式
python·设计模式·架构
c8i13 小时前
drf初步梳理
python·django
每日AI新事件13 小时前
python的异步函数
python
这里有鱼汤14 小时前
miniQMT下载历史行情数据太慢怎么办?一招提速10倍!
前端·python
databook1 天前
Manim实现脉冲闪烁特效
后端·python·动效
程序设计实验室1 天前
2025年了,在 Django 之外,Python Web 框架还能怎么选?
python
倔强青铜三1 天前
苦练Python第46天:文件写入与上下文管理器
人工智能·python·面试