pytest测试Tkinter待办清单程序时代码无法运行问题求助
问题根因
你的pytest流程无法正常执行是三个核心问题叠加导致的,和pytest框架本身无关:
- 模块导入直接触发Tk主循环:你的
to_do_list.py末尾直接写了window.mainloop(),没有做运行入口保护。只要测试代码执行from to_do_list import add_item, delete_item,就会直接启动Tkinter窗口阻塞整个测试流程,不手动关闭窗口pytest根本不会往下执行测试用例。 - 测试用例传参完全不匹配函数签名:业务代码里
add_item需要接收Entry组件实例、Listbox组件实例两个参数,你测试里只传了一个字符串;delete_item需要接收Listbox组件实例,你测试里调用时没有传任何参数,就算主循环不卡,跑起来也会直接报参数缺失的TypeError。 - 断言逻辑完全不匹配函数行为:两个业务函数都没有写
return返回值,默认返回None,你写的assert add_item('test') == 'test'从逻辑上就不可能成立。
修复步骤
- 先给主程序加运行入口保护
把主程序末尾的窗口启动代码放到if __name__ == "__main__":块里,只有直接运行这个脚本的时候才启动GUI,被测试文件等其他模块导入的时候不会触发主循环:
if __name__ == "__main__": window.update() window.mainloop()
额外提醒:你的业务代码里用到了END、ACTIVE这两个Tkinter常量,记得在to_do_list.py顶部补上from tkinter import END, ACTIVE,不然调用函数时会报常量未定义的错。
- 重写测试用例,正确初始化Tk测试组件
Tkinter的所有控件都必须依附于一个存在的Tk根窗口,测试里要先创建根窗口、测试用的Entry和Listbox控件,再传参给业务函数;断言不要判断不存在的返回值,要判断实际的操作结果:比如Listbox里的条目有没有正确增减、文件有没有正确写入。
参考测试代码如下,用pytest自带的tmp_pathfixture处理文件写入,避免污染你本地真实的items.txt:
from tkinter import Tk, Entry, Listbox import pytest from to_do_list import add_item, delete_item @pytest.fixture def tk_components(monkeypatch, tmp_path): # 初始化Tk根窗口和测试控件 root = Tk() entry = Entry(root) listbox = Listbox(root) # 把业务代码里写入的items.txt重定向到临时目录,不影响本地文件 test_file = tmp_path / "items.txt" def patched_open(file, mode, *args, **kwargs): if file == "items.txt": return open(test_file, mode, *args, **kwargs) return open(file, mode, *args, **kwargs) monkeypatch.setattr("builtins.open", patched_open) yield entry, listbox, test_file # 测试结束销毁根窗口 root.destroy() def test_add_item(tk_components): entry, listbox, test_file = tk_components # 给输入框插入测试内容 entry.insert(0, "测试待办项") # 调用添加函数 add_item(entry, listbox) # 断言列表里确实插入了内容 assert listbox.get(0) == "测试待办项" # 断言文件确实写入了内容 assert "测试待办项" in test_file.read_text(encoding="utf-8") def test_delete_item(tk_components): entry, listbox, test_file = tk_components # 先插入一个测试项并选中 entry.insert(0, "待删除项") add_item(entry, listbox) listbox.select_set(0) # 调用删除函数 delete_item(listbox) # 断言列表里已经没有该项 assert listbox.size() == 0
- 修复业务代码里的逻辑bug
你现在的delete_item函数本身有逻辑问题,就算测试写对了也跑不通:
- 以
r+模式打开文件直接写入会把新内容追加到旧内容后面,不会覆盖原有内容,会导致文件内容重复 - 遍历列表的同时执行
remove操作会漏遍历元素 - 用
line[:-2]做匹配很容易切掉正常的条目内容,判断逻辑不可靠
建议重写文件操作部分,先读全量内容,过滤掉要删除的条目之后再用w模式覆盖写回文件。
内容的提问来源于stack exchange,提问作者Izy
相关产品推荐
相关产品推荐

