Spring_couplet_generation 自动化测试Python脚本实现批量生成与评估对联生成服务部署好了界面也能正常访问但这就算完事了吗对于负责项目质量的工程师来说这仅仅是开始。服务能不能扛住多人同时请求生成的春联是不是真的对仗工整、语义通顺靠人工一条条去测效率低不说还容易遗漏。今天我们就来聊聊怎么用Python写一套自动化测试脚本把这件繁琐的活儿交给机器让测试既全面又高效。这套脚本的核心目标很明确一是模拟真实用户行为进行批量请求和压力测试确保服务稳定二是对生成的对联结果进行自动化评估检查其基本质量。这样一来每次服务更新或模型调整后我们都能快速、客观地了解其表现。1. 测试环境与目标设定在动手写代码之前我们先得把测试的“靶子”立好。假设你已经通过CSDN星图镜像广场部署好了Spring_couplet_generation服务它的API接口在http://your-server-address:port/generate上接收一个包含keywords关键词和length对联单句字数的JSON请求返回生成的上、下联及横批。我们的测试脚本要完成以下几件事功能正确性测试输入不同的关键词和长度服务是否能正常返回对联格式的结果。批量与并发测试模拟多个用户同时请求检查服务在高负载下的响应能力和稳定性。结果质量自动化评估对生成的对联进行初步的自动化检查比如检查字数是否匹配、上下联词性是否基本对仗、语义是否通顺通过基础NLP方法。2. 构造多样化测试用例好的测试始于丰富的测试数据。我们不能只用“新春”、“富贵”这样常见的词需要构造一个覆盖典型、边界和异常情况的测试集。# test_data.py import itertools def generate_test_cases(): 生成多样化的测试用例组合 # 典型关键词涵盖节日、场景、吉祥话等 typical_keywords [春节, 开业, 新婚, 山水, 勤奋, 平安, 数字, 科技] # 边界/特殊关键词空、长词组、英文、符号等用于测试鲁棒性 edge_keywords [, 人工智能与机器学习, HappyNewYear, #$%] # 常见对联单句字数 typical_lengths [5, 7, 9] # 五言、七言、九言 # 边界长度 edge_lengths [1, 4, 15] # 过短、非典型、过长 # 组合生成测试用例 test_cases [] # 1. 典型场景组合 for kw, ln in itertools.product(typical_keywords, typical_lengths): test_cases.append({keywords: kw, length: ln, type: typical}) # 2. 边界关键词测试使用典型长度 for kw in edge_keywords: test_cases.append({keywords: kw, length: 7, type: edge_keyword}) # 3. 边界长度测试使用典型关键词 for ln in edge_lengths: test_cases.append({keywords: 春节, length: ln, type: edge_length}) # 4. 随机组合一些压力测试用例数量较多 pressure_keywords [福, 财, 春, 喜, 和] * 5 # 重复词模拟简单重复请求 for kw in pressure_keywords[:20]: # 取20个 test_cases.append({keywords: kw, length: 7, type: pressure}) return test_cases if __name__ __main__: cases generate_test_cases() print(f共生成 {len(cases)} 条测试用例。) for i, case in enumerate(cases[:3]): # 打印前3条示例 print(f示例{i1}: {case})这个脚本会生成一个包含各种情况的测试用例列表从正常的“春节七言”到异常的“空关键词七言”为后续的测试提供了丰富的数据基础。3. 实现批量请求与并发测试有了测试用例接下来就是让脚本去“敲门”了。我们将使用requests库进行HTTP调用并用concurrent.futures来实现并发模拟真实场景下的压力。# batch_tester.py import requests import concurrent.futures import time import json from typing import Dict, List, Tuple from test_data import generate_test_cases # 导入上面写的测试用例生成器 class CoupletServiceTester: def __init__(self, base_url: str, max_workers: int 10): 初始化测试器 :param base_url: 对联生成服务的API地址 :param max_workers: 并发线程数 self.base_url base_url.rstrip(/) self.api_endpoint f{self.base_url}/generate self.session requests.Session() # 使用Session保持连接提升效率 self.max_workers max_workers self.results [] # 存储所有测试结果 def single_request(self, test_case: Dict) - Tuple[Dict, Dict, float]: 执行单次API请求 :return: (测试用例, 响应数据, 耗时) payload { keywords: test_case[keywords], length: test_case[length] } headers {Content-Type: application/json} start_time time.time() try: response self.session.post(self.api_endpoint, jsonpayload, headersheaders, timeout10) elapsed_time time.time() - start_time if response.status_code 200: resp_data response.json() # 简单校验返回结构 if all(k in resp_data for k in [upper, lower, horizontal]): status success else: status invalid_format resp_data {} else: status ferror_{response.status_code} resp_data {} except requests.exceptions.Timeout: elapsed_time time.time() - start_time status timeout resp_data {} except Exception as e: elapsed_time time.time() - start_time status fexception_{type(e).__name__} resp_data {} test_case[response_status] status test_case[response_data] resp_data test_case[elapsed_time] round(elapsed_time, 3) return test_case def run_batch_test(self, test_cases: List[Dict]) - List[Dict]: 使用线程池并发执行批量测试 print(f开始批量测试共 {len(test_cases)} 个用例并发数 {self.max_workers}...) start_time time.time() with concurrent.futures.ThreadPoolExecutor(max_workersself.max_workers) as executor: future_to_case {executor.submit(self.single_request, case): case for case in test_cases} for future in concurrent.futures.as_completed(future_to_case): case future_to_case[future] try: result future.result() self.results.append(result) except Exception as e: print(f用例 {case} 执行过程中发生异常: {e}) total_time time.time() - start_time print(f批量测试完成总耗时: {total_time:.2f} 秒平均每个请求: {total_time/len(test_cases):.3f} 秒) return self.results def generate_report(self): 生成简单的测试报告 if not self.results: print(暂无测试结果。) return total len(self.results) success sum(1 for r in self.results if r[response_status] success) avg_time sum(r[elapsed_time] for r in self.results) / total print(\n *50) print(测试执行报告) print(*50) print(f总请求数: {total}) print(f成功请求数: {success}) print(f成功率: {(success/total)*100:.1f}%) print(f平均响应时间: {avg_time:.3f} 秒) # 按状态码统计 status_stats {} for r in self.results: status r[response_status] status_stats[status] status_stats.get(status, 0) 1 print(\n详细状态分布:) for status, count in status_stats.items(): print(f {status}: {count} 次) # 找出最慢的5个请求 slowest sorted(self.results, keylambda x: x[elapsed_time], reverseTrue)[:5] print(\n响应最慢的5个请求:) for r in slowest: print(f 关键词『{r[keywords]}』, 长度{r[length]}, 耗时{r[elapsed_time]}秒, 状态:{r[response_status]}) if __name__ __main__: # 配置你的服务地址 SERVICE_URL http://localhost:8080 # 请替换为实际地址 tester CoupletServiceTester(SERVICE_URL, max_workers5) all_test_cases generate_test_cases() # 运行测试 results tester.run_batch_test(all_test_cases) # 生成报告 tester.generate_report()运行这个脚本你就能得到一份清晰的测试报告了解服务的成功率和响应性能。并发数的设置可以帮你试探服务的压力边界。4. 对联结果的自动化评估服务能返回结果还不够我们还得看看结果的质量。完全自动化地评价一副对联的文学性很难但我们可以从几个基础维度进行自动化检查。# quality_evaluator.py import jieba.posseg as pseg # 用于中文分词和词性标注 from typing import Dict, List class CoupletQualityEvaluator: 对联质量自动化评估器基础版 注意这是一个简化的评估方案主要基于规则更复杂的评估可能需要训练专门的模型。 staticmethod def check_length(upper: str, lower: str, expected_length: int) - bool: 检查上下联字数是否相等且符合预期 return len(upper) len(lower) expected_length staticmethod def basic_antithesis_check(upper: str, lower: str) - Dict: 基础对仗检查基于词性 这是一个简化检查实际对仗规则平仄、词义等要复杂得多。 # 分词并获取词性 upper_words pseg.cut(upper) lower_words pseg.cut(lower) upper_list [(w.word, w.flag) for w in upper_words] lower_list [(w.word, w.flag) for w in lower_words] if len(upper_list) ! len(lower_list): return {match: False, reason: 分词后词数不一致} # 简单比较对应位置词的词性是否相同或属于可对仗类别 pos_match_count 0 detail [] # 定义一些宽泛的可对仗词性类别例如名词对名词动词对动词 # 这里是一个非常简化的映射实际应用需要更细致的规则库 antithesis_map { n: [n, nr, ns, nt, nz], # 名词类 v: [v, vd, vn], # 动词类 a: [a, ad], # 形容词类 } for (uw, up), (lw, lp) in zip(upper_list, lower_list): # 判断词性是否可对仗 match False for main_pos, pos_list in antithesis_map.items(): if up in pos_list and lp in pos_list: match True break if match: pos_match_count 1 detail.append(f上联『{uw}』({up}) - 下联『{lw}』({lp}): {✓ if match else ✗}) match_ratio pos_match_count / len(upper_list) if upper_list else 0 is_acceptable match_ratio 0.6 # 设定一个阈值例如60%的词性能对上就算基础合格 return { match: is_acceptable, match_ratio: round(match_ratio, 2), detail: detail } staticmethod def check_horizontal(upper: str, lower: str, horizontal: str) - bool: 检查横批是否与上下联内容有一定关联非常简单的关键词检查 # 提取上下联中的实词名词、动词、形容词 all_text upper lower words [w for w, f in pseg.cut(all_text) if f.startswith((n, v, a))] # 检查横批中是否包含这些关键词或反之 # 这里只是一个非常简单的示例实际关联性判断复杂得多 common_words set(horizontal) set(.join(words)) return len(common_words) 0 or any(word in horizontal for word in words) def evaluate_single(self, result: Dict) - Dict: 评估单条生成结果 :param result: 包含 upper, lower, horizontal 的字典 :return: 评估结果字典 upper result.get(upper, ) lower result.get(lower, ) horizontal result.get(horizontal, ) expected_len result.get(input_length, len(upper)) # 假设输入中包含了期望长度 eval_result { upper: upper, lower: lower, horizontal: horizontal, checks: {} } # 1. 字数检查 length_ok self.check_length(upper, lower, expected_len) eval_result[checks][length_match] length_ok # 2. 基础对仗检查 if length_ok and upper and lower: antithesis_result self.basic_antithesis_check(upper, lower) eval_result[checks][basic_antithesis] antithesis_result else: eval_result[checks][basic_antithesis] {match: False, reason: 字数不符或内容为空} # 3. 横批关联性检查 if horizontal: horizontal_ok self.check_horizontal(upper, lower, horizontal) eval_result[checks][horizontal_relevance] horizontal_ok # 综合判断所有基础检查通过 all_basic_ok all([ eval_result[checks][length_match], eval_result[checks][basic_antithesis].get(match, False), eval_result[checks].get(horizontal_relevance, True) # 横批检查可能没有 ]) eval_result[overall_quality] acceptable if all_basic_ok else needs_review return eval_result def evaluate_batch_results(batch_results: List[Dict]) - None: 批量评估测试结果中的对联质量 evaluator CoupletQualityEvaluator() quality_results [] print(\n开始对联质量自动化评估...) for res in batch_results: if res.get(response_status) success and res.get(response_data): data res[response_data] # 将输入的长度信息也传递进去 data[input_length] res.get(length, 7) eval_res evaluator.evaluate_single(data) quality_results.append(eval_res) # 统计质量情况 total_evaluated len(quality_results) if total_evaluated 0: print(没有成功的结果可供评估。) return acceptable sum(1 for r in quality_results if r[overall_quality] acceptable) print(f\n质量评估完成共评估 {total_evaluated} 副对联。) print(f自动化评估通过基础规则: {acceptable} 副 ({acceptable/total_evaluated*100:.1f}%)) print(f建议人工复核: {total_evaluated - acceptable} 副) # 打印几个需要复核的例子 needs_review [r for r in quality_results if r[overall_quality] needs_review] if needs_review: print(\n以下为建议复核的对联示例前3个:) for i, example in enumerate(needs_review[:3]): print(f 示例{i1}: 上联『{example[upper]}』 下联『{example[lower]}』 横批『{example[horizontal]}』) for check_name, check_result in example[checks].items(): if isinstance(check_result, dict) and not check_result.get(match, True): print(f 未通过检查『{check_name}』: {check_result.get(reason, N/A)}) print() # 与批量测试脚本结合使用示例 if __name__ __main__: # 假设我们已经有了 batch_tester.py 运行后的 results # 这里模拟一些结果进行评估 mock_results [ { response_status: success, response_data: {upper: 春风送暖千山绿, lower: 旭日生辉万木荣, horizontal: 春回大地}, length: 7, keywords: 春节 }, { response_status: success, response_data: {upper: 人工智能创未来, lower: 机器学习谱新篇, horizontal: 科技兴邦}, length: 7, keywords: 科技 }, { response_status: success, response_data: {upper: 今天天气很好, lower: 明天可能下雨, horizontal: 天气预报}, length: 6, keywords: 天气 } ] evaluate_batch_results(mock_results)这个评估器提供了字数、基础词性对仗和横批关联性的自动化检查。它能快速筛出明显不符合格式或基础规则的结果大幅减少需要人工复核的工作量。当然对于对仗的平仄、词义的工整与意境目前还需要依靠人眼判断。5. 整合与持续测试建议把上面的脚本模块整合起来或者写一个主协调脚本就能形成一套完整的自动化测试流程。你可以定期例如每日构建时运行这套脚本监控服务性能和质量的变化趋势。在实际项目中还可以考虑以下增强点性能基准测试记录每次测试的响应时间、成功率绘制趋势图设置告警阈值。结果持久化将测试结果和评估结果保存到数据库或文件中便于历史追溯和对比分析。集成到CI/CD将测试脚本集成到Jenkins、GitLab CI等流水线中每次代码更新或模型部署后自动执行。更复杂的评估维度引入预训练的语言模型如BERT来计算上下联的语义相关性得分或者使用更专业的诗词格律检查库。获取更多AI镜像想探索更多AI镜像和应用场景访问 CSDN星图镜像广场提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。