news 2026/7/22 7:03:59

Pelco KBD300A 模拟器:17.按照pytest自动化测试方案规划建立测试基础框架

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Pelco KBD300A 模拟器:17.按照pytest自动化测试方案规划建立测试基础框架

17 按照pytest自动化测试方案规划建立测试基础框架**

测试目录结构:

tests/ ├── pytest.ini ├── conftest.py ├── unit/ # 单元测试(优先:protocol、macro、alarm) ├── integration/ # 集成测试(serial + protocol + macro) ├── ui/ # UI 测试(keyboard、macro_editor、log_panel) ├── e2e/ # 端到端测试(完整用户流程) └── performance/ # 性能测试(宏大循环、日志吞吐)

1. pytest.ini

1.1 指定测试文件的位置和命名规则:你可以通过配置项来改变pytest默认的测试文件查找规则。例如,你可以指定测试文件所在的目录、测试文件的命名模式等。

1.2 配置测试搜索路径:可以添加额外的目录到测试搜索路径中。

1.3 添加命令行默认选项:你可以在pytest.ini中设置一些默认的命令行选项,这样每次运行pytest时都会自动使用这些选项,而不需要每次都手动输入。例如,你可以设置默认使用详细输出(-v)或者自动识别并运行测试(–tb=short)等。

1.4 注册标记(marks):pytest允许你使用标记来分类测试,但是为了避免标记名拼写错误,你可以在pytest.ini中注册标记,这样pytest会检查标记名是否有效。注册标记时还可以提供标记的描述信息。

1.5 配置测试报告:可以配置测试报告的格式,例如使用JUnit XML格式输出测试结果,以便于持续集成工具(如Jenkins)读取。

1.6 配置插件:可以启用或禁用pytest插件,也可以配置插件的参数。

1.7 环境变量设置:可以在pytest.ini中设置环境变量,这些环境变量将在测试运行时生效。

1.8 配置测试运行的行为:例如,可以配置测试超时时间、并发执行测试的进程数(如果使用了pytest-xdist插件)等。

# tests/pytest.ini [pytest] testpaths = tests python_files = test_*.py *_test.py python_classes = Test* *Test python_functions = test_* *_test addopts = -ra --tb=short --strict-markers --maxfail=5 -p no:warnings --cov=core --cov-report=term-missing --cov-report=html:coverage_html --cov-report=xml:coverage.xml markers = unit: 单元测试(隔离依赖) integration: 集成测试(模块交互) ui: UI 测试(pytest-qt) e2e: 端到端测试(完整流程) performance: 性能测试(cProfile) slow: 慢测试(可跳过) serial: 需要真实或mock串口 macro: 宏相关测试 filterwarnings = ignore::DeprecationWarning ignore::PendingDeprecationWarning # 超时保护 timeout = 30 timeout_method = thread

2. conftest.py

conftest.py 是 pytest 的一个特殊文件,它用于存放 pytest 的夹具(fixtures)和插件配置,这些夹具可以在该文件所在的目录以及所有子目录中的测试文件中使用。
主要作用:

  1. 共享夹具(fixtures)
    可以在多个测试文件中共享夹具,避免重复代码。
    夹具可以用于设置测试环境、准备测试数据、初始化资源等。
  2. 钩子函数(hooks)
    可以自定义 pytest 的行为,例如添加自定义的启动和清理逻辑、修改测试报告等。
  3. 插件配置
    可以加载和配置 pytest 插件。
  4. 自定义命令行选项
    可以通过钩子函数添加自定义命令行选项,并在夹具或测试中使用。

使用特点:
自动发现:pytest 会自动发现 conftest.py 文件,无需导入。
作用域:
conftest.py 文件可以放在任何目录中,其作用域为该目录及其所有子目录。
可以在不同的目录中放置多个 conftest.py 文件,子目录中的 conftest.py 会覆盖父目录中的同名夹具或钩子。
不可导入:测试文件不需要导入 conftest.py 中的夹具,pytest 会自动注入。
共享夹具:可以用于跨测试文件共享夹具,特别是当多个测试文件需要相同的设置时。

# tests/conftest.pyimportpytestimporttempfileimportosimportjsonfromunittest.mockimportMock,patchfromPyQt5importQtWidgetsfromPyQt5.QtCoreimportQTimerimportserial# 用于mockfromcore.utils.log_emitterimportget_log_emitter# ----------------------------- 全局 fixture -----------------------------@pytest.fixture(scope="session")defqt_app():"""QApplication 单例 fixture"""app=QtWidgets.QApplication.instance()ifappisNone:app=QtWidgets.QApplication([])yieldapp# 避免退出时崩溃ifapp:app.quit()@pytest.fixturedefqtbot(qt_app,qtbot):"""pytest-qt 的 qtbot,自动使用 qt_app"""returnqtbot@pytest.fixturedefmock_serial(mocker):"""Mock pyserial.Serial"""mock_ser=mocker.patch("serial.Serial")mock_ser.return_value.is_open=Truemock_ser.return_value.in_waiting=0mock_ser.return_value.read.return_value=b""mock_ser.return_value.write.return_value=Nonereturnmock_ser@pytest.fixturedefmock_log_emitter(mocker):"""Mock LogEmitter 单例"""emitter=get_log_emitter()mocker.patch.object(emitter,"info")mocker.patch.object(emitter,"warning")mocker.patch.object(emitter,"error")mocker.patch.object(emitter,"debug")mocker.patch.object(emitter,"send")mocker.patch.object(emitter,"receive")mocker.patch.object(emitter,"alarm")returnemitter@pytest.fixturedeftemp_settings():"""临时 settings.json"""withtempfile.NamedTemporaryFile(mode="w",suffix=".json",delete=False)asf:config={"serial_config":{"port":"COM99","baud":9600,"protocol":"D","parity":"None","kbd_address":1,"default_cam_id":1}}json.dump(config,f)path=f.nameyieldpath os.unlink(path)@pytest.fixturedeftemp_macro_dir(tmp_path):"""临时宏目录"""macro_dir=tmp_path/"resources"/"macros"macro_dir.mkdir(parents=True,exist_ok=True)yieldstr(macro_dir)# ----------------------------- 常用 mock -----------------------------@pytest.fixturedefmock_virtual_device(mocker):"""Mock VirtualDevice"""device=mocker.MagicMock()device.process_command.return_value=b"ACK"device.get_status_dict.return_value={"pan":0.0,"tilt":0.0}returndevice# ----------------------------- 参数化数据 -----------------------------@pytest.fixture(params=[b"\xff\x01\x00\x02\x20\x20\x43",b"\xa0\x01\x00\x00\x00\x00\x00\xaf"])defsample_frame(request):"""D 和 P 协议示例帧"""returnrequest.param# ----------------------------- 清理 -----------------------------@pytest.fixture(autouse=True)defcleanup():yield# 可在此清理临时文件、停止定时器等

两者对比:

特性conftest.pypytest.ini
格式Python 代码INI 配置文件
主要用途夹具、钩子、插件配置选项、参数
位置可在多级目录通常只在根目录
内容动态代码逻辑静态配置
加载顺序多个文件层级加载单个文件

下一步安排

  • 单元测试优先模块:先写tests/unit/test_protocol.py(build/parse 函数)
  • 集成测试tests/integration/test_serial_protocol.py
  • UI 测试tests/ui/test_keyboard_joystick.py(需要 pytest-qt)
  • 端到端tests/e2e/test_macro_flow.py(键盘 → 宏 → 协议 → 模拟器)
    👉上一篇 :项目硬件相关测试的 Mock 技巧详解
    👉总目录:Python开发软键盘全程总览
    👉下一篇
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/19 9:43:25

为什么写java的都用jdk8?

写 Java 的程序员(尤其是国内中大型企业、传统互联网、金融、政府、外包等场景)到现在2026年1月还在大规模用 JDK 8 的原因,已经不是“技术最先进”,而是一堆现实约束叠加后的局部最优解。简单说:稳 > 新&#xff0…

作者头像 李华
网站建设 2026/7/20 9:10:26

想要学习Agent开发,听说有LangGraph框架,那还要学习LangChain吗?

是的,如果你主要目标是学习 Agent 开发,尤其是想做出可控、复杂、状态持久、生产级别的 Agent 系统,那么 LangGraph 是目前(2026 年)最值得优先深入的框架,但是否“必须”先学/同时学 LangChain 取决于你的…

作者头像 李华
网站建设 2026/7/19 9:31:56

大模型Agent的核心还是prompt?

不完全是,但 prompt(以及更广义的“上下文工程”)仍然是 LLM Agent 的核心基石之一,尤其在2026年初的实际工程实践中。 简单说:Agent 的“智能”本质上还是靠大模型的推理能力,而这个推理能力目前主要通过…

作者头像 李华
网站建设 2026/7/16 3:44:32

计算机毕业设计之springboot校园疫情管理微信小程序

时代在飞速进步,每个行业都在努力发展现在先进技术,通过这些先进的技术来提高自己的水平和优势,校园疫情管理当然不能排除在外。校园疫情管理是在实际应用和软件工程的开发原理之上,运用微信开发者、java语言以及SpringBoot框架进…

作者头像 李华
网站建设 2026/7/16 10:23:21

DevOps平台2026:本土化与云原生双轨并行下的战略抉择

DevOps平台2026:本土化与云原生双轨并行下的战略抉择 数字化转型浪潮下,DevOps平台正经历着前所未有的变革与演进。2026年的技术版图呈现出明显的双轨并行特征:一方面是以Gitee为代表的本土化解决方案快速崛起,另一方面则是Jenki…

作者头像 李华