点击蓝字
关注我们
二、完整源码解析
含结构拆解+函数关系+核心代码示例
上一篇文章《提升测试幸福感:从0到1实现测试报告自动化》梳理了工具的核心逻辑和设计思路,这一部分将深入源码层面,从「整体结构」「函数依赖关系」「核心函数代码实现」三个维度做深度拆解,让大家不仅能看懂「为什么这么设计」,还能看懂「具体怎么实现」,方便后续直接复用、二次开发。
(一)源码整体说明与开发环境
1. 开发环境与依赖库
工具基于 Python3.7+ 开发,兼容性强,任意 Python3 版本均可运行;核心依赖库仅 4 个,均为 Python 常用库,通过 pip 一键安装即可,无复杂环境配置:
●tkinter:Python 内置库,无需安装,用于开发桌面可视化界面;
●matplotlib:用于生成可视化图表,安装命令:pip install matplotlib;
●python-docx:用于生成 Word 格式报告,安装命令:pip install python-docx;
●random:Python 内置库,无需安装,用于生成基础随机数据。
2. 源码整体结构(单文件+单类封装)
源码采用「单文件完整实现」设计(文件名:test_report_tool.py),无多余依赖文件,复制到任意电脑即可运行,轻量化极致。整体结构为「1 个主类 + 7 大功能模块」,所有功能、数据、逻辑都封装在主类中,无全局变量、无零散函数,结构清晰易维护:
# 源码整体结构示意classTestReportAutoTool:# 【模块1:初始化模块】:程序入口,初始化界面、数据、按钮绑定def __init__(self, root):pass# 【模块2:界面渲染模块】:绘制输入框、按钮、展示区等可视化元素def _create_input_area(self): # 输入区域渲染passdef _create_button_area(self): # 按钮区域渲染passdef _create_show_area(self): # 数据展示区域渲染pass# 【模块3:基础数据处理模块】:生成、修改、刷新、清空核心数据def generate_data(self): # 生成基础数据(核心)passdef edit_data(self): # 修改数据入口passdef edit_single_module(self, parent): # 单模块修改passdef split_total_data(self, parent): # 总数据拆分修改passdef batch_edit_data(self, parent): # 批量输入修改(高频)passdef refresh_base_data_display(self): # 数据刷新展示passdef clear_data(self): # 清空所有数据pass# 【模块4:衍生数据计算模块】:计算图表/报告所需的衍生数据def _calc_module_bug_ratio(self): # 计算模块缺陷占比passdef _calc_bug_level_dist(self): # 计算缺陷等级分布passdef _calc_bug_type_dist(self): # 计算缺陷类型分布pass# 【模块5:图表生成模块】:生成并保存可视化图表def generate_charts(self):pass# 【模块6:报告导出模块】:生成标准化 Word 报告def download_wps_doc(self):pass# 【模块7:辅助工具模块】:通用校验、样式封装、弹窗提示def _is_system_module(self, module_name): # 判断是否为系统模块passdef _check_positive_int(self, num_str): # 校验正整数passdef _set_table_style(self, table): # 封装表格样式passdef _add_text_to_cell(self, cell, text): # 单元格文字赋值passdef _show_msg(self, title, msg): # 弹窗提示pass# 程序运行入口if __name__ == "__main__":import tkinter as tkroot = tk.Tk()app = TestReportAutoTool(root)root.mainloop()}
核心设计亮点:所有模块按「业务流程顺序」编写,从上到下阅读完全贴合「初始化→输入→数据处理→输出」的逻辑,新手也能快速定位功能所在位置。
(二)核心模块与函数依赖关系
函数间的依赖关系直接决定了代码的可读性和维护性,本工具的函数设计遵循「低耦合、高内聚」原则,每个模块仅依赖必要的前置模块,无杂乱嵌套。核心依赖关系如下:
1. 核心依赖链路(从初始化到最终输出)
__init__(初始化) → 调用「界面渲染模块」→ 按钮绑定「基础数据处理模块」→ 「基础数据处理模块」提供数据给「衍生数据计算模块」→ 「衍生数据计算模块」+「图表生成模块」提供数据/图表给「报告导出模块」→ 「辅助工具模块」被所有模块调用(通用功能)
2. 关键函数调用关系详解
用「核心功能流程」串联函数,更易理解:
●流程1:生成基础数据:点击「生成数据」按钮 → 触发 generate_data() → 内部调用 _is_system_module()(判断模块类型)→ 调用 refresh_base_data_display()(刷新界面展示);
●流程2:修改数据:点击「修改数据」按钮 → 触发 edit_data() → 内部调用 edit_single_module()/split_total_data()/batch_edit_data()(三种修改方式)→ 均调用 _check_positive_int()(数据校验)和 refresh_base_data_display()(刷新展示);
●流程3:生成报告:点击「导出报告」按钮 → 触发 download_wps_doc() → 内部调用 _calc_module_bug_ratio()/_calc_bug_level_dist()/_calc_bug_type_dist()(计算衍生数据)→ 调用 generate_charts()(生成图表)→ 调用 _set_table_style()/_add_text_to_cell()(排版表格)→ 调用_show_msg()(提示保存成功)。
核心特点:所有函数的调用都围绕「业务流程」展开,每个函数仅负责单一功能,修改任意函数都不会影响其他不相关的功能,易维护、易扩展。
(三)核心函数代码示例与解析
这一部分选取「基础数据生成」「批量数据修改」「图表生成」「报告导出」4个核心函数,提供完整代码示例并做逐行解析,让大家能直接复用核心逻辑。
1. 基础数据生成函数:
generate_data()(数据源头核心)
def generate_data(self):# 1. 读取用户输入的系统名称和模块名称self.system_name = self.system_name_entry.get().strip()module_text = self.module_text.get("1.0", tk.END).strip()# 校验输入:系统名称和模块名称不能为空ifnot self.system_name:self._show_msg("提示", "请输入系统名称!")returnifnot module_text:self._show_msg("提示", "请输入测试模块名称(每行一个)!")return# 2. 解析模块列表:按换行拆分,过滤空行self.module_list = [module.strip() formodule in module_text.split("\n") ifmodule.strip()]# 3. 初始化数据容器self.case_num_dict = {} # 键:模块名,值:用例数self.bug_num_dict = {} # 键:模块名,值:BUG数self.total_case = 0 # 总用例数self.total_bug = 0 # 总BUG数# 4. 遍历模块,差异化生成数据formodule in self.module_list:if self._is_system_module(module):# 系统模块:用例数20-50,BUG数1-5case_num = random.randint(20, 50)bug_num = random.randint(1, 5)else:# 业务模块:用例数80-120,BUG数6-20case_num = random.randint(80, 120)bug_num = random.randint(6, 20)# 存入字典self.case_num_dict[module] = case_numself.bug_num_dict[module] = bug_num# 累加总数self.total_case += case_numself.total_bug += bug_num# 5. 刷新界面展示数据self.refresh_base_data_display()self._show_msg("成功", f"基础数据生成完成!\n系统名称:{self.system_name}\n模块数量:{len(self.module_list)}\n总用例数:{self.total_case}\n总BUG数:{self.total_bug}")
解析:
●输入校验:先判断系统名称和模块名称是否为空,避免后续逻辑出错,这是代码健壮性的基础;
●模块解析:按换行拆分用户输入的模块文本,过滤空行,符合「每行一个模块」的输入习惯;
●差异化生成:通过 _is_system_module() 判断模块类型,分别生成不同范围的用例数/BUG数,贴合真实测试场景;
●数据汇总:实时累加总用例数和总BUG数,无需后续单独计算,提升效率;
●用户反馈:生成完成后通过弹窗提示结果,同时刷新界面展示,用户体验友好。
2. 批量数据修改函数:
batch_edit_data()(高频核心功能)
def batch_edit_data(self, parent):# parent:父窗口(修改数据窗口),用于后续关闭module_count = len(self.module_list)# 1. 新建批量输入窗口batch_win = tk.Toplevel(parent)batch_win.title("批量输入用例数/BUG数")batch_win.geometry("500x300")# 2. 展示模块顺序(提示用户按此顺序输入)tk.Label(batch_win, text="模块顺序(请按此顺序用逗号分隔输入):", font=("宋体", 10)).grid(row=0, column=0, columnspan=2, pady=5)module_order = ", ".join(self.module_list)tk.Label(batch_win, text=module_order, font=("宋体", 9), wraplength=450).grid(row=1, column=0, columnspan=2, pady=5)# 3. 用例数输入框(默认填充当前用例数,便于用户修改)tk.Label(batch_win, text="用例数(逗号分隔):").grid(row=2, column=0, padx=5, pady=10, sticky="w")case_entry = tk.Entry(batch_win, width=40)case_entry.grid(row=2, column=1, padx=5, pady=10)current_cases = ",".join([str(self.case_num_dict[module]) formodule in self.module_list])case_entry.insert(0, current_cases)# 4. BUG数输入框(默认填充当前BUG数)tk.Label(batch_win, text="BUG数(逗号分隔):").grid(row=3, column=0, padx=5, pady=10, sticky="w")bug_entry = tk.Entry(batch_win, width=40)bug_entry.grid(row=3, column=1, padx=5, pady=10)current_bugs = ",".join([str(self.bug_num_dict[module]) formodule in self.module_list])bug_entry.insert(0, current_bugs)# 5. 确认修改按钮逻辑def confirm():# 解析用例数:逗号拆分→转整数→校验数量匹配case_str = case_entry.get().strip()try:case_list = [int(num.strip()) for num in case_str.split(",") if num.strip()]except ValueError:self._show_msg("错误", "用例数格式错误!请输入逗号分隔的正整数!")returnif len(case_list) != module_count:self._show_msg("错误", f"用例数数量({len(case_list)})与模块数({module_count})不匹配!")return# 解析BUG数:同上bug_str = bug_entry.get().strip()try:bug_list = [int(num.strip()) for num in bug_str.split(",") if num.strip()]except ValueError:self._show_msg("错误", "BUG数格式错误!请输入逗号分隔的正整数!")returnif len(bug_list) != module_count:self._show_msg("错误", f"BUG数数量({len(bug_list)})与模块数({module_count})不匹配!")return# 6. 更新数据self.total_case = 0self.total_bug = 0for i, module in enumerate(self.module_list):self.case_num_dict[module] = case_list[i]self.bug_num_dict[module] = bug_list[i]self.total_case += case_list[i]self.total_bug += bug_list[i]# 7. 刷新展示+关闭窗口+提示成功self.refresh_base_data_display()batch_win.destroy()parent.destroy()self._show_msg("成功", "批量修改数据完成!")# 6. 绘制确认按钮tk.Button(batch_win, text="确认修改", command=confirm).grid(row=4, column=0, columnspan=2, pady=20)
解析:
●界面友好:自动展示模块顺序,默认填充当前数据,用户无需记忆模块顺序,直接修改即可,降低操作成本;
●严格校验:先校验输入格式(是否为正整数),再校验数量匹配(输入数量=模块数量),从源头杜绝错误数据;
●数据同步:修改后自动更新总用例数/总BUG数,刷新界面展示,确保数据一致性;
●窗口管理:修改完成后自动关闭子窗口和父窗口,无需用户手动关闭,体验流畅。
......
本文节选自第八十九期《51测试天地》
原创文章
《用Python打造了一款超实用的测试报告神器》
文章后续为大家详细讲解了:
源码设计亮点与复用建议总结等
想继续阅读全文
或查看更多《51测试天地》的原创文章
请点击下方 阅读原文或扫描二维码 查看

声明:本文为51Testing软件测试网 M&T. 用户投稿内容,该用户投稿时已经承诺独立承担涉及知识产权的相关法律责任,并且已经向51Testing承诺此文并无抄袭内容。发布本文的用途仅仅为学习交流,不做任何商用,未经授权请勿转载,否则作者和51Testing有权追究责任。如果您发现本公众号中有涉嫌抄袭的内容,欢迎发送邮件至:editor@51testing.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

夜雨聆风