Skip to main content

使用 nose 測試工具簡單做測試

· 4 min read

楔子

自從聽說了敏捷方法 (Agile programming) 後,一直很想試試這種 "測試先行" 的開發方式. 但是在 python 上前後試過 unitest, doctest, 都不夠 "簡單到會想常常拿來用" 的程度,

今天拿了一份原型寫得差不多的程式,試著寫些測試例子 (test case) 後用 nose 測試工具來測試看看,想不到 nose 還蠻容易使用的.

三步驟使用 nose 開始測試

  1. 安裝或更新 nose

# easy_install -U nose

沒用過 easy_install ? 你該開始試著用了!

  1. 撰寫測試例子 (test case)

打開一個新的資料夾,我們統一在這個新資料夾裡寫主程式與測試例子

將要測試的內容寫入 something.py 這個檔案 [註 1]:

> class Hello(object):
> def __init__(self):
> self.template = "hello world"
>
> def render(self):
> return self.template

nose 測試工具識別測試例子的條件,是判斷找到的這個類別或方法的名稱是不是以 "test" 或 "Test" 開頭。如果是的話就當成是測試例子. nose 會自動搜尋子目錄下所有符合的測試例子,並自動開始測試.

因此我們第一個範例程式用的測試例子只要是函式名稱用 'test' 開頭來命名就可以囉,我們命名一個檔案 testsomething.py (這個檔案名稱以 test 開頭與識別測試例子的條件並無關聯,只是慣例上放測試的例子的檔名都會加上 test 字樣), 並在裡面寫下:

testsomething.py:

>
> def test_Hello():
> abc = Hello()
> assert "hello" in abc.render()
>
> def test_foreign():
> abc = Hello()
> assert "bonjour" not in abc.render()

assert 是 nose 用來判斷測試結果的語法。主要有這兩種:

  • assert 片段 in "結果"

  • assert 片段 not in "結果" 對照上面範例,可以得知上面兩者的意思就是:

  • 測試結果 "hello" 字串應該在 abc.render () 回應的結果裡

  • 測試結果 "bonjour" 字串應該不會在 abc.render () 回應的結果裡如果上面任一種情況不符合 assert 敘述,這個測試用例就會回報失敗.

  1. 開始測試

切換到檔案在的檔案目錄下,輸入

# nosetests

結果應該類似這個樣子:

> D:\path\pyfile>nosetests
> ......
> ----------------------------------------------------------------------
> Ran 1 tests in 0.020s
>

OK 那麼如果我們改動了 something.py 中 self.template 變數的內容,在內容裡加上了 "bonjour" 字樣,會發生什麼事情呢?

有測試工具的好處就是我們只要單純地再次運行 nosetests 命令就好了,不用花腦力去判斷或思考:) 我們查看訊息時會看到類似以下的訊息:

> 2, in runTest
> self.testFunc()
> File "D:\path\pyfile\testsomething.py", line 90, in test_Hello
> assert "bonjour" not in abc.render()
> AssertionError
> -----------------
> Ran 1 tests in 0.030s
>
> FAILED (failures=1, errors=1)
>

上面的報告提醒我們有一件錯誤: "bonjour" 字串原本不應該出現在 abc.render () 回應結果中的,但結果中竟然出現了!

所以如果我們的測試用例寫的好,就可以肯定我們剛剛改動 something.py 時出了些問題。測試這件事確實有效!

較好的約定

我們已經知道,只要類別或方法的名稱是以 "test" 或 "Test" 開頭。就會被 nose 當成是測試例子,所以其實在一個小程式中,我們大可把測試例子跟主程式放在同一個檔案裡.

但是當你都還不很確定你在幹什麼的時候,我建議還是將測試例子跟主程式分開。這麼做除了程式不容易搞混之外,在切換檔案時,還可以順便切換撰寫程式與撰寫測試例子時的不同 MindSet.

測試驅動

那麼如果我們想改寫 hello 函式,好讓它可以用法語 "bonjour" 打招呼,我們該怎麼辦? 記得 "測試先行", 考慮加上一個新的測試例子,而不影響原本的功能吧!

加入的測試例子:

>
> def test_bonjour():
> abc = Hello('bonjour')
> assert "bonjour" in abc.render()

接著要做的就是再跑一次 nosetests, 看到這個新的例子跟我們報告錯誤了. OK, 那就開始修改 hello 函式吧![註 2]

其他的測試

nose 支援的測試的方式琳瑯滿目,可以使用 "nosetests -h" 命令來查看支援的項目.

例如另外一個常用的測試方式是使用 doctest: nosetests --with-doctest

那麼 doctest 是什麼樣的測試方式? 又該怎麼使用 doctest 呢?嘿嘿,4 月 OSDC.tw 07 再開講囉:D

我知道這個工具已經快半年了,到今天才有時間,勇氣真的下去嘗試. 讓我白白錯過這樣好用的工具這麼久,應該怪在 nose 太少文件可以參考的頭上吧? 乾脆自己來寫個 "三步驟使用 nose 開始測試" 的簡易文件好了.

註 1: 這篇文章不講怎麼寫 python 程式,這部份請自理:P 註 2: 同註 1, 建議妳逛逛 www.python.org.tw 可以看到更多參考資料

python 禪學

· 2 min read

任何安裝好的 python 版本中都包含著 python 禪學 (哲學), 在任何 python 互動介面 (如 IDLE) 中輸入

import this

則會出現如下的 python 禪學 (哲學)

Python 禪學 (pythoon Zen)

美觀的比醜陋的好 (Beautiful is better than ugly) 直率的比含糊的好 (Explicit is better than implicit) 簡單的比繁雜的好 (Simple is better than complex) 繁雜的比晦澀的好 (Complex is better than complicated) 平直的比巢雜的好 (Flat is better than nested) 疏落有致的比櫛次鱗比的好 (Sparse is better than dense) 可讀性應當被重視 (Readability counts)

就算是特例,也不能壞了規矩 (Special cases aren't special enough to break the rules) 然而能解決問題仍然比維持單純重要 (Although practicality beats purity)

錯誤不應該被默默地放過 (Errors should never pass silently) 除非你是刻意為之 (Unless explicitly silenced)

面對模稜兩可的情況,要抗拒猜測的誘惑 (In the face of ambiguity, refuse the temptation to guess) 應該會有一個 -- 而且最好只有一個 -- 適當的方式來實現 (There should be one-- and preferably only one --obvious way to do it) 雖然不是這個語言創造者的妳一開始可能看不出來 (Although that way may not be obvious at first unless you're Dutch)

現在動手比總是不動手的好 (Now is better than never) 然而不動手可能還比沒有準備就動手的好 (Although never is often better than right now)

如果實作方式難以解釋,那大概是個壞主意 (If the implementation is hard to explain, it's a bad idea) 如果實作方式易於解釋,那可能是個好主意 (If the implementation is easy to explain, it may be a good idea) 名稱空間是一個很棒的主意 -- 我們就盡量用吧!(Namespaces are one honking great idea -- let's do more of those!)

--Tim Peters (gasolin 翻譯)

2007/03/01 更新: 參考 http://wiki.python.org.tw/The_Zen_Of_Python 其他人的理解修改

示範影片: 使用 TurboGears 製作書站

· One min read

前幾個禮拜看到 limodou 的 Openbook platform 後弄的 TurboGears 製作書站 screencast (示範影片)

第一個影片裡示範了如何使用 TurboGears 建立一個專案,與如何啟動開發用網頁伺服器. 並展示了如何透過修改模板快速訂製頁面。這個 screencast 中完全使用 TurboGears 預設的 CSS style.

1st. is a quickstart demo with hello world template version (6.5MB)

第二個影片裡示範了如何使用 TurboGears 工具箱 (Toolbox) 中的模型設計工具 (Model Designer)和資料編輯工具 (Catwalk) 來建置 TurboGears 動態內容網站

2nd is Model Designer with Catwalk (7.7MB)

第三個影片中使用到我寫的 TurboGears tgcrud 擴充模組,透過 tgcrud 擴充模組可以很容易地產生類似 Rails 的 scaffold 介面架構。但與 scaffold 不同的是所有 code 都是 implicit 的,更加容易修改.

3rd. is tgcrud, the TG's scaffold (5.2 MB)

感謝 Elvelind Grandin 協助上傳至 TurboGears 網頁空間.