ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

用DeepSeek自动生成接口测试用例:Python自动化测试提效实践

用DeepSeek自动生成接口测试用例:Python自动化测试提效实践 简介这是一套面向测试工程师的 AI 测试用例生成与优化工具基于 Python 构建能够自动解析 Markdown、Word、Text 等格式的需求文档先生成测试点再将其转化为完整测试用例覆盖功能、性能、安全等 15 种测试类型同时支持对已有 Excel 用例进行完整性、详细度与准确性的智能优化。资源以 RAR 压缩包发布共 29 个文件、约 55KB其中包含 Python 源代码、编译后的 pyc 字节码文件以及 Docker 部署配置、依赖清单、说明文档与示例需求文档等结构清晰便于快速上手。目前已有 10341 人学习下载适用于测试工程师快速生成用例、团队优化既有用例库以及自动化测试脚本的前期准备也可用于测试用例的管理与维护。通过源码可以了解工具的前端页面、核心处理模块、配置管理方式并快速完成本地或 Docker 部署在此基础上进行二次开发灵活融入现有测试流程。 最近在帮团队搭测试工具链最耗时间的就是手工写测试用例。接口几十个、参数组合上百种全部人手写根本不现实而且写出来的用例质量全看个人状态——状态好覆盖率高状态差漏一堆边界值。后来我把DeepSeek接进了基于Python的自动化测试流程里用它来做测试用例的生成和优化实测下来用例覆盖率提升明显而且生成时间基本可以忽略不计。这篇文章就把我这套方案的完整思路、核心代码和踩过的坑都整理出来给正在做AI自动化测试落地、或者想把手头测试用例生成效率提上来的同学一个可以直接抄的参考。这套方案适合谁如果你已经在用pytest、selenium、appium这类Python测试框架但对AI生成测试用例还停留在“听说过、没试过”的阶段或者试过但生成结果没法直接用那这篇文章刚好对路。我会把从API调用、提示词设计、用例校验到pytest动态注入的完整链路都拆开讲一遍。1. 为什么想到把DeepSeek接进自动化测试链路1.1 手工写用例的三个核心痛点先说痛点。做接口自动化测试的同学应该都有体会写用例的时间通常远超跑用例的时间。我统计过我们团队的情况一个中等复杂度的订单接口字段大概二十几个涉及正常流程、异常参数、边界值、权限校验、依赖状态组合手工写完一套像样的用例至少大半天而且大概率还是会有遗漏。第二个痛点是维护成本。接口一迭代参数变了、返回结构改了手工维护用例集非常痛苦有时候为了赶版本测试用例就更新不及时最后变成跑了个寂寞。第三个痛点是思维惯性。写久了之后用例容易固化在常见路径上边界值和异常组合反而是最容易漏的地方。这部分靠人肉头脑风暴很难持续覆盖但恰恰是线上故障的高发区。1.2 为什么选DeepSeek而不是本地规则引擎在做方案选型的时候我其实是先看了两条路。一条是传统的规则引擎比如用JSON Schema自动生成边界测试数据配一些模板和策略。这条路的优点是稳定、可控、可解释但缺点也很明显它需要你事先把规则写全本质上还是在用人力换效率只是换了个形式。另一条就是用大模型来做生成。DeepSeek在这个场景下的优势是理解能力强它能直接读懂接口描述、字段含义甚至注释然后推理出合理的测试场景。而且它的API成本很低输出速度也快一次生成几十条用例也就几秒钟的事。当然它也有缺点比如输出格式偶尔不稳定、会一本正经地编造不存在的字段这些问题我在后面会给出解决方案。对比下来我的判断是规则引擎适合做兜底校验大模型适合做发散生成两者结合是最稳的落地方式。实际项目里我先让DeepSeek根据接口文档批量生成候选用例再用脚本做格式校验和字段合法性校验不合规的直接丢弃或者重新生成最后落到pytest里执行。1.3 整体技术链路长什么样我的这套工具核心链路很简单概括起来就是四步读取接口定义 → 调用DeepSeek生成候选用例 → 脚本校验与清洗 → 动态注入pytest执行。工具本身用Python写因为Python在测试领域生态最成熟pytest、requests、allure这些现成的库都能直接用上。整个项目结构也很轻量核心模块就三个一个负责调DeepSeek API一个负责解析和校验模型返回的用例一个负责把用例动态注入pytest并执行。部署也很简单一台普通的开发机就能跑不需要单独搞GPU服务器。2. DeepSeek API调用与生成参数设置2.1 基础调用方式DeepSeek的API接口是OpenAI兼容格式的这意味着如果你之前用过OpenAI的SDK基本可以无缝切换。我自己日常用requests直接调HTTP接口这样少一层依赖方便排查问题。import requests import json def call_deepseek(prompt, temperature0.7, max_tokens4096): url https://api.deepseek.com/chat/completions headers { Content-Type: application/json, Authorization: fBearer {api_key} } payload { model: deepseek-chat, messages: [ {role: system, content: 你是一名资深测试开发工程师擅长编写高质量的测试用例。}, {role: user, content: prompt} ], temperature: temperature, max_tokens: max_tokens, stream: False } response requests.post(url, headersheaders, jsonpayload, timeout60) response.raise_for_status() return response.json()[choices][0][message][content]这里有几个重点要说明一下。stream: 我测试过生成完整返回单次接口耗时大概2到5秒考虑到网络波动最好设置60秒超时避免连接卡死。max_tokens: 测试用例是一次性给较多的交互建议直接设4096因为DeepSeek的api一次返回上限很宽裕你可以让模型一次性返回整个测试用例集合降低调用次数与成本。另外有一点要注意生产环境中不要用同步阻塞方式跑大批量生成否则很容易卡在某一次网络抖动上建议后面接一个重试机制。我实际是把调用函数包了一层指数退避重试的装饰器尤其是报429限流或者503超时的时候稍等几秒就正常了。2.2 影响生成质量的四个关键参数DeepSeek的API参数不多但每个参数的影响都很大。我整理了一张表直接说结论参数推荐值影响说明temperature0.6~0.8值越高生成的场景越发散但也越容易出现编造字段值越低越保守越不会漏边界但可能漏场景max_tokens4096保证一次能返回完整用例集太短会被截断top_p0.9左右与temperature联动控制采样多样性我一般固定0.9不再额外调frequency_penalty0测试用例生成不需要避免重复用词所以这个参数不用开我踩过的一个坑就是一开始把temperature拉到了1.2结果模型开始“放飞自我”编出了好几个接口里根本不存在的字段比如给订单接口加了个discount_level字段看着挺像那么回事但一校验就全挂了。后来我把temperature压回0.7情况立刻好转。这说明大模型生成测试用例不是越“聪明”越好要有一定的约束感。2.3 提示词设计是成败的关键提示词设计这个事我认为占了整个工具效果权重的七成以上。如果你直接甩给模型一句“帮我写几个测试用例”它确实能给你写但写出来的基本都是教科书级别的通用用例放到你的系统里完全没法用。我在实战中总结了一套提示词配方核心是给足上下文和强约束。一段完整的提示词通常包含角色设定、被测接口的完整信息、期望输出的用例格式、覆盖场景的具体要求、禁忌说明。prompt f 你是一名资深测试开发工程师请根据以下接口定义生成测试用例。 接口信息 - 接口路径: {path} - 请求方法: {method} - 请求参数: {params} - 鉴权方式: {auth} - 关键约束: {constraints} 要求 1. 覆盖正常流程、异常参数、边界值、鉴权失败、依赖状态五类场景。 2. 每条用例必须包含用例名称、前置条件、请求参数、期望状态码、期望响应断言。 3. 参数值要具体不要使用合法值这类占位符。 4. 只输出JSON数组不要输出任何解释性文字。 5. 不要编造接口定义之外的字段。 6. 每条用例之间用英文逗号分隔保持JSON合法。 请直接输出结果 这里最关键的是第4条和第5条。第4条保证输出能直接解析第5条抑制模型编造字段。实际跑下来加了这两条约束之后解析失败率从最初的30%降到了5%以内。另外我还会在案例较多时把接口的返回示例也塞进提示词里让模型依据返回结构来设计更准确的断言这样比光看参数列表生成出来的断言要准得多。比如接口返回的是一个分页对象模型在看到示例后自然会把“page”和“total”字段纳入断言避免断言到一堆不存在的顶层字段。3. 测试用例工程化落地与优化实践3.1 从JSON解析到pytest动态注入模型生成完JSON数组之后不是直接就能用的还要过一道清洗校验。这一步我写了一个validate_case函数负责做三件事格式校验、字段白名单校验、参数类型校验。import json import pytest def parse_and_validate(raw_content, valid_fields, required_fields): try: cases json.loads(raw_content) except json.JSONDecodeError as e: print(f[ERROR] JSON解析失败: {e}) return [] valid_cases [] for idx, case in enumerate(cases): # 格式校验必须包含关键字段 if not all(k in case for k in [name, method, url, params]): print(f[WARN] 第{idx}条用例缺少关键字段已丢弃) continue # 字段白名单校验不允许出现接口定义之外的字段 if not set(case.get(params, {}).keys()).issubset(set(valid_fields)): print(f[WARN] 第{idx}条用例包含非法字段已丢弃) continue valid_cases.append(case) return valid_cases清洗通过之后就轮到pytest出场了。测试用例数量是不确定的每次生成的量可能不一样如果一个个写死在文件里就失去了自动化的意义。这里用的是pytest的parametrize在运行时把生成的用例作为参数传入动态执行。import pytest import requests pytest.mark.parametrize(case, generated_cases) def test_api_case(case): method case[method].upper() url base_url case[url] params case.get(params, {}) headers case.get(headers, {}) if method GET: resp requests.get(url, paramsparams, headersheaders, timeout10) elif method POST: resp requests.post(url, jsonparams, headersheaders, timeout10) # 其他方法同理 assert resp.status_code case[expected_status], \ f用例[{case[name]}]失败: 期望状态码{case[expected_status]}, 实际{resp.status_code} assert case[assert_text] in resp.text, \ f用例[{case[name]}]失败: 响应中未找到断言文本 {case[assert_text]}这套跑起来之后你会发现生成用例和用例执行完全解耦了。今天接口文档更新了重新生成一份JSON塞进去就能跑自动化用例集的维护成本大幅下降。3.2 让生成结果可回归、可追溯用AI生成测试用例一个很现实的问题是“每次生成的结果可能不一样”。今天生成的用例覆盖了A场景明天重新生成可能就漏了。这对测试来说是不能接受的——测了跟没测一样心里发虚。我的解决办法是把生成结果落盘存档文件名带时间戳方便回溯。同时每次生成之后和上一次做diff标注新增和删除的用例然后人工确认一轮。虽然麻烦一点但能保证测试行为的可预测性。import hashlib import os snapshot_dir ./case_snapshots os.makedirs(snapshot_dir, exist_okTrue) def snapshot_cases(cases, interface_tag): content json.dumps(cases, ensure_asciiFalse, indent2) digest hashlib.md5(content.encode()).hexdigest()[:8] file_path os.path.join(snapshot_dir, f{interface_tag}_{digest}.json) with open(file_path, w, encodingutf-8) as f: f.write(content) return file_path这个哈希值特别有用。如果两次生成的用例内容完全一致哈希值一样就说明结果稳定如果变了就能很直观地看到差异。回归报告这块我接的是Allure。pytest跑完之后自动生成Allure报告用例分类按接口路径和场景类型打标签看起来非常直观。Allure本身就支持标签和附件把模型生成的用例名称直接用作测试用例标题跑到哪一步挂了、参数是什么一目了然。pytest --alluredir./allure-results allure generate ./allure-results -o ./allure-report --clean3.3 持续优化闭环让用例越生成越准大模型生成用例有一个特性输入越精准输出越精准。所以我在工具里加了一个反馈闭环跑完一轮之后把失败的用例重新喂给模型让模型基于失败信息分析原因并给出补充或修正后的用例。feedback_prompt f 以下是上一轮测试中失败的用例信息 {failed_cases} 请分析失败可能的原因并给出修正后的测试用例。 如果是用例本身设计有误请直接修改用例如果是接口定义需要调整请标注建议。 这个玩法算是把大模型从“一次性生成器”变成了“持续优化器”。跑了几轮之后我发现模型对接口边界条件、参数类型的理解会越来越贴合实际被测系统的现状因为它能根据执行结果反馈进行自我修正。本质上就是一个小型的自我进化循环。提示这个反馈闭环不要全自动跑。大模型生成的东西必须有人工兜底审核尤其是涉及线上环境和生产数据的测试安全这根弦不能松。我一般会把模型建议的“自动修改”改成“人工确认后应用”只保留“自动分析原因”作为辅助。4. 常见问题与排查技巧实录4.1 模型返回的JSON总是解析失败这种情况非常常见尤其是刚接入SDK时可能问题不在网络层面而在输出内容里带了Markdown代码块标记。DeepSeek有时会在生成的JSON前后加“json”和“”导致json.loads直接报错。解决办法是加一个预处理函数把代码块标记剥离掉再提取第一个[到最后一个]之间的文本作为JSON主体。import re def extract_json(raw_content): # 剥离markdown代码块标记 content re.sub(rjson|, , raw_content).strip() # 提取第一个[到最后一个]的区间 start content.find([) end content.rfind(]) if start -1 or end -1: return None return json.loads(content[start:end1])这个处理看着简单但真的是救命级别的小技巧。我刚开始调试的时候至少有三分之一的时间耗在这上面。4.2 生成的用例数量不稳定有时多有时少这个问题主要出在提示词的覆盖要求写得太模糊。如果你只写“覆盖常见场景”模型可能给你生成10条也可能生成30条。稳定输出的办法是在提示词里明确“每个场景至少生成X条用例”并且给出结构化的分组说明。我的提示词是这么写的正常流程至少5条、异常参数至少8条、边界值至少5条、鉴权失败至少3条、依赖状态至少3条。这样模型输出数量基本稳定在20到30条左右批量生成的时候节奏就很可控。4.3 字段校验不通过大量用例被丢弃如果清洗阶段大量用例被丢弃先别急着怀疑模型不行先检查一下你喂给它的接口定义是否完整。我把接口的参数名、类型、必填项、枚举值都拼进了上下文模型的准确率能提高一大截。尤其是枚举值如果不告诉它某个字段只能取pending、paid、cancelled它就会编出completed这种看似合理但不存在的值。还有一种情况是接口定义里字段名是驼峰命名模型生成时改成了下划线命名。这种情况不用直接丢弃可以在清洗逻辑里加一个别名映射表把模型生成的字段名替换回真实字段名。4.4 超时与限流问题批量生成时经常遇到接口限流。DeepSeek的API对并发和每分钟请求数都有限制如果一次性提交几十个接口的生成任务很容易触发限流。我的做法是在调用层加一个线程池限制并发数在4到8之间同时加指数退避重试。实测下来比一次性全量并发要稳定很多总耗时反而更短。4.5 生成的断言过于宽松或者过于严格模型生成的断言如果一直卡在“断言响应包含某文本”对于JSON格式的接口来说太粗糙了。我在提示词里会让模型根据返回示例来生成断言表达式并且在清洗阶段支持XPath和JSONPath两种断言方式。这样就能对具体的返回字段做精确断言而不只是验证“返回里有没有某段文字”。这里我也踩过一个具体坑模型返回的断言文本常常包含英文引号、换行等特殊符号导致断言代码执行报错。所以我加了转义处理并且最后统一用JSONPath表达式来对比返回结构少了很多文本匹配的烦恼。根据我个人这几个月实操下来的体会AI生成测试用例这件事真正的门槛不在写代码而在你怎么把流程设计得可控。DeepSeek的生成能力已经够强了但它终究是个发散工具你得给它套上约束的笼头——格式约束、字段约束、数量约束再加上人工审核的兜底环节。把这层基础打好后续你想要它生成完整场景、复杂链路甚至跨接口组合的用例也只是在这个管道上面做增量的活。最后再分享一个小技巧如果你还没开始动手可以先挑一个你最熟悉的接口把文档定义整理好用这段代码跑通“生成→清洗→执行→出报告”的闭环。一旦这个最小流程跑顺了后面扩展起来会非常快。本文还有配套的精品资源点击获取
返回列表