Hypothesis 视角下的软件正确性经济学:为什么 Bug 无法避免,以及如何让“找 Bug“变得更便宜
测试开发工具【免费下载链接】hypothesisThe property-based testing library for Python项目地址https://gitcode.com/gh_mirrors/hy/hypothesis点击查看免费下载导读本文围绕 Hypothesis 项目作者在《The Economics of Software Correctness》中提出的核心命题展开——绝大多数非平凡软件必然包含 Bug问题不在于我们不会写正确软件而在于正确软件太贵了。文章将拆解把用户当 QA 部门的真实代价论证唯一可行且正和的质量杠杆是降低发现 Bug 的成本并结合本仓库中 Hypothesis 的源码实现自动生成、自动缩小、失败用例数据库说明它如何具体拉动这根杠杆。先接受一个不愉快的事实你几乎没写过正确的软件《The Economics of Software Correctness》开篇就给出一个直白的论断你很可能从未写过一份真正意义上正确的非平凡软件。这不是对人能力的贬低也不是学术意义上的吹毛求疵——它指的是那种如果有人指出来你自己也会承认确实是 Bug的行为甚至可能是你真正在意的 Bug。作者对此给出几乎百分百的信心每一个非平凡软件里至少有一个 Bug小型库或许可以做到基本无 Bug但写出非平凡且无 Bug 的程序概率趋近于零。为什么答案不是我们不知道怎么写正确软件。事实上人类早就掌握了生产接近正确软件的工程方法——NASA 的航天软件开发流程就是典型代表高密度评审、严格的过程管控、近乎苛刻的验证。但它付出的代价是数量级高于常规开发的工作量过程繁重、节奏缓慢、难以适应需求变更和紧迫工期。所以问题的本质是正确软件太贵了。这里的太贵不是利润少 10% 我们不愿意而是如果软件贵到这个程度没人愿意用我们付得起成本的价格购买它或者如果做这么慢竞争对手两年后就会抢先发布届时没人关心我们。安全关键行业医疗设备、航空之所以能承受这个成本是因为它们的 Bug 代价是数十亿美元、数年的工作、乃至人命——当 Bug 的成本如此之高时花那么多钱买正确性反而是划算的买卖。而对其余绝大多数软件团队来说用户并不愿意为这个级别的正确性付费。于是行业普遍采用了一种便宜得多的测试方法论发布出去看看会发生什么。把用户变成 QA 部门看起来免费实则昂贵当软件带着 Bug 发布用户就事实上成了我们的 QA 部门。文章明确指出这不是道德失败——用户已经用价格表达了正确性不在购买范围内的意愿所以得到不正确的软件是市场的正常结果。真正的问题是用户并不擅长做 QA。这带来的成本链条非常清晰用户不会写好的 Bug 报告。QA 是一种复杂的专业技能连资深开发者都经常写不出像样的 Bug 报告遑论用户。结果是漫长的来回沟通这是 Bug 还是误解真正的 Bug 在哪里整个过程既惹恼用户又消耗开发者和客服的大量时间。用户干脆不报告。一部分用户试用后直接判定软件不能用悄无声息地离开——对难以追踪使用者的软件尤其是库和开源项目来说尤其致命。部分用户是攻击者。他们不但不会报告 Bug还会主动掩盖 Bug 的存在因为它正被用来窃取金钱和数据。由此得出全文的核心经济学结论用户发现的 Bug比用户在见到软件之前被我们自己发现的 Bug 昂贵得多——它们可能带来用户流失、时间损耗与资产被盗全部直接伤害利润。同时由于用户数量众多他们找 Bug 的效率客观上高于我们而完全正确的软件又基本不可能。所以每个团队实质上都在选择某个可接受的缺陷率——它由这条边界决定自己再发现下一个 Bug 的边际成本恰好等于让用户去发现它的成本。缺陷率更高或更低理论上都可以通过调整开发流程赚更多钱。只有两根杠杆让用户更愤怒或让找 Bug 更便宜文章由此给出两条仅有的可行路径让用户对 Bug 更愤怒本质上是把质量成本外部化转嫁给用户的情绪它提高软件质量的方式是让写软件这件事变贵作为商业计划相当糟糕。让找 Bug 更便宜这是作者主张的正确杠杆。它通过提高利润空间来提升软件质量——开发者赢了、用户赢了、公司所有者赢了是真正的正和博弈。因此改变世界的杠杆只有一根打造或寻找能降低发现 Bug 所需努力的工具。Hypothesis 正是这根杠杆的一个实例——它既不是唯一一个也不是唯一需要的那个更好的监控、代码评审、静态分析、改进沟通都同样有效。Hypothesis 如何拉动这根杠杆把找 Bug变成自动化流水线Hypothesis 是 Python 的属性测试property-based testing库。它的核心主张可以表述为与其指望用户报告 Bug不如在发布之前用机器替用户完成海量而笨拙的探索。仓库中的实现把找 Bug拆成了三个自动化的环节恰好对应上述经济学杠杆的每一次拉动。第一环自动生成——把调用函数交给机器传统单元测试要求人手工列举输入Hypothesis 则用given装饰器声明策略strategy由机器生成输入。入门示例见 quickstart.rstfrom hypothesis import given, strategies as st given(st.integers()) def test_integers(n): assert isinstance(n, int)默认情况下 Hypothesis 会运行 100 个随机输入对应max_examples100的默认设置见 _settings.py 中defaultprofile 的定义并自动尝试在生成阶段就偏向有趣的值。这套能力建立在底层一个叫Conjecture的结构化字节流模糊测试引擎之上实现位于 internal/conjecture这正是Hypothesis 是一个 fuzzer 一组让构造属性测试更简单的工具这一设计的落地——构建属性测试库的实质是两件事一个模糊器以及用它构造测试的工具集合。仅仅用随机数据调用函数即 fuzzing就已经能发现大量真实问题因为最普遍的不变量就是软件不应该崩溃或只应以定义好的方式崩溃。一个极具性价比的起步测试模板如下来自 getting-started-with-hypothesis 的思路from hypothesis import given, reject from hypothesis.strategies import integers, text given(integers(), text()) def test_some_stuff(x, y): try: my_function(x, y) except SomeExpectedException: reject()其中reject丢弃已知合法的失败不计入用例预算——这让你能快速区分可预期的异常与真正的 Bug。第二环不变量——把正确翻译成机器可断言的属性纯 fuzzing 之上最简单的第二类不变量是encode/decode 往返一致编码后再解码应当与什么都不做完全等价。文档 encode-decode-invariant 给出了经典的 Run-Length Encoding 示例from hypothesis import given from hypothesis.strategies import text given(text()) def test_decode_inverts_encode(s): assert decode(encode(s)) s这个测试立刻发现了一个 Bug——encode没有正确处理空字符串UnboundLocalError修好后人为删除字符切换时重置计数这行代码测试又以最小反例110定位了缺陷。这展示了不变量测试的价值它把 fuzzing 免费地内嵌进来同时提供了比不崩溃强得多的判定标准。第三环自动缩小shrinking——把复现条件压缩到最小机器生成的反例往往又大又乱直接交给开发者难以阅读。Hypothesis 的集成缩小机制会自动把失败输入压到最短、最简的形式。在 anatomy-of-a-test 展示的运行输出中第一次失败是test_floats_are_commutative(x-10.0, ynan)随后 Hypothesis 一步步把它缩小成x0.0, ynan——从一堆复杂浮点数到一眼可读的最小反例这就是 shrinking 的功劳。底层的实现逻辑是缩小字节流即可缩小生成的数据shrinker 依据越短越简单、同长度时字典序更靠前越简单的规则反复删改字节序列见 how-hypothesis-works 与 shrinker.py。对开发者而言这意味着 Bug 报告从用户复述的一段模糊现象变成了一行可以直接粘贴复现的精确输入。第四环示例数据库——让历史失败自动回归即使找到了 Bug修复后也常担心回归。Hypothesis 会在本地维护一个示例数据库每次失败的用例及其缩小过程中的中间产物都会被保存下次运行测试时先重放历史失败用例再进入随机生成阶段这一流程在 core.py 中由execute_explicit_examples、数据库读取与 shrinking 阶段共同完成。因此你在本地修好 Bug 后再次运行测试会立刻重新触发旧失败验证修复是否有效——相当于把用户将来才可能踩到的坑提前变成了持续回归测试。example注解则提供了源码级的显式回归把已知的边界反例直接写进测试文件如example(0.0, float(nan))它会在任何随机生成之前先执行且不会被缩小。这意味着团队可以把最珍贵的复现条件固化进版本库与代码一同评审、一同演进。成本控制为什么这套自动化不会失控找 Bug 更便宜的杠杆要成立自动化本身也必须便宜。仓库中的 settings 体系_settings.py集中体现了这一点max_examples100单次测试运行的用例预算用例数会因assume/filter丢弃、搜索空间穷尽、发现失败而上下浮动细节见 test-case-count.rstdeadline200ms单用例执行时限防止慢用例拖垮整轮derandomizeFalse与database默认开启日常开发追求随机性与记忆性的平衡内置ciprofilederandomizeTrue、deadlineNone、databaseNone、print_blobTrue在 CI 上改为确定性、可复现、带完整失败信息的严格模式且max_examples可通过register_profile覆盖如扩到 1000。这套设计把机器替用户找 Bug的成本压到毫秒级同时把失败信息、复现条件和回归保障完整保留下来——这正是经济学杠杆在工程上的具体形态用机器时间换人工时间。反躬自省内疚解决不了系统性问题文章在结尾给出了一个反直觉但重要的观点靠感觉愧疚 拼命努力写正确代码 失败后自责并不能提高找 Bug 的能力——这似乎是行业现状却深具反效果。系统性缺陷无法靠个体行动修复发布更好软件的唯一办法是改变经济学让做得更好这件事变得可行。Hypothesis 的意义正在于此它不要求开发者突然获得写出无 Bug 软件的超能力也不要求用户突然学会专业 QA——它只是把发现 Bug这个昂贵环节的大部分机械劳动自动化了。结合更好的监控、代码评审、静态分析等手段团队完全可以在不牺牲工期与利润的前提下把可接受的缺陷率边界向更低处推移。结论与行动建议《The Economics of Software Correctness》给出的核心框架可以浓缩为三句话Bug 是经济现象不是道德问题——非平凡软件必然含 Bug因为正确性太贵而用户不愿为此付费用户是昂贵的 QA——他们不擅长报告、可能沉默流失、甚至可能是攻击者因此用户发现 Bug 的代价远高于发布前发现唯一正和杠杆是降低找 Bug 的成本——Hypothesis 正是这样一根杠杆用策略自动生成输入、用不变量自动判定对错、用 shrinking 自动压缩反例、用示例数据库自动回归让发现下一个 Bug的边际成本降到接近零。如果你想在项目里落地这套经济学从仓库的 quickstart.rst 与 usage.rst 出发按先 fuzz 入口函数不崩溃→ 再断言 encode/decode 往返 → 最后对复杂领域对象写定制策略的顺序推进是最省力也最快见效的路径。赞分享测试开发工具【免费下载链接】hypothesisThe property-based testing library for Python项目地址https://gitcode.com/gh_mirrors/hy/hypothesis点击查看免费下载相关推荐Erlang/OTP Common Test 测试哲学为什么测试无法证明程序正确以及如何写出真正能发现 Bug 的测试套件Erlang/OTP Common Test 测试哲学为什么测试无法证明程序正确以及如何写出真正能发现 Bug 的测试套件 在 Erlang/OTP 中编程语言语言运行时标准库编译器并发编程Plate 构建性能实践为什么避免 Barrel 导入以及 Next.js optimizePackageImports 的正确用法Plate 构建性能实践为什么避免 Barrel 导入以及 Next.js optimizePackageImports 的正确用法 本文基于 Plate前端富文本UI组件ComfyUI-MultiGPU如何突破单卡显存限制实现AI模型的高效多GPU部署ComfyUI MultiGPU如何突破单卡显存限制实现AI模型的高效多GPU部署 在AI图像生成和视频处理领域GPU显存不足已成为制约模型规模和应用效人工智能大模型深度学习本地部署上一篇彻底解决React依赖比较难题use-deep-compare-effect全指南下一篇StringZilla 开源项目安装与使用指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

PaddleSpeech 英中语音翻译(ST)实战指南:TED En-Zh ST1 的数据、Transformer+ASR 多任务训练与 Char-BLEU 评测

PaddleSpeech 英中语音翻译(ST)实战指南:TED En-Zh ST1 的数据、Transformer+ASR 多任务训练与 Char-BLEU 评测

人工智能语音音频 【免费下载链接】PaddleSpeech Easy-to-use Speech Toolkit including Self-Supervised Learning model, SOTA/Streaming ASR with punctuation, Streaming TTS with text frontend, Speaker Verification System, End-to-End Speech Translation and Keyword…

2026/9/25 2:21:04 阅读更多 →
dirsearch-master实战指南:命令行目录扫描器深度配置与避坑

dirsearch-master实战指南:命令行目录扫描器深度配置与避坑

简介:本资源是开源目录扫描工具 Dirsearch 的完整源码包,面向渗透测试初学者、网络安全从业者及CTF备赛人员,用于自动化探测网站敏感目录与文件路径,辅助发现未授权访问、备份文件泄露等常见Web安全风险。压缩包共217个文件&#…

2026/9/25 2:21:04 阅读更多 →
Flutter三方nonce库鸿蒙适配:从随机数到防重放的完整改造指南

Flutter三方nonce库鸿蒙适配:从随机数到防重放的完整改造指南

上周给一个准备上架应用市场的 Flutter 团队做安全评审,iOS 和 Android 双端压测都过了,结果在鸿蒙真机上出现了一个让我坐不住的现象:客户端在登录后发出带 nonce 的请求,服务端竟然放行了同一个 nonce 的第二次重放。进一步排查…

2026/9/25 2:21:03 阅读更多 →

最新新闻

龙芯GPU平台首个软件版本发布:支持OpenCL 3.0与CUDA兼容,AI推理部署实战解析

龙芯GPU平台首个软件版本发布:支持OpenCL 3.0与CUDA兼容,AI推理部署实战解析

1. 龙芯GPU平台首个软件版本到底发布了什么龙芯发布自研通用GPU加速计算平台首个软件版本,这条消息在圈子里传开的时候,我第一反应是去翻它的技术白皮书和开发者文档。原因很简单:硬件参数可以堆,但软件栈能不能跑通、能不能让开发…

2026/9/25 10:27:14 阅读更多 →
PyCharm必装AI编码工具大盘点:TaoToken统一Key接入与settings.json配置骨架

PyCharm必装AI编码工具大盘点:TaoToken统一Key接入与settings.json配置骨架

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/25 10:27:14 阅读更多 →
Vibe Coding氛围编程系列:AI 模型  服务选择之那个模型编程能力最强?TaoToken 统一 Key 配置实测

Vibe Coding氛围编程系列:AI 模型 服务选择之那个模型编程能力最强?TaoToken 统一 Key 配置实测

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/25 10:27:14 阅读更多 →
TaoToken 统一 Key 接入 Cline:settings.json 配置骨架与连通性验证

TaoToken 统一 Key 接入 Cline:settings.json 配置骨架与连通性验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/25 10:27:14 阅读更多 →
SWE-Explore 基准解读:Coding Agents 如何探索 Repositories 与 TaoToken 配置骨架

SWE-Explore 基准解读:Coding Agents 如何探索 Repositories 与 TaoToken 配置骨架

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/25 10:27:14 阅读更多 →
Atlas 300V 24G AI推理加速卡部署YOLO全流程:模型转换、ATC优化与性能调优

Atlas 300V 24G AI推理加速卡部署YOLO全流程:模型转换、ATC优化与性能调优

1. Atlas 300V 24G这张卡到底是怎么回事先说结论:atlas 300V 24G确实是运算加速卡,但更准确的说法是“AI推理加速卡”。它不带显示输出接口,不能像显卡那样插上就出画面,它被设计出来的唯一目标,就是把训练好的神经网络…

2026/9/25 10:26:14 阅读更多 →

日新闻

AI元人文:从工具使用到思维重构的深度探索

AI元人文:从工具使用到思维重构的深度探索

最近半年我一直在琢磨一件事:AI元人文到底是什么?说白了,就是“用元视角重新审视人与AI的关系”,也在“探索AI如何反向逼着我们发现自己的思考边界”。标题里的“元探索”,在我看就是一层套一层的追问——当你用AI解决…

2026/9/25 0:00:41 阅读更多 →
Python+CNN车牌识别实战:从数据预处理到模型训练与部署

Python+CNN车牌识别实战:从数据预处理到模型训练与部署

简介:基于Python与卷积神经网络的车牌识别项目,面向计算机视觉初学者及智能交通开发者,目标是帮助用户掌握从数据预处理、模型构建到实际部署的完整流程。压缩包共25个文件,包含jpg/png图像样本、py训练脚本、md说明文档、dat数据…

2026/9/25 0:00:41 阅读更多 →
Vim基础操作全攻略:保存退出、模式切换与高频命令实战

Vim基础操作全攻略:保存退出、模式切换与高频命令实战

1. 项目概述1.1 核心需求解析今天聊聊Vim。写这个题目的原因是:几乎每个后端开发者、运维人员、数据工程师某天都会遇到一个场景——深夜加班,服务器登录界面只有黑底白字,编辑器只有vi/vim,你必须在五分钟内完成一次配置修改并保…

2026/9/25 0:00:41 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/24 14:34:13 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/24 9:10:42 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/24 14:33:56 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/24 12:50:34 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/24 14:33:48 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/24 12:49:17 阅读更多 →