:测试与日志如何让返工问题可复现)
本篇直接复用上一篇report_job.py的job_key、load_completed_items()和状态标记并把固定的tests/fixtures/sync.db作为输入。测试验证报告重跑语义日志记录同一任务键的现场上一篇的任务状态由此成为本篇断言对象。客户说“今天不行了”时我们才能还原输入版本与失败位置。一、优先测试纯规则与边界importunittestfromdecimalimportDecimalfrompathlibimportPathfromtempfileimportTemporaryDirectoryfromunittest.mockimportpatchimportreport_jobdefnormalize_amount(raw:str)-Decimal:valueDecimal(raw.replace(,,).strip())ifvalue0:raiseValueError(negative amount)returnvalue.quantize(Decimal(0.01))classAmountTests(unittest.TestCase):deftest_comma(self):self.assertEqual(Decimal(1234.50),normalize_amount(1,234.5))deftest_negative(self):withself.assertRaises(ValueError):normalize_amount(-1)classMarkerTests(unittest.TestCase):deftest_second_run_reuses_completed_report(self):withTemporaryDirectory()asfolder:markerPath(folder)/job.donemarker.write_text(sha256abc\n,encodingutf-8)withpatch.object(report_job,marker,marker):self.assertEqual(0,report_job.main())self.assertEqual(sha256abc,marker.read_text().strip())deftest_fixture_is_report_input(self):rowsreport_job.load_completed_items(Path(tests/fixtures/sync.db))self.assertEqual([A-1042],[row[0]forrowinrows])if__name____main__:unittest.main()运行与输出示例$ python -m unittest -v test_comma ... ok test_negative ... ok二、日志记录事件不堆自然语言importjsonimportlogging logging.basicConfig(levellogging.INFO,format%(message)s)logging.info(json.dumps({event:file_finished,file:orders-202607.csv,accepted:248,rejected:7,},ensure_asciiFalse))运行输出{event:file_finished,file:orders-202607.csv,accepted:248,rejected:7}日志保留任务键、脱敏文件标识、步骤、耗时、数量和错误类别。原始内容只在客户授权的隔离目录保存。三、建立最小复现包每个故障只保留触发问题的最小脱敏输入、配置、程序版本、命令和期望/实际结果。修复后先增加回归测试再重新构建交付物避免同类问题反复出现。四、为什么测试与日志不能互相替代测试在发布前回答“我们已知的规则是否仍成立”日志在客户现场回答“这次运行究竟走了哪条路径”。只有测试无法解释未知输入只有日志每次修改都要靠人工重演。二者用job_key、事件名和错误类别共享词汇现场事件才能迅速映射到对应回归用例。日志应记录事实不记录散文。eventreport_publish_failed、任务键、步骤、耗时、计数和异常类型可以稳定检索一整句随版本变化的描述很难聚合。业务字段要白名单化或摘要化不能为了排错默认记录订单明细。记忆点是测试保存预期日志保存路径复现包把两者扣在一起。五、从故障到回归的闭环最小复现包包含触发问题的脱敏输入、配置摘要、程序版本、执行命令、期望与实际结果。先用它写一个会失败的测试确认测试确实捕获原故障再修复并运行全套测试。否则“修好了”可能只是换了一个无法复现的环境。对定时报告优先覆盖重复运行、旧标记、损坏数据库、排序稳定性和磁盘异常。结构化日志测试不应断言时间戳而应解析 JSON 后断言关键字段避免测试因无关格式变化而脆弱。下一篇将复用这些测试和事件协议把工程打包成 Windows 可执行文件并在诊断包中保留相同job_key。测试分层能降低维护成本。纯金额规则使用单元测试数据库到日报使用临时目录的集成测试打包后的命令再做少量端到端测试。若每个场景都启动完整浏览器反馈会变慢且故障难定位若只有纯函数测试又覆盖不到路径、编码和事务。测试金字塔的目的不是追求某个比例而是让失败尽量指向最小责任边界。日志同样需要契约测试每一行必须是合法 JSON包含事件、任务键、版本和级别异常事件必须有稳定错误码。人类可读消息可以变化错误码不应随措辞改变。轮转策略和保留天数也要在交付配置中说明否则一个长期定时任务最终可能因为日志占满磁盘而失败。可观察性本身也会消耗资源必须像业务数据一样管理生命周期。 本文把纯规则测试、结构化事件和最小复现包连成维护闭环让远程故障从描述问题变成验证问题。 你维护自动化脚本时更缺少测试样例、现场日志、版本记录还是脱敏复现数据 关注《Python 自动化接单实战》下一篇继续解决 Windows 客户没有 Python 环境时的桌面交付。参考来源Dev.toThe Friction Is a FeatureHacker NewsMeasuring developer productivity with DX Core 4