解放双手尽情摸鱼,ai大模型自动生成测试用例!!

先展示整体结构跟效果!

这里xlsx中的数据是可以自行定义的,让大模型返回什么,写出对应的提示词即可

以下是我的提示词文件内容

from langchain_openai import ChatOpenAI
from config import OPENAI_API_KEY, MODEL_NAME, BASE_URL

def analyze_document(content):
    try:
        prompt = f"""请从以下产品需求文档中分析测试要点:{content}     
                请严格按以下结构返回JSON格式:
                1. 功能点:["...","..."]
                2. 业务规则(列出关键判断逻辑):["...","..."]
                3. 测试步骤(可以分成2-8步分情况而定):["1、... 2、....","3、...","1、... 2、....","3、..."]
                测试步骤的value中要标明1、2、3....的步骤顺序
                括号里的内容只是表示要求的内容,返回时不需要返回
                以上的功能的、业务规则、测试步骤的json的value列表中的数量要一致,一个功能点对应一个业务规则对应一套测试步骤
                """
        llm = ChatOpenAI(
            api_key=OPENAI_API_KEY,  # 如果您没有配置环境变量,请用百炼API Key将本行替换为:api_key="sk-xxx"
            base_url=BASE_URL,  # 填写DashScope base_url
            model=MODEL_NAME
        )
        messages = [
            {"role": "system", "content": prompt},
            {"role": "user", "content": content},
        ]
        response = llm.invoke(messages)
        return response.content

    except Exception as e:
        raise ValueError(f"AI分析失败: {str(e)}")

使用tk包生成可视化的程序展示,方便使用

import tkinter as tk
from tkinter import filedialog, messagebox
import os
import threading
from main import cli_main

class TestCaseGeneratorGUI:
    def __init__(self, root):
        self.root = root
        self.root.title("测试用例生成系统")
        
        # 文件选择区域
        self.file_frame = tk.LabelFrame(root, text="选择输入文件")
        self.file_frame.pack(padx=10, pady=10, fill="x")
        
        self.file_entry = tk.Entry(self.file_frame, width=40)
        self.file_entry.pack(side="left", padx=5, pady=5)
        
        self.browse_btn = tk.Button(self.file_frame, text="浏览...", command=self.browse_file)
        self.browse_btn.pack(side="left", padx=5, pady=5)
        
        # 输出目录区域
        self.output_frame = tk.LabelFrame(root, text="选择输出目录")
        self.output_frame.pack(padx=10, pady=10, fill="x")
        
        self.output_entry = tk.Entry(self.output_frame, width=40)
        self.output_entry.pack(side="left", padx=5, pady=5)
        
        self.output_browse_btn = tk.Button(self.output_frame, text="浏览...", command=self.browse_output)
        self.output_browse_btn.pack(side="left", padx=5, pady=5)
        
        # 进度条
        self.progress = tk.Label(root, text="准备就绪")
        self.progress.pack(padx=10, pady=5)
        
        # 生成按钮
        self.generate_btn = tk.Button(root, text="生成测试用例", command=self.generate_testcases)
        self.generate_btn.pack(padx=10, pady=10)
        
    def browse_file(self):
        file_path = filedialog.askopenfilename(
            title="选择输入文件",
            filetypes=[("支持的文件", "*.pdf;*.docx;*.md")]
        )
        if file_path:
            self.file_entry.delete(0, tk.END)
            self.file_entry.insert(0, file_path)
            
    def browse_output(self):
        dir_path = filedialog.askdirectory(title="选择输出目录")
        if dir_path:
            self.output_entry.delete(0, tk.END)
            self.output_entry.insert(0, dir_path)
    
    def generate_testcases(self):
        input_file = self.file_entry.get()
        output_dir = self.output_entry.get() or "."
        
        if not input_file:
            messagebox.showerror("错误", "请选择输入文件")
            return
            
        if not os.path.exists(input_file):
            messagebox.showerror("错误", "输入文件不存在")
            return
            
        self.progress.config(text="正在生成测试用例...")
        self.generate_btn.config(state="disabled")
        
        # 在新线程中运行生成过程
        thread = threading.Thread(
            target=self.run_generation,
            args=(input_file, output_dir),
            daemon=True
        )
        thread.start()
    
    def run_generation(self, input_file, output_dir):
        try:
            # 调用命令行主函数
            cli_main(input_file, output_dir=output_dir)
            self.root.after(0, self.on_generation_success)
        except Exception as e:
            self.root.after(0, self.on_generation_error, str(e))
    
    def on_generation_success(self):
        self.progress.config(text="测试用例生成完成")
        self.generate_btn.config(state="normal")
        messagebox.showinfo("成功", "测试用例已成功生成")
    
    def on_generation_error(self, error):
        self.progress.config(text="生成失败")
        self.generate_btn.config(state="normal")
        messagebox.showerror("错误", f"生成失败: {error}")


def main():
    root = tk.Tk()
    app = TestCaseGeneratorGUI(root)
    root.mainloop()

if __name__ == "__main__":
    main()

main文件生成用例xlsx文件的全流程

from file_processor import extract_text
from ai_analyzer import analyze_document
from testcase_generator import generate_testcases
import os

def cli_main(input_file, output_dir='.'):
    try:
        # 读取文件内容
        print(f"正在读取文件: {input_file}")
        content = extract_text(input_file)
        
        # AI分析
        print("正在进行需求分析...")
        analysis_result = analyze_document(content)
        
        # 生成测试用例
        print("正在生成测试用例...")
        wb, timestamp = generate_testcases(analysis_result)
        
        # 保存结果
        output_path = os.path.join(output_dir, f'testcase_{timestamp}.xlsx')
        wb.save(output_path)
        
        print(f"测试用例已生成至: {os.path.abspath(output_path)}")
    
    except Exception as e:
        print(f"\033[31m错误发生: {str(e)}\033[0m")

读取上传文档中的内容,获取之后传给大模型

import PyPDF2
from docx import Document
import os

def read_pdf(file_path):
    try:
        with open(file_path, 'rb') as file:
            reader = PyPDF2.PdfReader(file)
            return '\n'.join([page.extract_text() for page in reader.pages])
    except Exception as e:
        raise ValueError(f"PDF读取失败: {str(e)}")


def read_docx(file_path):
    try:
        doc = Document(file_path)
        return '\n'.join([para.text for para in doc.paragraphs])
    except Exception as e:
        raise ValueError(f"Word文档读取失败: {str(e)}")


def read_markdown(file_path):
    try:
        with open(file_path, 'r', encoding='utf-8') as file:
            return file.read()
    except Exception as e:
        raise ValueError(f"Markdown读取失败: {str(e)}")


def extract_text(file_path):
    ext = os.path.splitext(file_path)[1].lower()
    if ext == '.pdf':
        return read_pdf(file_path)
    elif ext == '.docx':
        return read_docx(file_path)
    elif ext in ('.md', '.markdown'):
        return read_markdown(file_path)
    else:
        raise ValueError("不支持的文件格式,仅支持PDF/DOCX/Markdown")

将上传的文档中的内容传给大模型,获取返回的json内容后,处理大模型返回内容,生成xlsx并将返回内容放入xlsx文件中(ps:这里一开始一直有问题,找了半天原因最后发现是大模型返回的内容只会是string类型的,并且会在string的开头标明返回的类型是什么,这里做了切片并且转换成了json类型的数据)

import json
import openpyxl
from datetime import datetime

def generate_testcases(analysis_result):
    try:
        print(f"原始分析结果: {analysis_result}")  # 调试输出

        # 如果输入已经是字典,直接使用
        if isinstance(analysis_result, dict):
            data = analysis_result
        else:
            # 检查输入是否为字符串且非空
            if not isinstance(analysis_result, str) or not analysis_result.strip():
                raise ValueError("输入必须是有效的JSON字符串或字典")

            # 尝试解析JSON前先去除可能的空白字符
            analysis_result = analysis_result.strip()
            
            # 预处理:删除前四个字符
            if len(analysis_result) > 7:
                analysis_result = analysis_result[7:-3]
                analysis_result = analysis_result.strip()
                # print(f"处理后结果: {analysis_result}")

            # 检查字符串是否以{开头和}结尾,确保是完整JSON对象
            if not (analysis_result.startswith('{') and analysis_result.endswith('}')):
                raise ValueError("输入的JSON字符串格式不正确,必须以'{'开头和'}'结尾")

            # 验证JSON格式有效性
            try:
                data = json.loads(analysis_result)
            except json.JSONDecodeError as e:
                print(f"JSON解析错误位置: 行{e.lineno} 列{e.colno}")
                print(f"错误上下文: {analysis_result[max(0, e.pos-20):e.pos+20]}")
                print(f"完整JSON内容: {analysis_result}")
                raise
        
        # 验证JSON格式有效性
        try:
            data = json.loads(analysis_result)
        except json.JSONDecodeError as e:
            print(f"JSON解析错误位置: 行{e.lineno} 列{e.colno}")
            print(f"错误上下文: {analysis_result[max(0, e.pos-20):e.pos+20]}")
            print(f"完整JSON内容: {analysis_result}")
            raise
        
        # 创建Excel工作簿
        wb = openpyxl.Workbook()
        ws = wb.active
        ws.title = "测试用例"
        
        # 设置表头并调整列宽
        ws.append(["功能点", "业务规则", "测试步骤"])
        ws.column_dimensions['A'].width = 30
        ws.column_dimensions['B'].width = 40
        ws.column_dimensions['C'].width = 60
        
        # 设置单元格样式
        header_font = openpyxl.styles.Font(bold=True)
        feature_font = openpyxl.styles.Font(bold=True)
        scenario_font = openpyxl.styles.Font(bold=True)
        
        # 应用表头样式
        for cell in ws[1]:
            cell.font = header_font
        
        # 处理功能点、业务规则和测试步骤
        features = data.get('功能点', [])
        scenarios = data.get('业务规则', [])
        test_steps = data.get('测试步骤', [])
        
        if not features and not scenarios and not test_steps:
            raise ValueError("输入数据为空,请检查分析结果")
            
        # 填充功能点、业务规则和测试步骤
        for i, feature in enumerate(features):
            scenario = scenarios[i] if i < len(scenarios) else ""
            test_step = test_steps[i] if i < len(test_steps) else ""
            ws.append([feature, scenario, test_step])
            
            # 设置单元格样式
            ws.cell(row=ws.max_row, column=1).font = feature_font
            ws.cell(row=ws.max_row, column=2).font = scenario_font
            ws.cell(row=ws.max_row, column=3).font = scenario_font
        
        # 生成时间戳文件名
        timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
        return wb, timestamp
    
    except json.JSONDecodeError as e:
        raise ValueError(f"JSON解析失败: {str(e)}\n原始内容: {analysis_result}")
    except Exception as e:
        raise ValueError(f"测试用例生成失败: {str(e)}")

都搞好之后用pyinstaller打包文件就可以生成exe文件直接使用了!

ps:菜鸡随便自己记录一下

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值