python - 自动化 tkinter 文件对话以进行功能测试
问题描述
我有一个 Python tkinter 脚本,我想在上面运行一些功能测试。该脚本同时包含tkinter.filedialog.askopenfilename()
and tkinter.filedialog.asksaveasfilename()
,所以我想要上传/下载文件的测试的一部分。我试图用它pyautogui
来尝试自动化鼠标点击并发送键来尝试自动化这些操作,但这样做没有用(屏幕上没有任何可见的变化,也没有加载文件)。
尝试使用 pyautogui 进行功能测试
class TestOrganizeAttendance(unittest.TestCase):
def setUp(self):
self.organizer = AttendanceOrganizer()
...
def test_attendance_organizer_window_operation(self):
...
#User clicks button and their computer's files appear
self.organizer.upload_file_button.invoke()
self.assertIn(
"explorer.exe", [p.name() for p in psutil.process_iter()])
#User selects a file to be uploaded
filepath = os.path.abspath(
os.path.join('.', 'tests', 'sample_attendance.csv'))
pyautogui.PAUSE = 2.5
pyautogui.hotkey('alt', 'd')
pyautogui.typewrite(filepath)
pyautogui.hotkey('enter')
....
脚本
class AttendanceOrganizer:
def __init__(self):
self.upload_file_button = tkinter.Button(
self.root, text="Upload File", command=self.upload_file)
self.download_file_button = tkinter.Button(
self.root, text="Download File", command=self.download_file)
...
def upload_file(self):
self.details_var.set(
value="Select a file to upload")
filetypes = [('Comma Separated Values', '.csv')]
filepath = tkinter.filedialog.askopenfilename(
parent=self.root, filetypes=filetypes)
if not (filepath and os.path.splitext(filepath)[-1] == '.csv'):
return
self.upload_var.set(value=filepath)
self.details_var.set(
value=f"File Uploaded\t{self.details_var.get()}")
with open(filepath, encoding='utf-16') as file:
self.values = list(csv.reader(file, delimiter='\t'))
del self.values[0]
self.organize_data_button.config(state='normal')
def download_file(self):
filetypes = [('Comma Separated Values', '.csv')]
filepath = tkinter.filedialog.asksaveasfilename(
parent=self.root, filetypes=filetypes)
with open(f"{filepath}.csv", 'w', newline='') as file:
fieldnames = ["Last", "First", "Joined", "Left"]
writer = csv.DictWriter(
file, fieldnames=fieldnames, delimiter='\t')
writer.writeheader()
for item in self.data:
writer.writerow(self.data[item])
...
解决方案
上面代码的问题functional_tests.py
是两者tkinter.filedialog.askopenfilename
都是tkinter.filedialog.asksaveaskfilename
阻塞函数,即函数必须在执行进一步的代码之前完成。避免此问题的最简单方法是使用threading
创建一个线程,该线程执行pyautogui
与主线程分开的所有功能。
带有 pyautogui 的functional_tests.py
class TestOrganizeAttendance(unittest.TestCase):
def setUp(self):
...
def tearDown(self):
...
def automate_file_dialogue(self, filepath):
while "explorer.exe" not in [p.name() for p in psutil.process_iter()]: #Wait for the file dialogue to open
continue
directory, filename = os.path.split(filepath)
pyautogui.hotkey('alt', 'd') #Keyboard shortcut to focus the address bar
pyautogui.typewrite(directory)
pyautogui.hotkey('enter')
pyautogui.hotkey('tab')
pyautogui.hotkey('tab')
pyautogui.hotkey('tab') #Repeatedly press TAB to remove focus from the address bar
pyautogui.hotkey('alt', 'n') #Keyboard shortcut to focus the file name
pyautogui.hotkey(filename)
pyautogui.hotkey('enter')
def test_attendance_organizer_window_operation(self):
...
filepath = os.path.abspath(
os.path.join('tests', 'sample_attendance.csv'))
upload_thread = threading.Thread(
target=self.automate_file_dialogue, args=(filepath,))
upload_thread.start()
upload_thread.start()
self.assertTrue(os.path.exists(filepath))
self.organizer.upload_file_button.invoke()
self.assertIn(
"explorer.exe", [p.name() for p in psutil.process_iter()])
upload_thread.join()
...
filepath = os.path.abspath(
os.path.join('tests', 'new_sample_attendance'))
download_thread = threading.Thread(
target=self.automate_file_dialogue, args=(filepath,))
download_thread.start()
self.assertFalse(os.path.exists(filepath))
self.organizer.download_file_button.invoke()
self.assertIn(
"explorer.exe", [p.name() for p in psutil.process_iter()])
download_thread.join()
推荐阅读
- javascript - 将文本颜色图标颜色更改为选定颜色 Froala Editor
- angular - 以角度构造键值对,其中键值将由用户给出
- numpy - numpy.linalg.eig 没有找到明显的特征向量
- php - 在编辑从数据库循环的数据期间,如何在选择选项中获取数据?
- css - 滚动时修复 ThreeJS 模型的位置
- html - 奇怪的弹性项目行为
- database - 了解填充猫鼬
- c++ - 为什么当我调用它时 QTextBrowser::clear() 不能立即工作?
- javascript - 如何将 oswald google 字体作为字体系列下拉列表中的列表应用到 tinymce 编辑器?
- c# - .Net 从 MySQL 转储文件中解析 blob 数据