桌面应用【免费下载链接】yasbA highly configurable Windows status bar written in Python.项目地址https://gitcode.com/gh_mirrors/yas/yasb点击查看免费下载本文以 YASBYet Another Status Bar一个高度可配置的 Windows 状态栏使用 Python PyQt6 编写仓库中的测试体系为对象完整讲解测试的运行方式、隔离机制、目录职责、编写规范以及一套独一无二的「把 ctypes 声明与真实 Windows SDK 逐项对拍」的校验方案最后落到 GitHub Actions 的 x64 / ARM64 双架构 CI 流水线。读完本文你将能在本地跑通全部测试、按规范新增测试并读懂任何一条 Windows 校验失败信息的含义与修法。一、快速开始安装与运行测试YASB 的测试基于 pytest测试依赖以 extra 的方式声明在 pyproject.toml 中[project.optional-dependencies]的test组目前为pytest9.1同时项目要求 Python 3.14。在仓库根目录执行pip install -e .[test] python -m pytest第一条命令以可编辑模式安装项目并带上测试依赖第二条命令运行 pyproject.toml 中testpaths [tests]指定的整个测试目录。也可以只运行某个子目录或单个文件python -m pytest tests/cloud python -m pytest tests/win32/test_structs.pypytest 的配置项同样集中在 pyproject.tomlminversion 9.1要求最低 pytest 版本pythonpath [src, .]把src放入导入路径因此测试里可以import core.xxx直接引用 YASB 源码见下文「编写测试」addopts [-ra]汇总显示所有结果的摘要strict true开启严格标记faulthandler_timeout 300让卡死的测试 5 分钟后自动 dump 堆栈。此外还注册了一个sdk标记tests/win32下与 Windows SDK 对拍的测试统一使用详见第四节。二、测试隔离绝不碰你真实的 YASB 配置tests/README.md强调「测试永远不会碰你真实的 YASB 配置」这句话的机制在 tests/conftest.py 中可以看到完整实现pytest_configuretests/conftest.py在任何测试模块导入src之前运行它先创建临时目录tempfile.mkdtemp(prefixyasb-tests-)然后把环境变量YASB_CONFIG_HOME和LOCALAPPDATA分别指向该临时目录下的子目录并setdefault(QT_QPA_PLATFORM, offscreen)。这样所有读取配置路径的模块级代码例如settings.DEFAULT_CONFIG_DIRECTORY在导入时解析到的就是沙箱路径而不是用户真实配置目录。由于导入发生在重定向之后任何模块级路径常量都安全地落在沙箱里。pytest_unconfiguretests/conftest.py在会话结束时恢复原始环境变量并删除临时目录。qappfixturetests/conftest.py按 session 粒度提供一个QApplication实例复用已存在的实例避免重复创建任何需要创建 Qt 控件的测试都通过它拿应用实例。Qt 以offscreen平台插件运行因此测试过程中不会有窗口弹出。YASB Cloud 相关测试还额外保证「绝不联网」见 tests/cloud/conftest.py —— 一个autouse的offline_apifixture 把core.cloud.api.API_BASE_URL替换为不可达地址http://127.0.0.1:9从源头阻断对真实服务器的请求。三、测试目录全景每个目录在检查什么tests/目录下共六个子目录职责划分如下表目录检查内容smoke/冒烟测试每个模块都能成功导入每个 widget 的配置 schema 都能构建。widgets/状态栏 widget 的通用规则例如 widget 永远不对自己调用winId()以及逻辑容易出错、值得聚焦测试的 widget如 custom widget 的命令输出、label 与回调。bar/状态栏窗口用每种配置项构建窗口、窗口在屏幕上的位置、自动隐藏、动画与右键菜单以及 adaptive 风格的 islands、rail、border 与边缘曲线在各种组合下的表现。注册为 Windows App Bar 的行为被 fake 掉。win32/ctypes 代码与真实 Windows SDK 对拍以及窗口辅助函数在真实窗口上的测试。cloud/YASB CloudAPI 错误、加密、备份、恢复、设置全部不接触真实服务器。support/测试共享的辅助代码。smoke/导入即零容忍smoke/test_imports.py 用pytest.mark.parametrize(module, core_modules())对src/core下每一个.py模块逐一执行importlib.import_module任何导入期错误语法、循环导入、缺失依赖都会立刻暴露smoke/test_config_schema.py 则遍历core.widgets.registry.WIDGET_REGISTRY中注册的每个 widget断言其validation_schema是一个 pydanticBaseModel子类且能成功生成 JSON Schema同时验证全局的YasbConfig.model_json_schema()可构建。widgets/通用规则 高风险逻辑聚焦widgets/test_native_windows.py 是一类「规则性测试」的代表它通过 AST 扫描所有BaseWidget子类与所有core模块断言任何代码都没有对self调用winId()那会把 bar 里的 widget 连同兄弟控件全部变成原生窗口并验证替代方案get_widget_monitor_hwnd确实不会把子控件变成原生窗口。这种用源码静态扫描来强制架构规则的写法比人工 code review 可靠得多。widgets/test_custom.py 则是「聚焦高风险逻辑」的代表custom widget 允许用户配置任意外部命令并渲染其输出因此测试覆盖了 JSON 输出解析、非 JSON 输出回退、字符串去空格、缺失 key 时显示模板原文而不是崩溃、超长输出截断、hide_empty空结果隐藏、label 与 alt label 切换、带引号参数完整传入、tooltip 格式化与回退、exec回调的模板插值等十余个分支。bar/Bar 窗口与 Adaptive 样式矩阵bar/test_bar.py 以BAR_CONFIGS字典枚举每个会走独立代码路径的配置项底部对齐、padding、adaptive 样式、auto/像素/百分比宽度、fade/slide 动画、模糊圆角、置顶、App Bar、全屏/最大化隐藏、自动隐藏、关闭右键菜单、拉伸关闭等外加几个真实组合逐一对 Bar 做「创建 → 定位 → 显示 → 隐藏」的生命周期验证并断言 App Bar 注册行为是否正确触发还验证了状态栏贴靠屏幕边缘时与 padding 的精确像素关系、自动隐藏管理器、最大化监听、auto-width 管理器、动画是否完整跑完、右键菜单是否包含预期条目。bar/test_adaptive_bar.py 对 adaptive 样式做了穷举式组合测试itertools.product遍历 上/下 × islands 开/关 × 边缘圆角 0/10 × 边框开/关 × 四种布局三组、仅居中、空、含 excluded 项对每个组合用frame.grab().toImage()逐像素断言——widget 不侵入边缘曲线条带、island 精确覆盖 widget、gap 被挖空且 rail 完整、边框正确等。此外还有「island 随 widget 内容增长」「excluded widget 拆分组」「边缘曲线只对全宽 bar 生效」「修改 edgeradius 时 bar 不得位移」「贴近屏幕边缘的 island 吸附到边缘」等行为测试。cloud/离线环境下的云端功能测试cloud/test_footer_reason.py 是README中示例的真实出处完整版本共 5 个用例它验证订阅异常状态下页脚提示语的语义准确性payment_past_due在仍可写时显示 Payment failed不能声称备份已停、只读时显示 Subscription ended、完全关闭时显示 Subscription expired以及no_subscription与subscription_expired的文案。其背后的代码来自 src/core/cloud/ui/window.py 的_reason函数与 src/core/cloud/models.py 的Access模型测试断言的是「提示文案与账号真实状态严格一致」这一产品语义。四、编写测试规则、fixture 与技巧tests/README.md给出了清晰的编写规范在合适的目录下新建名为test_something.py的文件每个测试是一个以test_开头的函数内部用assert做断言。src已在导入路径上由pyproject.toml的pythonpath配置保证直接以core.something导入 YASB 代码。如果测试会创建 Qt 控件通过qappfixture 获取QApplication会话级单例定义在 tests/conftest.py。文件操作使用 pytest 内置的tmp_path需要临时替换某个函数或环境变量时使用monkeypatch这正是上文 cloud 测试把API_BASE_URL换成不可达地址、bar 测试把Win32AppBar换成 fake 的方式。不要调用真实服务器不要依赖硬件。CI 跑在 GitHub 的 Windows 机器x64 与 ARM64上那里没有 GPU、蓝牙或 Wi-Fi。修 bug 时最好的测试是「修复前失败、修复后通过」的那一个——先写失败测试再修代码最后让测试转绿。一个典型示例节选自 tests/cloud/test_footer_reason.pyfrom core.cloud.models import Access from core.cloud.ui.window import _reason def test_never_having_subscribed_is_not_an_expiry(): assert _reason(Access(reasonno_subscription)) No active subscription五、Windows ctypes 校验在编译期抓出 Python 读不到的错误这是 YASB 测试体系里最独特、也是工程价值最高的一部分。背景是ctypes 代码出错时不会抛 Python 异常——如果结构体少了一个字段或函数被声明成返回 4 字节而 Windows 实际返回 8 字节程序只会读到垃圾数据或直接崩溃且没有 traceback。tests/win32/的整套机制就是为了在发布前拦住这类错误。工作原理Python 与 Windows SDK 逐项对拍tests/README.md描述了核心流程对应源码如下收集discovery.py遍历src/core下所有模块用ast静态分析找出全部 ctypesStructure/Union子类、comtypes COM 接口、windll/cdll/oledll绑定的外部函数声明以及大写的整型常量见 tests/win32/discovery.py 的ctypes_structs、com_interfaces、foreign_bindings、win32_constants。生成 C 探针probe.py根据收集结果生成一个 C 程序包含 tests/win32/probe.py 里HEADERS列出的约 50 个 SDK 头文件windows.h、dwmapi.h、wlanapi.h、pdh.h、dxgi.h等用sizeof、offsetof、函数指针签名、vtable 槽位、枚举/常量值逐项输出「SDK 的答案」。编译运行msvc.py用vswhere.exe定位 Visual Studio / Build Tools 安装依次尝试原生与交叉工具链调用vcvarsall.bat拿到环境后以/std:c17编译探针程序并运行得到结构化 JSON 结果见 tests/win32/msvc.py。对比abi.py把 Python 侧的 ctypes 类型归一化为统一的 ABI 描述void/signed int/unsigned int/float/pointer/struct/array/... 字节大小test_structs.py、test_functions.py、test_declarations.py、test_constants.py、test_com.py分别对比结构体布局、函数签名、无restype的调用、常量值、COM vtable 槽位。若编译失败probe.py会按诊断信息把失败项逐步隔离最多 25 轮并单独重试失败项以区分「级联错误」与「真错误」。缓存tests/win32/conftest.py的sdkfixture 以「工具链描述 probe/msvc/specs 源码 请求指纹」的 SHA-256 为 key把探针结果缓存在 pytest 的.pytest_cache中重复运行不重复编译会话结束时还会在终端打印所用的编译器与 SDK 版本pytest_terminal_summary。如果MIB_IF_ROW2少了最后一个字段你会看到sizeof is 1344, the SDKs MIB_IF_ROW2 is 1352哪些名字需要特殊映射specs.py 的角色Python 侧命名与 SDK 不一定一一对应tests/win32/specs.py 专门维护这些映射STRUCTS例如 Python 的WNDCLASS对拍 SDK 的WNDCLASSWSHELLEXECUTEINFO对应SHELLEXECUTEINFOW且字段hIconOrMonitor映射到hIconIP_ADAPTER_ADDRESSES是 SDK 的IP_ADAPTER_ADDRESSES_LH且允许prefixTruePython 只声明前部字段剩余内存由 API 分配尺寸更小也是合法的。VENDORED_DECLARATIONSSDK 根本不声明的类型例如未文档化的user32导出SetWindowCompositionAttribute的载荷ACCENTPOLICY/WINDOWCOMPOSITIONATTRIBDATA、AMD ADL 与 NVIDIA NVML 的结构体、Explorer 通过WM_COPYDATA接收的 32 位NOTIFYICONDATA32布局等。这些声明直接从真实头文件复制而来保证对拍对象不是「第二份手写猜测」。NOT_IN_SDK同样未在 SDK 头文件声明的导出名Everything_*、nvml*、ADL2_*、SetWindowCompositionAttribute、SetTaskmanWindow等。CONSTANT_ALIASES/COM_INTERFACES/UNDOCUMENTED_INTERFACES常量与 COM 接口的别名及未文档化名单。前置条件与跳过策略对拍需要 Visual Studio 或 Build Tools 并安装「使用 C 的桌面开发」工作负载msvc.py通过vswhere -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 / VC.Tools.ARM64检查。没有工具链时这些检查会在本机被跳过设置环境变量YASB_REQUIRE_SDK1可以让它们失败而不是跳过——CI 正是这么做的见第七节。win32/下有两类检查不需要编译器一是导出检查——用到的每个函数必须真实存在于对应 DLL例如user32.dll有GetWindowLongW而没有GetWindowLong后者只是 SDK 头文件里的宏实现在 tests/win32/test_declarations.py 的test_referenced_functions_are_exported二是 tests/win32/test_window_actions.py它注册真实窗口类、创建真实 HWND验证core.utils.win32.window_actions.can_minimize对「普通窗口 / 带最小化按钮的 popup / 无最小化按钮 / disabled」四种窗口的判定并覆盖窗口销毁后的行为。文件职责一览tests/win32/下的文件各司其职README用一张表说清了「哪些该改、哪些不该碰」文件职责是否要编辑test_*.py校验本身仅在需要新增校验种类时specs.pyPython 名与 SDK 名的差异如WNDCLASS↔WNDCLASSW以及 SDK 之外的东西未文档化函数、AMD、NVIDIA是当校验报错要求时known_issues.py已记录但尚未修复的已知问题仅在删除条目时probe.py编写、编译、运行 C 探针程序仅其HEADERS列表当校验要求时msvc.py定位 Visual Studio 编译器否foreign.py、discovery.py在src/core中发现 ctypes 代码否abi.py对比 Python 类型与 C 类型否conftest.py只运行一次探针程序并缓存结果否校验失败对照表看到报错就知道怎么修报错信息含义与修法sizeof is 1344, the SDKs MIB_IF_ROW2 is 1352结构体与 Windows 布局不符修正其字段。argtypes has 4 entries, the SDK takes 5 parameters修正函数的argtypes。restype c_int is signed int(4), the SDK returns signed int(8)修正函数的restype。X returns pointer(8) but has no restype声明restype和argtypes仿照 src/core/utils/win32/bindings 下各绑定模块的写法。user32.dll does not export GetWindowLong调用 DLL 真实导出的名字这里应改为GetWindowLongW。X is not declared by the SDK headers检查拼写若名字正确把该类型所在头文件加进 tests/win32/probe.py 的HEADERSMicrosoft Learn 的 Requirements 一节会列出头文件。只有未文档化的名字才允许放进specs.py的NOT_IN_SDK。known_issues让 CI 保持绿色但只允许「缩水」tests/win32/known_issues.py 记录了已发现但尚未修复的问题使 CI 在问题存续期间保持绿色。它有两条硬规则禁止为消除新失败而添加条目——正确做法是修代码修复某个已记录问题时对应测试会要求删除该条目xfail_if_known使用strictTrue的 xfail问题一旦不再复现就会失败直到条目被删。因此这个文件只会「只减不增」地收缩形成「记录 → 修复 → 删条目」的正向循环。六、CIx64 与 ARM64 双架构守护tests/README.md说明了 CI 的编排真实工作流与之一致.github/workflows/tests.yaml真正的测试工作流。矩阵包含windows-latestx64与windows-11-armARM64Python 3.14安装.[test]依赖并设置YASB_REQUIRE_SDK1保证 Windows SDK 对拍检查在 CI 上必须通过而不是被跳过。pytest 输出同时写入reports/junit.xml与reports/pytest.log由.github/scripts/test_report.py汇总为报告并上传 artifact。注意它通过workflow_call支持被其他工作流复用。.github/workflows/pr-check.yamlPR 检查的总闸门依次执行 Ruff 格式与 lint、Pyright 严格类型检查typeCheckingMode strict、pythonPlatform Windows见 pyproject.toml、复用上面的测试工作流全部通过且非 draft 时才开始 x64/ARM64 的安装包构建。Ruff 失败会生成包含格式 diff 与 lint 详情的注释文本。.github/workflows/pr-comment.yamlbot 评论工作流。它通过workflow_run监听「PR Check」始终从main分支检出脚本因此对该工作流的修改要合并后才生效下载 PR 运行产生的元数据与测试报告用.github/scripts/test_report.py生成评论再由 GitHub Script 智能管理通过则删除旧 bot 评论失败则创建/更新评论。测试若整体崩溃ctypes 调用错误的典型症状评论会说明情况并贴出日志末尾。tests/README.md提到的关键约束「当 PR 失败时 bot 会评论失败项且测试通过前不会构建安装包」在 pr-check.yaml 中体现为build-x64/build-arm64两个 job 均needs: [ruff-lint, typecheck, tests]且if: success()。换言之代码风格、类型、测试三重关卡全绿产物才会产出。七、快速索引继续深入测试配置与标记 pyproject.toml全局隔离与qappfixture tests/conftest.py各目录测试实例 tests/smoke/test_imports.py、tests/widgets/test_custom.py、tests/bar/test_adaptive_bar.py、tests/cloud/test_footer_reason.pySDK 对拍核心 tests/win32/probe.py、tests/win32/msvc.py、tests/win32/specs.py、tests/win32/abi.py、tests/win32/discovery.py被校验的底层绑定代码 src/core/utils/win32/bindingsCI 编排 .github/workflows/tests.yaml、.github/workflows/pr-check.yaml、.github/workflows/pr-comment.yaml一句话总结这套体系的价值smoke与widgets守住 Python 层的可导入性与 widget 行为bar用逐像素断言守住像素级 UI 正确性win32用「编译期 SDK 对拍」堵住 ctypes 这类无声错误cloud在离线沙箱中验证云端语义而 CI 把这一切放大到 x64 与 ARM64 双架构、并把测试通过设为产物构建的前置条件——每一个环节都能被精确复现、定位与修复。赞分享桌面应用【免费下载链接】yasbA highly configurable Windows status bar written in Python.项目地址https://gitcode.com/gh_mirrors/yas/yasb点击查看免费下载相关推荐Sunshine 游戏串流指南3 步把 PC 变成 Moonlight 串流主机Sunshine 游戏串流指南3 步把 PC 变成 Moonlight 串流主机 周五晚上想窝沙发打游戏但 PC 还留在书房。装一个 Sunshine自托音视频后端LiveCharts2 贡献指南测试体系、CI 流水线与代码规范深度解析LiveCharts2 贡献指南测试体系、CI 流水线与代码规范深度解析 本文面向希望为 LiveCharts2一个面向 .NET 全平台 UI 框架的统一数据可视化图表库跨平台SparkyFitness 全栈测试体系实战指南Jest、pytest 与路径感知的 CI 测试流水线SparkyFitness 全栈测试体系实战指南Jest、pytest 与路径感知的 CI 测试流水线 导读 SparkyFitness 是一个横跨前端Vi后端前端移动开发上一篇终极指南5个步骤实现Falco Kubernetes安全监控与完整审计日志集成下一篇别再四处翻找这份 970 公开数据集聚合清单让你按主题快速选数据创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考