Pytest學習(二)
第一次(或n次)故障後停止
在第一(n)次失敗後停止測試過程:
pytest -x # stop after first failure
pytest --maxfail=2 # stop after two failures
指定測試/選擇測試
pytest支援幾種方法來執行和從命令列中選擇測試。
在模組中執行測試
pytest test_mod.py
在目錄中執行測試
pytest testing/
按關鍵字表達式執行測試
pytest -k "MyClass and not method"
這將執行包含與給定名稱匹配的名稱的測試字串表示式
TestMyClass.test_something
但不是TestMyClass.test_method_simple
.
標記函式
Pytest 查詢測試策略
預設情況下,pytest 會遞迴查詢當前目錄下所有以test
開始或結尾的 Python 指令碼,並執行檔案內的所有以test
開始或結束的函式和方法。
對於下面指令碼:
# test_no_mark.py
def test_func1():
assert 1 == 1
def test_func2():
assert 1 != 1
直接執行測試指令碼會同時執行所有測試函式:
$ pytest tests/test-function/test_no_mark.py ============================= test session starts ============================= platform win32 -- Python 3.6.4, pytest-3.6.1, py-1.5.2, pluggy-0.6.0 rootdir: F:\self-repo\learning-pytest, inifile: collected 2 items tests\test-function\test_no_mark.py .F [100%] ================================== FAILURES =================================== _________________________________ test_func2 __________________________________ def test_func2(): > assert 1 != 1 E assert 1 != 1 tests\test-function\test_no_mark.py:6: AssertionError ===================== 1 failed, 1 passed in 0.07 seconds ======================
標記測試函式
由於某種原因(如test_func2
的功能尚未開發完成),我們只想執行指定的測試函式。在 pytest 中有幾種方式可以解決:
第一種,顯式指定函式名,通過::
標記。
$ pytest tests/test-function/test_no_mark.py::test_func1 ============================= test session starts ============================= platform win32 -- Python 3.6.4, pytest-3.6.1, py-1.5.2, pluggy-0.6.0 rootdir: F:\self-repo\learning-pytest, inifile: collected 1 item tests\test-function\test_no_mark.py . [100%] ========================== 1 passed in 0.02 seconds ===========================
第二種,使用模糊匹配,使用-k
選項標識。
$ pytest -k func1 tests/test-function/test_no_mark.py ============================= test session starts ============================= platform win32 -- Python 3.6.4, pytest-3.6.1, py-1.5.2, pluggy-0.6.0 rootdir: F:\self-repo\learning-pytest, inifile: collected 2 items / 1 deselected tests\test-function\test_no_mark.py . [100%] =================== 1 passed, 1 deselected in 0.03 seconds ====================
註解
以上兩種方法,第一種一次只能指定一個測試函式,當要進行批量測試時無能為力;第二種方法可以批量操作,但需要所有測試的函式名包含相同的模式,也不方便。
第三種,使用pytest.mark
在函式上進行標記。
帶標記的測試函式如:
# test_with_mark.py
@pytest.mark.finished
def test_func1():
assert 1 == 1
@pytest.mark.unfinished
def test_func2():
assert 1 != 1
測試時使用-m
選擇標記的測試函式:
$ pytest -m finished tests/test-function/test_with_mark.py ============================= test session starts ============================= platform win32 -- Python 3.6.4, pytest-3.6.1, py-1.5.2, pluggy-0.6.0 rootdir: F:\self-repo\learning-pytest, inifile: collected 2 items / 1 deselected tests\test-function\test_with_mark.py . [100%] =================== 1 passed, 1 deselected in 0.10 seconds ====================
使用 mark,我們可以給每個函式打上不同的標記,測試時指定就可以允許所有被標記的函式。
註解
一個函式可以打多個標記;多個函式也可以打相同的標記。
執行測試時使用-m
選項可以加上邏輯,如:
$ pytest -m "finished and commit" $ pytest -m "finished and not merged"
跳過測試
上一節提到 pytest 使用標記過濾測試函式,所以對於那些尚未開發完成的測試,最好的處理方式就是略過而不執行測試。
按正向的思路,我們只要通過標記指定要測試的就可以解決這個問題;但有時候的處境是我們能進行反向的操作才是最好的解決途徑,即通過標記指定要跳過的測試。
Pytest 使用特定的標記pytest.mark.skip
完美的解決了這個問題。
# test_skip.py
@pytest.mark.skip(reason='out-of-date api')
def test_connect():
pass
執行結果可以看到該測試已被忽略:
$ pytest tests/test-function/test_skip.py ============================= test session starts ============================= platform win32 -- Python 3.6.4, pytest-3.6.1, py-1.5.2, pluggy-0.6.0 rootdir: F:\self-repo\learning-pytest, inifile: collected 1 item tests\test-function\test_skip.py s [100%] ========================== 1 skipped in 0.13 seconds ==========================
註解
pytest 使用s
表示測試被跳過(SKIPPED
)。
Pytest 還支援使用pytest.mark.skipif
為測試函式指定被忽略的條件。
@pytest.mark.skipif(conn.__version__ < '0.2.0',
reason='not supported until v0.2.0')
def test_api():
pass
以前-好記性不如爛筆頭 現在-好記性不如爛鍵盤