问题描述
我有一个 Python tkinter 脚本,我想对其运行一些功能测试。该脚本包括 rgbArray
和 tkinter.filedialog.askopenfilename()
,所以我想要上传/下载文件的测试的一部分。我尝试使用 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')
....
解决方法
上述functional_tests.py
代码的问题在于tkinter.filedialog.askopenfilename
和tkinter.filedialog.asksaveaskfilename
都是阻塞函数,即函数必须在执行进一步代码之前完成。避免此问题的最简单方法是使用 threading
创建一个线程,该线程执行与主线程分开的所有 pyautogui
函数。
functional_tests.py 和 pyautogui
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,))
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()