pytest测试框架

1、测试框架概念

  • 抽象出来的工具集合,提供大量组件、工具和功能
  • 用例发现:可以自动发现任何目录下的用例
  • 用例管理:用例筛选
  • 环境管理:前置操作或后置操作
  • 用例执行:执行用例当中的步骤,并收集用例的结果
  • 测试报告:将用例发现、用例执行及最终的结果生成一个完整的报告

1.1、主流编程语言测试框架

  • java:junit和testng
  • python:unittest和pytest
  • unittest和pytest对比
    image

2、快速安装

  • pip install pytest #普通安装
  • pip install pytest -U #升级到最新版本

2.1、pytest三种启动方式

  • 方法一:命令方式启动:pytest
  • 方法二:代码方式启动
点击查看代码
import pytest

pytest.main()
  • 方法三:鼠标方式启动(鼠标右键点击run)不建议
    -(1)该方法是由pycharm软件提供的,并非pytest自身的
    -(2)行为与前两种不一致,不适用复杂项目

2.2、pytest断言

  • pytest在简单基础上,对断言进行了高级的封装(AST),对python数据结构的断言非常的友好
  • 1)遵循python简单的学习方式
  • 2)同时实现了很多高级特性
  • 3)鼓励大家积极使用断言(建议强制使用)

3、看懂结果
============================= test session starts =============================
platform win32 -- Python 3.14.0, pytest-9.0.2, pluggy-1.6.0
rootdir: D:\Pycharm2025\pytest自动化学习
plugins: anyio-4.12.1, Faker-40.1.2
collected 9 items

test_base.py .F [ 22%]
test_data.py FFFF..F [100%]

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

def test_fail():
  assert False

E assert False

test_base.py:6: AssertionError
__________________________________ test_str ___________________________________

def test_str():
    a = 'aaaaaa'
    b = 'aaaabc'
  assert a == b

E AssertionError: assert 'aaaaaa' == 'aaaabc'
E
E - aaaabc
E + aaaaaa

test_data.py:6: AssertionError
=========================== short test summary info ===========================
FAILED test_base.py::test_fail - assert False
FAILED test_data.py::test_num - assert 1 == 2
FAILED test_data.py::test_str - AssertionError: assert 'aaaaaa' == 'aaaabc'
FAILED test_data.py::test_list - assert [1, 2, 3, 4, 5, 6] == [1, 2, 3, 5, 4, 7]
FAILED test_data.py::test_dict - AssertionError: assert {'a': 1, 'b':...c': 3...
FAILED test_data.py::test_bool - assert True == False
========================= 6 failed, 3 passed in 0.29s =========================

  • 执行环境:python、pytest、pluggy版本、代码根目录、用例数量
  • 执行过程:文件名称、用例结果、执行进度
  • 失败详情:用例内容、断言提示
  • 整体摘要:整体用例结果数量、结果情况、花费时间
  • pytest用例执行结果情况

image

4、用例规则
4.1用例发现规则

  • 测试框架在识别、加载用例的过程,称之为:用例发现
    4.1.1 pytest用例发现步骤:
    (1)遍历所有的目录,例外venv目录和‘.’开头的不在遍历范围内
    (2)打开python文件,文件名称规则:‘test_’开头,'_test'结尾
    (3)遍历所有Test开头类
    (4)收集所有test_开头函数 或者 方法

4.2 用例内容规则

  • (1)可调用的(函数、方法、类、对象)
  • (2)名字'test_'开头
  • (3)没有参数(参数有另外的含义
  • (4)没有返回值(默认为None)
  • (5)变量可作为测试用例
    4.3 练习
    有函数add接收两个参数,并返回他们相加的结果,请为此编写测试用例
点击查看代码
def add(a,b):
    return a+b
class TestAdd:
    def test_int(self):
        res = add(1,2)
        assert res == 3

    def test_str(self):
        res = add('1','3')
        assert res == '13'

    def test_list(self):
        res = add([1],[2,3,4])
        assert res == [1,2,3,4]

    def test_float(self):
        res = add(1.2,3.4)
        assert res == 4.6

5、配置框架
5.1 配置可以改变pytest默认规则
(1)命令行参数
(2)ini配置文件(在根目录中创建pytest.ini)
5.2 所有配置可以一键获取 pytest -h **
5.2.1 有那些参数
5.2.2 分别是什么方式
- 1) -开头的是:参数
- 2)小写字母开头:ini配置
- 3)大写字母开头:环境变量
5.3 常用参数
(1)-v:增加详细程度
(2)-s:在用例中正常的
使用输入和输出**(允许用例中的输入和输出显示)
(3)-x:快速退出(当遇到失败的用例停止执行)
(4)-m:用例筛选
6、标记mark
6.1 标记作用
标记可以让用例与众不同,进而可以让用户被区别对待
6.1.1 用户自定义标记,只能实现用例筛选
6.1.1.1 用户自定义标记的操作步骤
1)先注册
在pytest.ini中注册

点击查看代码
[pytest]

markers =
    api:接口测试
    web:UI测试
    ut:单元测试
    login:登陆相关
    pay:支付相关
2)再标记(装饰器) @pytest.mark.web @pytest.mark.ui @pytest.mark.ut @pytest.mark.login @pytest.mark.pay 3)后筛选 pytest -m web

6.1.2 框架内置标记(为用例增加特殊执行效果)
6.1.2.1 和用户自定义标记区别
(1)不需要注册,可以直接使用
(2)不仅可以筛选,还可以增加特殊效果
(3)不同的标记,增加不同的特殊效果

  • skip:无条件跳过
  • skipif:有条件跳过
  • xfail:预期失败
  • parametrize:参数化
  • usefixtures:使用fixtures

7、数据驱动测试参数
数据驱动测试 = 参数化测试 + 数据文件
根据数据文件的内容,动态决定用例数量、内容

  • 构造的csv数据信息
    image

  • 获取csv数据的代码

点击查看代码
import csv
import os
import chardet
#检测文件编码
def detect_encoding(file_path):
    with open(file_path, 'rb') as f:
        result = chardet.detect(f.read())
        return result['encoding']
#获取csv文件内容
def read_csv(filename):
    # 获取当前文件的绝对路径
    current_dir = os.path.dirname(os.path.abspath(__file__))
    file_path = os.path.join(current_dir, filename)
    file_encoding = detect_encoding(file_path)
    with open(file_path, 'r', encoding=file_encoding) as f:
        reader = csv.reader(f)
        header = next(reader)
        return list(reader)
  • 数据驱动测试的代码信息
点击查看代码
    @pytest.mark.ddt
    @pytest.mark.parametrize(
        'a,b,c',
        read_csv("ddt.csv")
    )
    def test_ddt(self,a,b,c):
        res = add(int(a),int(b))
        assert res == int(c)

11、夹具fixtuer

  • 在用例执行之前执行之后,自动运行代码
    场景:
  • 接口:之前:加密参数/之后:解密结果
  • web:之前:启动浏览器/之后:关闭浏览器
  • web:之前登陆账号/之后:退出账号

11.1 创建fixtuer

点击查看代码
@pytest.fixture
def f():
    print()
    #前置操作
    yield 
    #后置操作

** 11.2 使用fixture**
(1)在用例的参数列表中,加入fixture名字即可
def test_1(f):
pass
(2)给用例加上usefixtures装饰器标记
@pytest.mark.usefixtures("f")
def test_2():
pass

11.3 高级用法

  • 自动使用
  • 依赖使用
    (1)linux:使用linux进行编译
    (2)git:使用git进行版本控制
    (3)fixture:使用fixture进行前后置自动操作
  • 返回内容:接口自动化测试封装:接口关联
    (1)在yield后面携带fixture的传递的数据
  • 范围共享
    (1)默认范围:function(函数) @pytest.fixture(autouse=True,scope='funtion')
    (2)全局范围:session(全局) @pytest.fixture(autouse=True,scope='session')
    • 使用conftest.py(第三方命名空间),将需要全局共享的fixture放在该文件中
点击查看代码
import datetime
import pytest
@pytest.fixture(scope='session')
def ff():
    print('我也是fixture,但是被fixture使用')

@pytest.fixture(autouse=True,scope='session')
def f(ff):
    print(datetime.datetime.now(),"用例开始执行")
    #前置操作
    yield  123#开始执行执行用例“123”为f的返回值
    #后置操作
    print(datetime.datetime.now(), "用例执行完成")
    #从python的语法来看,函数中可以有多个 yield,但pytest框架要求只能出现一个

12、插件管理

  • pytest插件生态是pytest特别的优势之处
    https://docs.pytest.org/en/stable/reference/plugin_list.html
    12.1 插件类型
  • 不需要安装:内置插件
  • 需要安装:第三方插件
    12.2 插件启用管理
  • 启用:-p abc
  • 禁用:-p no:abc
    12.3 插件使用方式
  • 参数
  • 配置文件
  • fixture
  • mark
    12.4 常用第三方插件
    (1)pytest-html
  • 用途:生成html测试报告
  • 安装:pip install pytest-html
  • 使用方式1:参数化:pytest --html=report.html --self-contained-html
  • 使用方式2:在pytest.ini中添加如下代码
    addopts = --html=report.html --self-contained-html
    image

(2)pytest-xdist (默认采用多进程)

  • 用途:分布式执行
  • 安装:pip install pytest-xdist
  • 使用:-n N
  • 说明:
  • 只有在任务本身耗时较长,超出调用成本很多的时候,才有意义
  • 分布式执行,有并发问题,资源竞争、乱序执行
    (3)pytest-rerunfailures
  • 用途:用例失败之后,重新执行
  • 安装:pip install pytest-rerunfailures
  • 使用:Num:重试次数,Time:每次重试之间的间隔等待时间
    参数:--reruns Num --reruns-delay Time

(4)pytest-result-log

  • 用途:把用例的执行结果记录的日志文件中
  • 安装:pip install pytest-result-log
  • 使用:通过配置文件实现
点击查看代码
log_file = ./logs/pytest.log
log_file_level = info
log_file_format = %(levelname)-8s %(asctime)s [%(name)s:%(lineno)s] : %(message)s
log_file_date_format = %Y-%m-%d %H:%M:%S

; 记录用例执行结果
result_log_enable = 1
; 记录用例分割线
result_log_separator = 1
; 分割线等级
result_log_level_separator = warning
; 异常信息等级
result_log_level_verbose = info

13、企业级测试报告
allure是一个测试报告框架
13.1 allure插件基本操作

  • 安装
    pip install allure-pytest
  • 配置:只能生成json元数据
    addopts = --alluredir=temps --clean-alluredir
  • 生成报告(需要安装allure)
    allure generate -o report -c temps
  • 安装allure
    https://github.com/allure-framework/allure2/releases/download/2.30.0/allure-2.30.0.zip
  • 解压至D盘根目录
    Expand-Archive -Path D:\allure-2.30.0.zip -DestinationPath D:\allure -Force
  • 添加环境变量
    在windows系统,高级系统设置,环境变量,系统变量,Path中添加D:\allure\allure-2.30.0\bin,重启系统生效
  • 测试有效性
    分别在pycharm和cmd命令行中执行allure --version
  • 通过脚本方式启动,自动生成报告
点击查看代码
import pytest
import os

pytest.main()

os.system("allure generate -o report -c temps ")

13.2 allure支持对用例进行分组和关联(敏捷开发术语)
@allure.epic #史诗,项目
@allure.feature #主题 模块
@allure.story #故事 功能
@allure.title #标题 用例

  • 使用相同装饰器的用例,自动的并入同一组
点击查看代码
import allure
import pytest

@allure.epic('小象自动化学习')
@allure.feature('pytest自动化训练营')
@allure.story('mark标记和筛选')
@allure.title('实现筛选的用例')
@pytest.mark.ut
def test_a():
    pass

@allure.epic('小象自动化学习')
@allure.feature('pytest自动化训练营')
@allure.story('fixture前置和后置')
@allure.title('使用fixture的用例')
@pytest.mark.ut
def test_b():
    pass

14、Web自动化测试实践

posted @ 2026-02-24 10:53  jake瑞  阅读(4)  评论(0)    收藏  举报