news 2026/6/9 17:38:27

Pelco KBD300A 模拟器:TEST02.重构后键盘部分的测试操作一步一步详细指导

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Pelco KBD300A 模拟器:TEST02.重构后键盘部分的测试操作一步一步详细指导

TEST02.重构后键盘部分的测试操作一步一步详细指导

在上一篇《重构后键盘部分的测试方案规划》中,我们从宏观角度梳理了测试的整体思路:为什么要测、测什么、覆盖率目标以及测试分类。那篇文章更像是一份蓝图,帮助我们建立测试体系的战略方向。

本篇《重构后键盘部分的测试操作一步一步详细指导》则承接前文,聚焦于具体的落地实践。我们将从环境准备开始,逐步讲解如何编写单元测试、集成测试、端到端测试,并补充手动验证环节。目标是让读者不仅理解测试的重要性,还能亲手跑通整个流程,获得可量化的覆盖率结果。预计耗时 2–4 小时,适合在 Windows 7 环境下完整演练。

前提:项目已克隆到本地,Python 3.7 环境激活,pyserial/PyQt5 已安装。Win7 注意:用管理员运行命令提示符,避免权限问题。


步骤1:环境准备(10–15 分钟)

  1. 安装测试依赖

    • 打开命令提示符(cmd.exe),导航到项目根目录。

    • 创建/激活 virtualenv(推荐,避免全局污染):

      python-mvenv venv venv\Scripts\activate
    • 安装依赖(requirements.txt 已含 PyQt5/pyserial,再加测试工具):

      pipinstallpytest==7.4.0 pytest-qt==4.4.0coverage==6.5.0

      (这些版本兼容 Python 3.7 和 Win7,无高版本依赖冲突。)

  2. 创建 tests/ 目录和测试文件

    • 在项目根新建tests/keyboard/

    • 添加示例测试文件(从规划复制,稍后详述)。初始结构如下:

      tests/ ├── keyboard/ │ ├── test_panel.py # 单元:按键 / LCD │ ├── test_integration.py # 集成:信号 + 串口 mock ├── analyze_coverage.py # 覆盖率分析脚本 ├── test_e2e.py # 端到端:全链路 └── conftest.py # 全局 fixtures(如 QApplication)

      简短的说明表格:

      文件/目录作用说明
      keyboard/键盘相关测试模块目录
      test_panel.py单元测试:按键输入、LCD 显示
      test_integration.py集成测试:信号与串口交互
      test_e2e.py端到端测试:完整链路验证
      analyze_coverage.py覆盖率分析辅助脚本
      conftest.py全局 pytest fixtures(QApplication 等)
  3. 添加 conftest.py(全局 fixture)

    # tests/conftest.py# 全局 fixture 配置importsysimportosimportpytestfromPyQt5.QtWidgetsimportQApplicationfromunittest.mockimportMagicMock# 添加项目根目录到 sys.path(tests/ 的上两级)project_root=os.path.abspath(os.path.join(os.path.dirname(__file__),'..'))ifproject_rootnotinsys.path:sys.path.insert(0,project_root)@pytest.fixture(scope="session")defqapp():""" 全局 QApplication fixture,整个测试会话只初始化一次。 """app=QApplication.instance()orQApplication([])yieldapp app.quit()@pytest.fixturedefapp_window(qapp):""" 提供一个完整的 AppWindow 实例,并在测试结束后自动关闭。 避免在各个测试文件中重复定义。 """fromui.main_windowimportAppWindow win=AppWindow()win.show()qapp.processEvents()yieldwin win.close()@pytest.fixturedefkeyboard_panel(qapp):""" 提供一个独立的 KeyboardPanel 实例,用于单元测试。 """fromui.keyboard.panelimportKeyboardPanel panel=KeyboardPanel()qapp.processEvents()yieldpanel panel.close()

    这样,所有测试文件都可以直接使用qappfixture,而无需重复初始化 QApplication。

  4. 添加 analyze_coverage.py(覆盖率分析辅助脚本)

    # tests/analyze_coverage.pyimportjsondefmain():withopen("coverage.json","r",encoding="utf-8")asf:data=json.load(f)totals=data["totals"]print(f"整体覆盖率:{totals['percent_covered_display']}%")forfilename,infoindata["files"].items():pct=info["summary"]["percent_covered_display"]ifint(pct)<50:print(f"{filename}: 覆盖率{pct}%")print("缺失行:",info["missing_lines"])if__name__=="__main__":main()

    运行python tests/analyze_coverage.py可以快速定位覆盖率薄弱的文件和缺失行,指导后续补充测试。

  5. 验证环境

    • 运行pytest --version,预期输出 pytest 7.4.0。

    • 运行项目:python app.py,检查 UI 正常(键盘显示)。

    • 检查pytest.ini配置:

      markers = keyboard: 测试键盘 UI 与交互 filterwarnings = ignore:.*sipPyTypeDict.*:DeprecationWarning

      这样运行时可以用pytest -m keyboard来跑所有键盘相关测试,并且不会刷屏显示 PyQt5 的弃用告警。


步骤2:单元测试(隔离组件)

目标:测试单个文件(如 panel.py 的 _on_digit),不跑 GUI/串口。快速反馈。

  1. 编写/运行 test_panel.py

    -预期:所有 `@pytest.mark.keyboard` 的测试通过。-如果失败:检查import路径(fromui.keyboard.panelimportKeyboardPanel)。pytest tests/keyboard/test_panel.py-v-W ignore::DeprecationWarning# tests/keyboard/test_panel.pyimportpytestfromui.keyboard.panelimportKeyboardPanelfromunittest.mockimportMagicMock@pytest.fixturedefkeyboard(qapp):returnKeyboardPanel()@pytest.mark.keyboarddeftest_on_digit_limit(keyboard):foriinrange(5):# 输入5位keyboard._on_digit(1)assertlen(keyboard.input_buffer)==4# 限长4assertkeyboard.lcd.display.called# mock 检查调用@pytest.mark.keyboarddeftest_set_mode(keyboard):keyboard.mode_changed=MagicMock()keyboard.lcd.display_text=MagicMock()keyboard._set_mode("PRESET")assertkeyboard.mode=="PRESET"keyboard.mode_changed.emit.assert_called_with("PRESET")keyboard.lcd.display_text.assert_called_with("PRESET",...)
  2. 运行

    pytest-mkeyboard-v
    • 预期:所有 test_ 通过(e.g., 2 passed)。
    • 如果失败:检查 import 路径(from ui.keyboard.panel import KeyboardPanel)。
  3. 类似测试 LCD/indicator

    • test_lcd.py:mock theme,检查 display_text 的 setStyleSheet。
    • test_indicator.py:mock QTimer,检查 flash 后 off 调用。
  4. 覆盖率检查

    coverage run -m pytest tests/keyboard/ coverage report -m # 显示缺失行 coverage html # 生成 htmlcov/index.html 查看
    • 目标:ui/keyboard/ 覆盖 90%+。

步骤3:集成测试(模块交互)

目标:测试键盘与核心/mock 串口的交互(如按键 emit → 串口 write)。

  1. 编写 test_integration.py

    # tests/keyboard/test_integration.pyimportpytestfromunittest.mockimportpatch,MagicMockfromui.keyboard.panelimportKeyboardPanelfromcore.protocolimportptz_control@pytest.fixturedefkeyboard(qapp):kb=KeyboardPanel()kb.serial_mgr=MagicMock()# mock 串口returnkb@pytest.mark.keyboarddeftest_joystick_to_protocol(keyboard):withpatch('core.protocol.ptz_control')asmock_ptz:keyboard.joystick_moved.emit(10,-20)mock_ptz.assert_called_with(keyboard.serial_mgr,...,10,-20)@pytest.mark.keyboarddeftest_enter_error_indicator(keyboard):keyboard.input_buffer="invalid"keyboard.indicator_manager.on=MagicMock()keyboard._on_enter()keyboard.indicator_manager.on.assert_called_with("ERR")
  2. 运行

    pytest -m keyboard -v
    • 预期:通过,mock assert_called 检查交互。
  3. 协议集成测试

    • 新建 test_protocol_integration.py:mock build_pelco_d,检查 checksum。

步骤4:端到端测试(全链路)

目标:模拟用户操作,验证 UI → 核心 → 反馈。

  1. 安装 pytest-qt(如果未装):pip install pytest-qt==4.0.2

  2. 编写 test_e2e.py

    # tests/test_e2e.pyimportpytestfromPyQt5.QtTestimportQTestfromPyQt5.QtCoreimportQtfromui.main_windowimportAppWindow@pytest.mark.keyboarddeftest_full_keyboard_flow(qapp):window=AppWindow()window.show()# 显示窗口qapp.processEvents()# 模拟数字输入fordigitin"123":btn=window.keyboard.findChild(QtWidgets.QPushButton,digit)# 假设 text=digitQTest.mouseClick(btn,Qt.LeftButton)assertwindow.keyboard.lcd.value()==123# 检查 LCD# 模拟 ENTent_btn=window.keyboard.findChild(QtWidgets.QPushButton,"ENT")QTest.mouseClick(ent_btn,Qt.LeftButton)# 检查 TX 闪(indicator_manager.state("TX") 暂 True)# 异常:输入无效后 ENT,检查 ERR on
  3. 运行

    pytest -m keyboard -v
    • 预期:窗口短暂闪现,通过(Win7 可能慢,加 -s 显示输出)。
    • 注意:端到端慢,标记 @pytest.mark.slow。

步骤5:手动测试与验证

目标:覆盖自动化难测(如视觉/手感)。

  1. 运行项目python app.py

  2. Checklist 操作

    • 输入 1234 → LCD 显示 1234,超限不增。
    • 按 PRESET → LCD “PRESET” + 颜色变(themes.py)。
    • 摇杆拖拽 → TX 闪(模拟发送)。
    • 切换主题(右上按钮) → LCD/灯颜色变。
    • resize 窗口 → 布局不崩(stretch 生效)。
    • 模拟错误(断串口) → ERR 灯 + 弹窗。
    • Win7 特定:多分辨率(1024x768)测试;旧 COM 端口连接真实设备验证。
  3. 最终覆盖率

    coverage run -m pytest -m keyboard coverage report -m coverage html
    • ui/keyboard/覆盖率 90%+。

步骤6:常见问题与调试

  • 失败:ImportError → 检查 PYTHONPATH(sys.path.append(“…”) 在 test)。
  • Win7 卡顿:减 QTimer 间隔;关防病毒。
  • CI:GitHub Actions 加 Win7 runner(自建或第三方)。
  • 扩展:加 @pytest.mark.parametrize 参数化(e.g., 多模式测试)。

通过本文的详细操作,你已经能够在本地环境中完成键盘部分的测试:从单元到集成,再到端到端和手动验证,覆盖率报告也能直观呈现测试成果。与上一篇的规划篇形成呼应,本篇提供了实操指南,真正把测试方案落地。

至此,键盘模块的测试体系已经基本完善。下一篇我们将进入宏系统的开发与测试,继续扩展整个项目的可靠性与可维护性。这样,一个完整的测试闭环就逐步建立起来,为后续功能迭代打下坚实基础。

上一篇总目录下一篇

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/29 3:07:36

Wireshark抓包实操:ModbusTCP报文格式说明新手教程

从零开始看懂ModbusTCP&#xff1a;用Wireshark抓包拆解工业通信的“心跳” 你有没有过这样的经历&#xff1f;PLC和HMI之间突然断联&#xff0c;现场设备数据不更新&#xff0c;排查一圈却找不到原因。最后发现&#xff0c;问题其实藏在那条看不见的网络报文里。 在工业自动…

作者头像 李华
网站建设 2026/5/25 9:47:07

你真的会用R做系统发育信号检测吗:trait数据建模常见误区与纠正

第一章&#xff1a;你真的会用R做系统发育信号检测吗在进化生物学研究中&#xff0c;系统发育信号&#xff08;phylogenetic signal&#xff09;反映了物种性状的演化是否受到其系统发育关系的影响。R语言凭借其强大的统计分析与可视化能力&#xff0c;成为检测系统发育信号的首…

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

【零膨胀模型建模宝典】:基于R语言的GLM应用精讲与案例实操

第一章&#xff1a;零膨胀模型与R语言GLM基础在处理计数数据时&#xff0c;常会遇到因过多零值而导致传统广义线性模型&#xff08;GLM&#xff09;拟合不佳的问题。零膨胀模型&#xff08;Zero-Inflated Models&#xff09;为此类数据提供了有效解决方案&#xff0c;尤其适用于…

作者头像 李华
网站建设 2026/6/5 14:53:35

最新爆火8款AI论文神器!10分钟3万字+真实文献,PaperFine强推

深夜急救提醒&#xff1a;距离期末答辩/投稿截止只剩最后3天&#xff0c;还在为论文卡字数、改格式、降重抓狂&#xff1f;别等DDL前夜崩溃——这篇2026最新急救方案&#xff0c;帮你用最短时间拿下高质量论文&#xff0c;错过这波AI红利&#xff0c;你可能要多熬无数个通宵&am…

作者头像 李华
网站建设 2026/6/5 2:43:59

广告配音成本太高?试试IndexTTS 2.0批量生成统一风格音频

广告配音成本太高&#xff1f;试试 IndexTTS 2.0 批量生成统一风格音频 在短视频广告每秒都在抢夺注意力的今天&#xff0c;一条30秒的促销语音如果节奏慢了半拍、情绪不到位&#xff0c;或是不同版本之间声音“变脸”&#xff0c;用户可能还没看到优惠信息就划走了。而传统专业…

作者头像 李华
网站建设 2026/5/31 19:48:22

什么是IS-IS

文章目录为什么需要IS-ISIS-IS有哪些基本概念IS-IS邻居关系是如何建立的LSDB是如何同步的路由计算是如何进行的IS-IS扩展IS-IS与OSPF的区别IS-IS最初是国际标准化组织ISO&#xff08;the International Organization for Standardization&#xff09;为它的无连接网络协议CLNP&…

作者头像 李华