通过Chain Prompts方式将LLM的能力引入测试平台:正交实验测试用例生成
Chain Prompts
Chain Prompts是指在一个对话或文本生成任务中,将前一个提示的输出作为下一个提示的输入,形成一个连续的链条。这种方法常常用于创建连贯的、有上下文关联的文本。在对话系统中,这种方法可以模拟真实对话中的连续性,使得生成的回复更加自然和流畅。
利用Chain Prompts,可以将LLM、外部程序、外部数据连接到一起,实现一个完整的解决方案。下面我们使用Chain Prompts的方式实现正交实验测试用例生成。
STEP1:LLM gen参数的边界值
> 文中使用的LLM是讯飞的星火2.0
首先,借助LLM的能力,设计CoT的Prompt实现让大模型返回每个参数的边界值数组,具体的代码如下:
''' @des :针对LLM反馈的内容,做一些文本处理,最终仅仅留下边界的数组返回 @params : LLM反馈的内容 @return : 处理好的,仅仅剩下list类型的边界值列表 ''' def get_boundary(content): result_boundary_list=[] if content.find("[") != -1: while content.find("[") != -1: if content.find("[")!= content.find("]")+1: try: stemp = content[content.index("["):content.index("]")+1] # pattern = r'#.*?\n' # stemp=re.sub(pattern,"",stemp) result=eval(stemp) result_boundary_list.append(result) content = content.replace(content[content.index("[")],"") content = content.replace(content[content.index("]")],"") except Exception as e: content = content.replace(content[content.index("[")],"") continue else: content = content.replace(content[content.index("[")],"") content = content.replace(content[content.index("]")],"") return result_boundary_list else: return [] ''' @des :和大模型交互,生成边界值数组 @params : 描述变量的Prompts @return :边界值list ''' def gen_boundary(usr_message_list): # 分隔符 boundary_param_list=[] delimiter = "####" if len(usr_message_list)<1: return [{"error":"no user param prompt!"}] for usr_message in usr_message_list: text.clear # user_message = f"""{usr_message}{delimiter}。""" boundary_message=f"""{delimiter}设计参数的边界值,{usr_message}。 {delimiter}边界值还要包含不满足要求的一些内容,并将结果放到到一个数组中,不要返回python代码,只返回一个具体数组内容,不要包含任何注释。 """ system_message = f"""{delimiter}是分隔符。{delimiter}你是一名资深测试工程师,{boundary_message}{delimiter}。""" SparkApi.answer="" question = checklen(getText("user",system_message)) SparkApi.main(appid,api_key,api_secret,Spark_url,domain,question) try: boundary_param_list.append(get_boundary(SparkApi.answer)) except Exception as e: print("error:"+SparkApi.answer+"\"}") # print(boundary_param_list) return boundary_param_list
STEP2 通过传统编码寻找参数的因素和水平,强度默认是2
接下来,我们需要将大模型处理后的反馈处理成Python可以处理的对象,然后处理成正交表的因素和水平字典。
factors = {} levels=[] istep = 0 factors['username']=list[0][0] factors['password']=list[1][0]
STEP3:通过itertool处理,完成正交表设计和测试用例生成
@des :生成正交表 @params :每个因素的水平数list @return :正交表(array) def generate_orthogonal_table(levels): return list(itertools.product(*[range(1, l+1) for l in levels]))
通过统一的入口,调用上述步骤,完成测试用例设计
#!/usr/bin/env python # -*- coding: utf-8 -*- ''' @File : main.py @Time : 2023/10/18 13:12:25 @Author : CrissChan @Version : 1.0 @Site : https://blog.csdn.net/crisschan @Desc : 主要函数,尝试使用Chain Prompts的方式构建基于正交试验的测试用例生成 step1:LLM gen参数的边界值 step2:寻找参数的因素和水平,强度默认是2 step3:LLM 生成正交表 step4 用正交表替换测试用例 ''' from gen_boundary import gen_boundary from gen_boundary import generate_orthogonal_table import numpy as np if __name__ == '__main__': # step 1 :调用LLM通过Prompt生成参数的边界值。 user_message_list=[] user_message_1 = f"""username是一个系统的用户名,string类型,长度限制10个字符,不能为空。""" user_message_2 = f"""password是一个系统用户的密码,string类型,长度限制10个字符,不能为空。""" user_message_list.append(user_message_1) user_message_list.append(user_message_2) list = gen_boundary(user_message_list) print(list) # step2 : 寻找参数的因素和水平,强度默认是2 factors = {} levels=[] istep = 0 factors['username']=list[0][0] factors['password']=list[1][0] # step 3: python计算正交表 levels_list=[] # 创建强度为2的正交表 for k,v in factors.items(): levels_list.append(len(v)) art_array = generate_orthogonal_table(levels_list) #step4:将正交表替换测试用例 tc_list = [] for a_arr in art_array: tc_list.append((factors['username'][a_arr[0]-1],factors['password'][a_arr[1]-1])) print(tc_list)
运行结果
请注意,这只是一个示例,实际的数组内容可能会根据具体需求而有所不同。
因素和水平数组:
[[['', '12345678901', 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', '!@#$%^&*()', 'username', 'extra_long_username_that_exceeds_the_limit', '']], [['', '1234567890', 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'password', 'passw0rd', 'Passw0rd!', 'p@ssw0rd', 'p@$$w0rd', 'p@ssword']]]
生成的测试用例
[('', ''), ('', '1234567890'), ('', 'abcdefghijklmnopqrstuvwxyz'), ('', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'), ('', 'password'), ('', 'passw0rd'), ('', 'Passw0rd!'), ('', 'p@ssw0rd'), ('', 'p@$$w0rd'), ('', 'p@ssword'), ('12345678901', ''), ('12345678901', '1234567890'), ('12345678901', 'abcdefghijklmnopqrstuvwxyz'), ('12345678901', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'), ('12345678901', 'password'), ('12345678901', 'passw0rd'), ('12345678901', 'Passw0rd!'), ('12345678901', 'p@ssw0rd'), ('12345678901', 'p@$$w0rd'), ('12345678901', 'p@ssword'), ('abcdefghijklmnopqrstuvwxyz', ''), ('abcdefghijklmnopqrstuvwxyz', '1234567890'), ('abcdefghijklmnopqrstuvwxyz', 'abcdefghijklmnopqrstuvwxyz'), ('abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'), ('abcdefghijklmnopqrstuvwxyz', 'password'), ('abcdefghijklmnopqrstuvwxyz', 'passw0rd'), ('abcdefghijklmnopqrstuvwxyz', 'Passw0rd!'), ('abcdefghijklmnopqrstuvwxyz', 'p@ssw0rd'), ('abcdefghijklmnopqrstuvwxyz', 'p@$$w0rd'), ('abcdefghijklmnopqrstuvwxyz', 'p@ssword'), ('ABCDEFGHIJKLMNOPQRSTUVWXYZ', ''), ('ABCDEFGHIJKLMNOPQRSTUVWXYZ', '1234567890'), ('ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), ('ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'), ('ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'password'), ('ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'passw0rd'), ('ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'Passw0rd!'), ('ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'p@ssw0rd'), ('ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'p@$$w0rd'), ('ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'p@ssword'), ('!@#$%^&*()', ''), ('!@#$%^&*()', '1234567890'), ('!@#$%^&*()', 'abcdefghijklmnopqrstuvwxyz'), ('!@#$%^&*()', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'), ('!@#$%^&*()', 'password'), ('!@#$%^&*()', 'passw0rd'), ('!@#$%^&*()', 'Passw0rd!'), ('!@#$%^&*()', 'p@ssw0rd'), ('!@#$%^&*()', 'p@$$w0rd'), ('!@#$%^&*()', 'p@ssword'), ('username', ''), ('username', '1234567890'), ('username', 'abcdefghijklmnopqrstuvwxyz'), ('username', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'), ('username', 'password'), ('username', 'passw0rd'), ('username', 'Passw0rd!'), ('username', 'p@ssw0rd'), ('username', 'p@$$w0rd'), ('username', 'p@ssword'), ('extra_long_username_that_exceeds_the_limit', ''), ('extra_long_username_that_exceeds_the_limit', '1234567890'), ('extra_long_username_that_exceeds_the_limit', 'abcdefghijklmnopqrstuvwxyz'), ('extra_long_username_that_exceeds_the_limit', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'), ('extra_long_username_that_exceeds_the_limit', 'password'), ('extra_long_username_that_exceeds_the_limit', 'passw0rd'), ('extra_long_username_that_exceeds_the_limit', 'Passw0rd!'), ('extra_long_username_that_exceeds_the_limit', 'p@ssw0rd'), ('extra_long_username_that_exceeds_the_limit', 'p@$$w0rd'), ('extra_long_username_that_exceeds_the_limit', 'p@ssword'), ('', ''), ('', '1234567890'), ('', 'abcdefghijklmnopqrstuvwxyz'), ('', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'), ('', 'password'), ('', 'passw0rd'), ('', 'Passw0rd!'), ('', 'p@ssw0rd'), ('', 'p@$$w0rd'), ('', 'p@ssword')]