既然采集数据又坏了,我就逼 AI 写了极高强度的回归测试

数据又坏了,这次不是 API 频率限制,也不是反爬策略升级,是我自己写的清洗逻辑里一个该死的边界条件没处理好。凌晨两点半,看着数据库里那堆被错误截断、字段错位的脏数据,胃里一阵翻腾。这不是第一次了,但这次损失的是客户那边等着要的实时舆情数据,明天早上九点就要交付。修复脚本花了二十分钟,但修复数据、重新跑历史任务,又搭进去三个小时。天快亮了,我瘫在椅子上,脑子里就一个念头:这种低级错误,绝不能再有第二次。

十年前,2016年那会儿,我写爬虫哪管什么测试。能跑通、能抓到数据就是胜利,出错了就人肉盯着日志改,靠的是熬夜硬扛。那时候的“测试”就是多跑几遍,凭感觉。后来团队大了,2019年搞交付,倒是弄过一阵子单元测试,但太耗时间,业务催得紧,往往第一个迭代写完,后面就没人维护了,测试代码比业务代码烂得还快。最后测试成了摆设,大家还是靠“人肉回归”——也就是出事了再加班修。现在回想,那几年赚的流水,有多少是填了这种“人肉测试”和“紧急修复”的坑?身心俱疲,根源就在这里。

这次,我不打算再用人肉了。我要让 AI 来干这个脏活累活,而且要干到极致。我的目标不是写几个简单的断言,是生成一套极高强度的、覆盖各种边角案例的回归测试集,把我这个数据采集清洗管道,从入口到出口,每一个环节都拿压力测试机一样的用例轰一遍。

具体怎么做的?我先用自然语言把这次出错的场景、数据格式、以及我怀疑的其他潜在风险点(比如编码问题、特殊字符、空值、数组越界、日期格式混乱)描述给 GPT-4。我不让它直接写代码,我让它先输出测试用例设计表:用例编号、测试数据(要求极端,比如超长字符串、全是emoji、嵌套的JSON里套着XML)、预期输出、要覆盖的函数或模块。这一步是关键,AI 在穷举“恶心”数据方面,想象力比人类丰富得多。它给出了三十多个用例,其中一半是我根本没想到的“阴间”数据组合。

然后,我让它根据这个用例表,生成 Pytest 代码。这里有个技巧,不能让它生成一个巨型的、难以维护的 test.py。我要求它按模块和风险类别,拆分成多个测试文件,并且使用 pytest 的 parametrize 装饰器来参数化驱动。这样,每个测试文件结构清晰,增加新用例只要往参数列表里加数据就行。AI 生成的初始代码有瑕疵,比如有些导入路径不对,或者对一些内部工具函数的 mock 方式不准确。我不直接改代码,我把错误信息反馈给它,让它自己修正。来回几个迭代,一套基于参数化、覆盖了网络请求模拟(用 pytest-httpx)、数据库临时环境(用 pytest-docker)、以及各种畸形数据输入的测试框架就搭起来了。

跑起来那一刻,感觉像给代码上了刑。绿色的小点一个个亮起,但也有几个红了。红的点不是这次修复的问题,是挖出了两个更隐蔽的历史遗留隐患——一个是在处理某种特定编码的 HTML 实体时可能丢失信息,另一个是多线程环境下对某个共享状态的处理有极小概率的竞争条件。冷汗下来了。如果不是这套 AI 生成的“暴力测试”,这两个炸弹不知道什么时候会炸。

搞完这一切,窗外已经大亮。耗时?从构思到测试全部通过,大概五个小时。看上去比直接修复数据多花了两小时,但这五个小时是投资,不是消耗。以后每次代码改动,我只需要点一下“pytest”,几分钟内,就能知道我的改动有没有捅破以前任何一扇窗户。这种安全感,是以前熬夜死磕根本给不了的。

慢就是快。以前总觉得写测试拖慢开发速度,现在明白了,没有测试的“快”,是虚假的、危险的快,每一次“快”都在债务上记了一笔高利贷,迟早要连本带利还回来,而且往往是在你最累、最不想还的时候。稳就是赢。对于我这种靠交付质量和可靠性吃饭的超级个体来说,系统稳定、不出篓子,就是最大的竞争力。AI 把我从重复的、低层次的测试用例编写中解放出来,让我可以去思考更复杂的测试策略和架构问题。这次教训,值了。

© 版权声明
THE END
喜欢就支持一下吧
点赞36 分享