2024年4月18日 星期四

Pytest

http://4rdp.blogspot.com/2024/04/pytest.html?m=0

最近公司 PXI 新儀器開發完成了,終於有時間可以整理一些技術文章,以便日後需要時能夠快速查閱,這一篇文章記錄 pytest 指令常用用法,pytest 是一個 Python 自動測試模組,可以用來判別與記錄測試結果相不相符。

首先 Python 需要安裝 pytest 模組,開啟 Command Prompt,輸入 DOS 指令,

> pip install pytest

然後撰寫一個 Python 程式,但是檔案命名須為 test_XXX.py,程式內依據測試項目再寫出相關的小程式,每一個小測項名稱也是要以 testZZZ() 來命名,每個小程式盡量 50 行以內不要太大,
import pytest

def test1():
    b = 'Apple'
    assert b != 'Hello'    # PASS
    
    a = 1
    assert a == 0          # FAIL 1
    print('--------')      # 上一行錯誤後,從這一行開始就不會被執行
    assert b != 'Apple'    # FAIL 2


def test2():
    b = 'Apple'
    assert b != 'Hello'    # PASS
    
    a = 1
    #assert a == 0          # FAIL

最後執行 pytest 即可,

> pytest

上面指令會測試工作路徑下,包含所有子目錄中檔案名字有 test 的 Python 程式,

> pytest .\path\test_YYY.py > .\path\data.txt

上面指令可以指定特定程式執行,而後面黃色部分可以將螢幕輸出內容存成檔案,方便後續分析問題原因。


接下來介紹進階用法,首先為選項用法,這需要另外新增一個 pytest.ini 檔,否則會出現警告訊息,不過沒有 ini 宣告,也是可以執行。
[pytest]
markers = 
    AAAonly: test cases only for AAA.
    BBBonly: test cases only for BBB.

此外 Python 程式需要加入 @pytest.mark,
@pytest.mark.AAAonly
def test1():
    b = 'Apple'
    assert b != 'Hello'    # PASS
    
    a = 1
    assert a == 0          # FAIL 1
    print('--------')      # 上一行錯誤後,從這一行開始就不會被執行
    assert b != 'Apple'    # FAIL 2


@pytest.mark.BBBonly
def test2():
    b = 'Apple'
    assert b != 'Hello'    # PASS
    
    a = 1
    #assert a == 0         # FAIL

指令需加入 -m 參數,這樣可以指定哪些項目要測試或是不測試,

> pytest test_try.py -m "not AAAonly"


指令加入 -s 參數,可以將程式內 print() 的內容顯示於螢幕上,

 > pytest -s


如果某項目不測試,也可以使用 @pytest.mark.skip,例如
@pytest.mark.skip(reason='太累了,不想測!')
def test0():
    c = 0
    assert c != 0

第二個是參數用法,如果測試時需要變換參數檢查各式條件,請用這方法,它比在程式內使用 for loop 好,可以很容易知道在測試哪個條件時異常,請使用 @pytest.mark.parametrize,
@pytest.mark.parametrize("num", [0, 1])
def test3(num):
    assert num == 0           # check number

它可以多參數同時引入,方法如下,
@pytest.mark.parametrize("index, value, unit", [
                        ( 1,      0.1,   'V'),
                        ( 2,      1.0,   'A'),
    ])
def test4(index, value, unit):
    print('')
    print(f'Index = {index}, Set {value}{unit}')

當你想巢狀測試多個參數,可以用下列的方法,
@pytest.mark.parametrize("num", [0, 1])
@pytest.mark.parametrize("word", ['Apple', 'Hello'])
def test5(num, word):
    assert num == 0           # check number
    assert word != 'Hello'    # check word

pytest 的用法不只這些,有興趣的人可以再研讀 https://docs.pytest.org/ 技術文件。

Python 是一個超好用的程式語言,想當初在工作上吸引我注意到 Python 是一位 Google 工程師,他只寫不到十行程式,就可以測試我當時開發中的儀器,我被這個程式語言的簡潔性驚艷到,之後玩 Raspberry Pi 又遇到它,了解它可跨多種作業系統執行,說它是我現在最愛的程式語言也不為過,目前 TIOBE 調查顯示 Python 已經站上程式流行語言排行第一名,它的廣泛使用性,我想未來很難再有其它程式語言可以超越。

沒有留言:

張貼留言