最近把项目里的代码补丁任务交给Qwen2.5-Coder-14B,发现它特别喜欢给函数生成冗长的mock对象,尤其是涉及数据库操作时,明明可以直接用内存sqlite,它非要mock一个假的repository层。跑测试的时候,覆盖率倒是上去了,但实际逻辑很多没测到。我试过在prompt里强调“少用mock、多写集成测试”,效果还是不稳定。想问下各位,是我系统提示词写得太笼统,还是这个模型本身对测试风格的理解就偏向保守?另外,有没有人对比过它和DeepSeek-Coder在这类任务上的差异?我用的vLLM部署,温度0.2,max_tokens设的2048。
用Qwen2.5-Coder写单元测试总生成一堆无用mock,是我姿势不对吗?
全部回复
共 57 条试试把“少用mock”改成“禁止mock数据库层,必须用内存sqlite”,指令具体点效果会好不少。
说实话我觉得跟模型关系不大,主要是prompt里对“数据库操作”的边界定义没给清楚,我后来直接甩给它一段“用sqlite内存模式重写repo接口”的示例代码,效果立刻就不一样了。另外温度0.2对代码生成来说有点偏保守,我试过拉到0.6反而能跳出那种模板化的mock套路。DeepSeek-Coder我也跑过类似任务,它更倾向于直接生成可执行的测试函数,但偶尔会漏掉异常分支,两者各有各的坑吧。
我这边用Qwen2.5-Coder也遇到过类似情况,感觉它默认把“测试”理解成了隔离优先,尤其涉及IO就条件反射式地mock。后来在系统提示里直接塞了个内存sqlite的示例,并明确说“除非外部HTTP,否则别mock”,才稳定不少。DeepSeek-Coder相对更愿意写真实调用,但有时又太放飞,边界case容易漏。你温度0.2已经挺低了,可能问题更多在提示词的结构而不是模型本身。
我也遇到过类似情况,Qwen2.5-Coder确实倾向于mock掉外部依赖,感觉它训练数据里单元测试的范式偏保守。你可以试试在prompt里直接给一两个few-shot示例,展示用sqlite内存库测repository的写法,比单纯说“少用mock”管用得多。另外温度0.2可能太低了,稍微调到0.4左右让它有点发挥空间,配合max_tokens给足,生成的测试会灵活一些。DeepSeek-Coder我也用过,它在集成测试风格上确实更放得开,但逻辑覆盖的严谨度感觉稍弱一点,各有取舍吧。
这个现象我也遇到过,Qwen2.5-Coder在测试生成上确实有点“mock上瘾”,特别是你提到数据库那块,它默认就会往repository层去套。我后来发现一个比较管用的办法是在系统提示里直接给它一个具体的测试范例,比如“所有涉及sqlite的测试都用:memory:,禁止mock任何数据访问层”,比单纯说“少用mock”要有效得多。温度0.2其实已经挺保守了,但问题可能不在随机性上,而是模型对“测试意图”的理解有偏差,它更倾向于生成看起来完整、结构工整的测试代码,而不是真正去覆盖业务逻辑。我对比过DeepSeek-Coder,它在集成测试风格上确实稍微好一点,但也不是完全没这个问题,只是mock比例低一些。max_tokens设2048可能也偏大了,模型有足够空间去铺陈那些冗余的mock结构,试试压到1024甚至768,逼它写紧凑一点。另外你可以在prompt里加一句“如果测试代码超过30行就说明写错了”,这种约束有时候比正面指令更管用。
我拿Qwen2.5-Coder-7B也遇到过类似情况,感觉这模型对“测试”的理解就是先把依赖隔离开,至于测没测到真逻辑它不太管。后来我在prompt里直接给了两个示例,一个用sqlite内存库、一个明确禁止mock某个类,稳定性好了不少。温度0.2其实影响不大,关键还是few-shot约束。DeepSeek-Coder我试得少,但印象里它更倾向写短小的直接断言,mock确实少一些。
温度调到0.2确实容易让它保守,试试0.7加few-shot示例,直接给它看内存sqlite的测试写法。
这问题挺典型的,Qwen2.5-Coder在测试生成上确实有点“防御性编程”的倾向,感觉它训练数据里mock-heavy的测试代码占比不低。我拿它和DeepSeek-Coder对比过,后者在同样提示下更愿意写真实调用,但代价是偶尔会生成跑不通的测试,得手动修。你温度0.2其实已经挺保守了,可以试试调到0.5左右,让它别那么死板地套模板。另外系统提示词可以更具体点,比如直接写“涉及数据库时优先用sqlite内存库,禁止mock Repository”,光说“少用mock”太虚了,模型抓不住边界。还有个歪招是在prompt里塞一两个你满意的测试样例当few-shot,效果比纯文字指令稳不少。max_tokens 2048有时候会截断复杂测试的生成,导致它草草收尾用mock凑数,可以适当放宽到4096试试。
这个模型确实有这毛病,我拿它生成接口测试也老爱mock一堆东西,明明内存sqlite更直接。你试试在prompt里直接给个反面例子,比如“不要像这样mock repository”,比单纯说少用mock管用。DeepSeek-Coder在这块我体感更偏向写真实依赖的测试,但生成速度慢一些。温度0.2其实已经偏保守了,调到0.4反而有时能跳出固定套路。
温度调到0.1试试,Qwen2.5-Coder确实爱mock,我一般直接给few-shot示例才管用。
我也遇到过类似情况,Qwen2.5-Coder确实有种“防御性编程”的倾向,宁可mock满天飞也不愿意碰真实依赖。后来我把system prompt改成明确禁止mock数据库,并指定“用pytest.fixture + sqlite内存库”,才勉强稳住。温度0.2其实已经挺低了,再降可能影响生成多样性,感觉问题更多在提示词的约束力上。DeepSeek-Coder我没深度对比过,但它对集成测试的偏好似乎稍好一些,你可以拿同一个仓库跑一批试试。
温度调到0.7试试,0.2太死板了,模型不敢跳出mock套路。
我也遇到过类似情况,Qwen2.5-Coder确实有点“mock依赖症”,感觉它训练时见到的测试代码里mock比例太高了。后来我把提示词拆开写,明确说“除非有外部HTTP调用,否则一律用真实依赖”,效果好了不少。温度0.2其实偏低了,试试调到0.4到0.6,生成风格会灵活一点。DeepSeek-Coder在这块更倾向写轻量级集成测试,但生成速度慢一些,看你更在意哪头。
温度0.2确实容易让模型反复走保守路线,mock多了它觉得“安全”。我一般会把提示词写成“数据库相关测试用sqlite内存实例,禁止mock repository”,并且给一两个few-shot示例,效果比单纯说“少用mock”稳不少。DeepSeek-Coder在测试生成上更爱直接调真实依赖,但有时又过于激进,得看项目容忍度。你这套vLLM配置可以先把温度提到0.4试试,max_tokens 2048对长测试文件可能偏紧。
温度0.2确实容易让它往保守方向走,模型会倾向于选最“安全”的写法,mock一堆东西至少不会报错。我一般会把提示词拆成两步:先让它列测试点,再针对每个点单独生成,比一次性丢整个函数效果好不少。DeepSeek-Coder在这方面也差不多,但它在明确说了用sqlite之后会更听话一些,可能跟训练数据里集成测试样本多少有关。可以试试把max_tokens调小点,逼它别写太啰嗦的东西。
我最近也在用Qwen2.5-Coder-14B做类似的事,确实有同感,它生成mock的倾向特别强,尤其是碰到依赖注入的类,恨不得每个接口都给你造个假的。我试过把系统提示词写得很细,比如“优先用真实依赖、能跑内存数据库就别mock”,但效果只能说时好时坏,感觉它对“测试意图”的理解还是偏保守,可能训练数据里mock-heavy的单元测试占比太高了。温度0.2其实已经挺低了,再降可能输出会变呆,我一般会加一句“如果被测函数涉及DB,请用sqlite内存连接并建表”,这样命中率会高一些。DeepSeek-Coder我对比过,它在生成集成测试风格上稍微好一点,但也不是完全听话,偶尔也会给你套一层mock。另外max_tokens 2048可能不够它把完整测试文件写出来,截断后它容易回头补mock凑逻辑,你可以试着提到4096看看。还有个歪招,在prompt里直接给一个你满意的测试样例当few-shot,比单纯说“少用mock”管用不少。
这个现象我也遇到过,感觉跟模型本身的训练数据分布有关系。Qwen2.5-Coder在代码补全任务上确实偏向保守风格,因为它的训练语料里大量开源项目的测试就是疯狂mock,模型只是学到了这个模式而已。你光在prompt里说“少用mock”其实效果有限,我试过更狠的办法,直接在system prompt里给一个具体的反面例子,告诉它“像这种mock repository的写法是错的”,然后附上你想要的sqlite内存测试模板,这样收敛会快很多。温度0.2其实已经挺低了,问题不在采样上。max_tokens 2048对生成测试来说够用,但如果它前面写了一大堆mock setup,后面真正的assert就没空间了,可以试试降到1024逼它精简。DeepSeek-Coder我对比过,它在测试风格上确实更倾向于直接调用真实依赖,尤其是V2版本,但代价是有时候生成的测试跑不起来,需要手动修。另外你可以试试在prompt里明确要求“禁止出现unittest.mock或MagicMock”,这种硬约束比“少用”这种模糊表述有效得多。