今天是第十八天我們可以寫一個mock test來測試我們寫的斑馬魚軟體介面,以下是程式碼
import unittest
from unittest.mock import patch, MagicMock
import tkinter as tk
from tkinter import ttk
from your_module import perform_yolo, show_zebrafish_window, select_file, select_weight_file # 假設這些函數在 your_module 中定義
class TestZebrafishGUI(unittest.TestCase):
def setUp(self):
# 初始化tkinter主窗口
self.root = tk.Tk()
self.root.withdraw() # 隱藏主窗口
# 初始化檔案路徑變數
self.file_path_var = tk.StringVar()
self.weight_value_var = tk.StringVar()
# 初始化主框架和小部件
self.main_frame = ttk.Frame(self.root)
self.main_frame.grid(row=0, column=0, sticky="nsew")
# 建立 image_label 來顯示圖片
self.image_label = ttk.Label(self.main_frame)
self.image_label.grid(row=4, column=0, columnspan=3, padx=5, pady=5, sticky="nsew")
def test_select_file(self):
with patch('your_module.filedialog.askopenfilename', return_value='/path/to/image.gif'):
select_file()
self.assertEqual(self.file_path_var.get(), '/path/to/image.gif')
def test_select_weight_file(self):
with patch('your_module.filedialog.askopenfilename', return_value='/path/to/weights.weights'):
select_weight_file()
self.assertEqual(self.weight_value_var.get(), '/path/to/weights.weights')
def test_perform_yolo(self):
# 模擬 YOLO 計算
with patch('your_module.yolo_calculate', return_value='/path/to/result.gif'), \
patch('your_module.load_image'), \
patch('your_module.show_zebrafish_window') as mock_show_window:
perform_yolo()
mock_show_window.assert_called_once()
def test_show_zebrafish_window(self):
with patch('your_module.ttk.Button') as mock_button:
show_zebrafish_window()
self.assertTrue(mock_button.called)
def tearDown(self):
self.root.destroy()
if __name__ == '__main__':
unittest.main()
import unittest
from unittest.mock import patch, MagicMock
import tkinter as tk
from tkinter import ttk
from your_module import perform_yolo, show_zebrafish_window, select_file, select_weight_file
unittest
:Python 的內建測試框架,用來編寫和執行測試案例。unittest.mock
:這是一個允許你在測試中替代和模擬 Python 物件的模組。它提供了 patch
和 MagicMock
來模擬和替換真實的函數或物件。tkinter
和 ttk
:Python 的標準 GUI 庫,用來建立視覺化介面。from your_module import ...
:假設你的 perform_yolo
, show_zebrafish_window
, select_file
, select_weight_file
函數在 your_module
中定義,這一行將它們匯入以供測試。class TestZebrafishGUI(unittest.TestCase):
def setUp(self):
# 初始化tkinter主窗口
self.root = tk.Tk()
self.root.withdraw() # 隱藏主窗口
# 初始化檔案路徑變數
self.file_path_var = tk.StringVar()
self.weight_value_var = tk.StringVar()
# 初始化主框架和小部件
self.main_frame = ttk.Frame(self.root)
self.main_frame.grid(row=0, column=0, sticky="nsew")
# 建立 image_label 來顯示圖片
self.image_label = ttk.Label(self.main_frame)
self.image_label.grid(row=4, column=0, columnspan=3, padx=5, pady=5, sticky="nsew")
setUp(self)
:unittest
框架中的 setUp()
方法在每次執行測試之前自動運行。它主要用來設定測試的初始條件。self.root = tk.Tk()
:建立 tkinter 的主窗口。self.root.withdraw()
:隱藏主窗口。這在測試中很常見,因為通常不需要真正顯示 GUI。self.file_path_var
和 self.weight_value_var
:這些是 tkinter 的字串變數,用來儲存選擇的檔案路徑和權重檔案路徑。self.main_frame
:建立一個框架來容納介面中的小部件。self.image_label
:建立一個用來顯示圖像的標籤。 def test_select_file(self):
with patch('your_module.filedialog.askopenfilename', return_value='/path/to/image.gif'):
select_file()
self.assertEqual(self.file_path_var.get(), '/path/to/image.gif')
patch('your_module.filedialog.askopenfilename', return_value='/path/to/image.gif')
:使用 patch
來模擬 filedialog.askopenfilename
的行為,並設定它返回一個固定的檔案路徑。select_file()
:呼叫模擬過的 select_file()
函數。self.assertEqual(self.file_path_var.get(), '/path/to/image.gif')
:驗證 file_path_var
變數的值是否與預期的檔案路徑相同。 def test_select_weight_file(self):
with patch('your_module.filedialog.askopenfilename', return_value='/path/to/weights.weights'):
select_weight_file()
self.assertEqual(self.weight_value_var.get(), '/path/to/weights.weights')
這段程式碼與 test_select_file()
類似,只是它測試的是選擇權重檔案的功能。
def test_perform_yolo(self):
# 模擬 YOLO 計算
with patch('your_module.yolo_calculate', return_value='/path/to/result.gif'), \
patch('your_module.load_image'), \
patch('your_module.show_zebrafish_window') as mock_show_window:
perform_yolo()
mock_show_window.assert_called_once()
patch('your_module.yolo_calculate', return_value='/path/to/result.gif')
:模擬 yolo_calculate
函數,設定它返回一個固定的結果圖像路徑。patch('your_module.load_image')
:模擬 load_image
函數,因為我們在測試中不需要真的去加載圖像。patch('your_module.show_zebrafish_window') as mock_show_window
:模擬 show_zebrafish_window
函數,並將其模擬物件命名為 mock_show_window
。perform_yolo()
:呼叫 perform_yolo
函數。mock_show_window.assert_called_once()
:檢查 show_zebrafish_window
是否被正確呼叫一次。 def test_show_zebrafish_window(self):
with patch('your_module.ttk.Button') as mock_button:
show_zebrafish_window()
self.assertTrue(mock_button.called)
patch('your_module.ttk.Button') as mock_button
:模擬 ttk.Button
,以便監控按鈕的建立。show_zebrafish_window()
:呼叫 show_zebrafish_window
函數。self.assertTrue(mock_button.called)
:驗證 ttk.Button
是否有被呼叫,確認按鈕有被正確建立。 def tearDown(self):
self.root.destroy()
tearDown(self)
:unittest
框架中的 tearDown()
方法在每次測試之後自動運行。它主要用來清理測試環境。self.root.destroy()
:銷毀 tkinter 主窗口,釋放資源。if __name__ == '__main__':
unittest.main()
unittest
會自動搜尋並運行所有定義在這個檔案中的測試。這個測試代碼模擬了 tkinter GUI 的行為,並確保各個功能在測試中能夠正確運作。透過 unittest
和 unittest.mock
的結合,我可以有效地檢查 GUI 程式碼的功能是否符合預期。