Python 測試入門 - 前言

我們都知道測試很重要,但複雜的系統總讓人們卻步,故分享一點基本概念想讓這件事看起來沒這麼可怕

最近要做 Python testing 的分享,主要要聊聊 PyTest,順便把內容整理起來丟到部落格來。

有句嘴砲說軟體工程師最喜歡的事是別人可以寫好文件,而最討厭的事是寫文件。相同地,我們總希望能拿到一份有完善測試的腳本,但很多人卻很害怕踏入這個領域。寫測試對不少人而言聽起來十分的複雜,這個分享便是希望可以讓大家稍微去體會到寫測試不見得會是一個麻煩的工作、甚至有機會幫我們解決部分的工作。

本系列文會提到一些非最佳解的方法或情境,但我相信這些 practice 很可能是不少 Python 開發者的日常。

腳本的測試:開端

Python 作為一個膠水語言,在日常使用中它常常只是一個簡短的程式碼、用於把某些資料從 A 地丟去 B 地。也正因為程式的簡短,在許多時候不會凸顯出「寫測試」這個需求。

然後作為一個負責任、不想交出屍體的開發者,有一種測試方法是寫一段程式、打開 REPL、跑一次新的 code、看著它炸掉、讀 error message 並修正,然後重新開始一個循環。

隨著程式愈來愈完成、或需求愈來愈複雜,但是當標準的進入點還沒架構完成之時,這個測試的行為也會愈來愈複雜——可能需要先跑過函數 A 去取得資料 B 、然後餵食給函數 C 來看測試結果:

🍀 ipython
Python 3.9.13 (main, Aug 11 2022, 13:40:36)
Type 'copyright', 'credits' or 'license' for more information
IPython 8.4.0 -- An enhanced Interactive Python. Type '?' for help.

In [1]: def func_a():
   ...:     return 'dlrow olleh'
   ...:

In [2]: def func_b(msg: str):
   ...:     print(''.join(reversed(msg)))
   ...:

In [3]: out = func_a()

In [4]: func_b(out)
hello world

到這個階段,世間的萬物開始複雜了起來,作為職業沙發馬鈴薯,我可不想重複這麼多動作。

所以就會發生下一種操作——把這個過程直接丟在 __main__ 底下:

def func_a():
return 'dlrow olleh'
def func_b(msg: str):
print(''.join(reversed(msg)))
if __name__ == '__main__':
out = func_a()
print(f'{out=}')
func_b(out)

有了這段程式碼,我們就可以升級為這樣的循環:寫一段程式碼、直接跑這隻腳本、看看有沒有出現預期行為、然後修正。

恩,比前面的流程簡單了一些。

然後再思考兩秒,這樣其實就是在寫測試腳本了,把這段程式碼搬家到另外的地方基本上就能成為一組合格的測試了,後面開始介紹測試腳本的實作方法。


續讀:使用內建的 unittest 框架是個什麼體驗 或 看看 使用 PyTest 是個如何的體驗