当前位置: 首页 > news >正文

AI自动生成接口测试脚本全流程

一、接口自动化生成自动化脚本的思路

1、接口文档发给大模型2、让大模型编写接口功能用例

3、再让大模型依据接口功能用例编写自动化用例

4、把自动化用例保存在指定目录下

二、LangChain设计

1、从完整的swagger_json中提取指定接口信息

编写代码的提示词

#背景
需要从swagger文档里面提取出对应的配置信息,根据用户输入的接口名称,提取对应的内容#需求
用户传入接口的名称列表,从swagger文档的json中找到接口名称的summary,还有接口的请求方式,path,需要把整个接口的节点的信息全部提取出来。在接口信息的response中,200节点下面有schema节点,里面引用了一个DO对象。该DO对象是在definitions节点中定义的,需要找到对应DO对象,把相关信息过滤出来#入参
1、完整的swgger_json
2、需要提取接口的名称列表summary_listswagger_json示例格式:
```json
{"swagger":"2.0","info":{"description":"卖家中心API接口","version":"7.0","title":"卖家中心Api文档"},"host":"59.36.173.55:7003","basePath":"/","tags":[{"name":"distribution-goods-seller-controller","description":"分销商品API"}],"paths":{"/seller/distribution/goods":{"put":{"tags":["distribution-goods-seller-controller"],"summary":"分销商品返利设置","operationId":"settingGoodsUsingPUT","consumes":["application/json"],"produces":["*/*"],"parameters":[{"name":"Authorization","in":"header","description":"令牌","required":false,"type":"string"},{"name":"goods_id","in":"query","description":"商品id","required":true,"type":"integer","format":"int32"},{"name":"grade1_rebate","in":"query","description":"1级提成金额","required":true,"type":"number","format":"double"},{"name":"grade2_rebate","in":"query","description":"2级提成金额","required":true,"type":"number","format":"double"}],"responses":{"200":{"description":"OK","schema":{"$ref":"#/definitions/DistributionGoods"}},"201":{"description":"Created"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Not Found"}}}},"/seller/distribution/goods/{goods_id}":{"get":{"tags":["distribution-goods-seller-controller"],"summary":"分销商品返利获取","operationId":"querySettingUsingGET","produces":["*/*"],"parameters":[{"name":"Authorization","in":"header","description":"令牌","required":false,"type":"string"},{"name":"goods_id","in":"path","description":"商品id","required":true,"type":"integer","format":"int32"}],"responses":{"200":{"description":"OK","schema":{"$ref":"#/definitions/DistributionGoods"}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Not Found"}}}},"/seller/distribution/setting":{"get":{"tags":["distribution-goods-seller-controller"],"summary":"获取分销设置:1开启/0关闭","operationId":"settingUsingGET","produces":["*/*"],"parameters":[{"name":"Authorization","in":"header","description":"令牌","required":false,"type":"string"}],"responses":{"200":{"description":"OK","schema":{"$ref":"#/definitions/SuccessMessage"}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Not Found"}}}}},"definitions":{"DistributionGoods":{"type":"object","required":["goods_id","grade1_rebate","grade2_rebate"],"properties":{"goods_id":{"type":"integer","format":"int32","description":"商品id","allowEmptyValue":false},"grade1_rebate":{"type":"number","format":"double","description":"1级提成金额","allowEmptyValue":false},"grade2_rebate":{"type":"number","format":"double","description":"2级提成金额","allowEmptyValue":false}},"title":"DistributionGoods"},"SuccessMessage":{"type":"object","properties":{"message":{"type":"object"}},"title":"SuccessMessage"}}}
```#返回值
返回一个json,包含paths、definitions两个节点
def fetch_swagger_json(swagger_url):"""从Swagger接口获取JSON数据:param swagger_url: Swagger接口URL:return: Swagger JSON数据"""try:response = requests.get(swagger_url)response.raise_for_status()  # 检查请求是否成功return response.json()except requests.exceptions.RequestException as e:print(f"获取Swagger数据失败: {e}")return Nonedef extract_swagger_info(swagger_json, summary_list):"""从Swagger JSON中提取指定接口的信息:param swagger_json: 完整的Swagger JSON文档:param summary_list: 需要提取的接口summary列表:return: 包含paths和definitions的JSON"""try:# 如果传入的是字符串,则解析为字典if isinstance(swagger_json, str):swagger_data = json.loads(swagger_json)else:swagger_data = swagger_jsonresult = {"paths": {},"definitions": {}}# 收集所有需要提取的DO对象引用do_refs = set()# 遍历paths中的所有接口for path, methods in swagger_data.get("paths", {}).items():for method, details in methods.items():if isinstance(details, dict) and details.get("summary") in summary_list:# 添加到结果中的pathsif path not in result["paths"]:result["paths"][path] = {}result["paths"][path][method] = details# 检查200响应中的schema引用responses = details.get("responses", {})if "200" in responses:schema = responses["200"].get("schema", {})if "$ref" in schema:do_refs.add(schema["$ref"])# 提取definitionsfor ref in do_refs:# 解析引用路径,如"#/definitions/DistributionGoods"parts = ref.split("/")if len(parts) == 3 and parts[1] == "definitions":do_name = parts[2]if do_name in swagger_data.get("definitions", {}):result["definitions"][do_name] = swagger_data["definitions"][do_name]return resultexcept Exception as e:return {"error": str(e)}def main(swagger_url,summary_list):# 1. 获取Swagger JSON数据swagger_json = fetch_swagger_json(swagger_url)if not swagger_json:print("无法获取Swagger数据,请检查网络或URL是否正确")return# 2. 提取指定接口信息result = extract_swagger_info(swagger_json, summary_list)# 3. 输出结果return json.dumps(result, indent=2, ensure_ascii=False)if __name__ == "__main__":api_json = main(swagger_url = "url",summary_list = [ "接口"])

2、调用LangChain生成测试用例


llm = ChatOpenAI(openai_api_base="",api_key="",temperature=0.8,max_tokens=10240,model_name="",
)def read_prompt(filename):"""读取当前脚本同级目录下的prompts文件夹中的指定文件Args:filename (str): 要读取的文件名Returns:str: 文件内容"""# 获取当前脚本所在目录current_dir = os.path.dirname(os.path.abspath(__file__))# 构建prompts文件夹路径prompts_dir = os.path.join(current_dir, 'prompts')# 构建目标文件的完整路径file_path = os.path.join(prompts_dir, filename)# 检查文件是否存在if not os.path.exists(file_path):raise FileNotFoundError(f"Prompt file '{filename}' not found in '{prompts_dir}'")# 读取文件内容with open(file_path, 'r', encoding='utf-8') as file:return file.read()def call_chain(api_json,requirements):#第一步:让大模型根据接口的json和补充需求,生成一份标准的接口需求文档prompt_template_summary = PromptTemplate(input_variables=["api_json", "requirements"],template=read_prompt("summary_prompt.md"),template_format="jinja2")#定义第一个节点summary_chain = LLMChain(llm=llm, prompt=prompt_template_summary, verbose=True, output_key="summary_result")prompt_template_summary_case = PromptTemplate(input_variables=["summary_result"],template=read_prompt("case_prompt.md"),template_format="jinja2")summary_chain_case = LLMChain(llm=llm, prompt=prompt_template_summary_case, verbose=True, output_key="api_case")#第三个节点prompt_template_script = PromptTemplate(input_variables=["api_case"],template=read_prompt("script_prompt.md"),template_format="jinja2")script_chain = LLMChain(llm=llm, prompt=prompt_template_script, verbose=True, output_key="script_result")#创建一个顺序链,把两个节点按照顺序组装all_chain = SequentialChain(chains=[summary_chain,summary_chain_case,script_chain],input_variables=["api_json","requirements"],output_variables=["api_case","script_result"],verbose=True)#运行整个链result = all_chain.invoke({"api_json":api_json,"requirements":requirements})print(result)

3、大模型根据接口测试用例生成接口自动化脚本

未完待续

http://www.dtcms.com/a/326507.html

相关文章:

  • 当AI重塑世界:普通人如何成为“主动进化者”?
  • 在 .NET Core 5.0 中启用 Gzip 压缩 Response
  • ECCV 2024 论文解读丨具身智能、机器人研究最新突破创先点分享合集
  • MCU中的存储器映射(Memory Map)
  • 登录系统英文使用 Sign In?Log In?还是 Log On?
  • Windows Server 2022域控制器部署与DNS集成方案
  • 大模型工程问题
  • Python网络爬虫(一) - 爬取静态网页
  • 打烊:餐厅开业前的“压力测试”
  • nginx 设置二级目录-实战
  • P1967 [NOIP 2013 提高组] 货车运输【题解】
  • 当智慧在腕间流转:一场无声的协同交响
  • haproxy 2.4.x, /metrics 取数据遇到的问题
  • 项目代码涉及的知识点笔记整理
  • C++高频知识点(二十一)
  • 嵌入式学习 day48 IMX6ULL裸机驱动 -按键、中断
  • 源码分析Eino框架工具调用--创建篇
  • Redis RDB和AOF 流程、优缺点详细介绍
  • python每日一题练习 有效的字母异位词 非常简单
  • Linux软件编程--IO
  • Linux 软件编程:IO——标准IO
  • 《录井管理与工程》书籍第一章要点及相应思考
  • 工业数采引擎-通信协议(Modbus/DTU/自定义协议)
  • FFmepg源码系列-avformat_open_input()
  • python之uv使用
  • [动态规划]最长公共子序列(LCS)
  • Nacos添加权限
  • uart通信中出现乱码,可能的原因是什么 ?
  • Linux软件编程:标准IO(ASCII文件)
  • Discuz论坛和java应用的架构部署