2009年3月8日 星期日

讓 Python 的 unittestgui 可以載入 test suite

由於 pyUnit 附的 unittestgui 怎麼試都沒成功,我改用這個 unittestgui.py:GUI test runner using wxPython。相關說明請見之前的文章。美中不足的是,它不方便載入 test suite,所以我修改了一下這份程式。

程式下載和用法

點此下載修改後的程式碼。使用的範例程式碼如下:

1
2
3
4
5
6
7
8
9
# all_test_suite.py
import unittest
import catsinbag.card_factory_test
import catsinbag.cash_test
 
def suite():
    suites = []
    suites.append(unittest.TestLoader().loadTestsFromTestCase(some_module.SomeTestCase))
    return unittest.TestSuite(suites)

執行 unittestgui.py 後,按 Open 選擇 all_test_suite.py 即可載入。

目前這個工具仍有些問題,像是原始碼改過後,得重開檔案載入後才會生效,所以無法一邊改程式碼一邊按 Run Test。還有錯誤訊息顯示得不夠清楚,而且還是顯示在 console 上,不是顯示在 GUI 上。

修改過程心得

參照 unittest官方文件,最方便載入多個 test cases 和 test suites 的方法,是採用下面這段 code:

1
2
3
suite1 = unittest.TestLoader().loadTestsFromTestCase(SomeTestCase1)
suite2 = unittest.TestLoader().loadTestsFromTestCase(SomeTestCase2)
alltests = unittest.TestSuite([suite1, suite2])

若自己用 console 執行 unittest,只要把 alltests 交給 TextTextRunner 即可,例如:

1
unittest.TextTestRunner(verbosity=2).run(alltests)

但是,一個熱愛寫 testing 程式的程式設計師,除了想要有更高品質的程式碼外,內心更渴望看到 Green Bar啊!所以非得用 GUI 版的 unittest 不可。而 unittestgui.py 可以載入 test case、test suite,卻沒辦法載入 module 內產生的 test suite。所以只好直接改 unittestgui.py 的程式碼。關鍵在於 OnMenuOpen() 如何取得 test suite。原本的程式碼如下:

1
2
3
4
5
6
7
modname, modtype = os.path.splitext(os.path.basename(self.filename))
if modtype.lower() == '.py':
    moduleToTest = imp.load_source(modname, self.filename, file(self.filename))
elif modtype.lower() in {'.pyc':0, '.pyo':0}:
    moduleToTest = imp.load_compiled(modname, self.filename, file(self.filename, 'rb'))
#print moduleToTest, dir(moduleToTest)
self.suite = unittest.defaultTestLoader.loadTestsFromModule(moduleToTest)

修改後的程式碼如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
modname, modtype = os.path.splitext(os.path.basename(self.filename))
if modtype.lower() == '.py':
    moduleToTest = imp.load_source(modname, self.filename, file(self.filename))
elif modtype.lower() in {'.pyc':0, '.pyo':0}:
    moduleToTest = imp.load_compiled(modname, self.filename, file(self.filename, 'rb'))
#print moduleToTest, dir(moduleToTest)
if hasattr(moduleToTest, 'suite'):  # use the prepared suite if it exists.
    if callable(moduleToTest.suite):
        self.suite = moduleToTest.suite()
    else:
        self.suite = moduleToTest.suite
else:
    self.suite = unittest.defaultTestLoader.loadTestsFromModule(moduleToTest)

利用已讀到的 module: moduleToTest,增加判斷它是否有提供 function suite() 或是 attribute suite,若有的話,直接使用準備好的 test suite,而非從 TestCase 或 TestSuite 中產生。

最後附上執行後的精美圖片,辛苦了這麼久,就是為了看到這 Green Bar 啊!

unittestgui_with_suite

沒有留言:

張貼留言