目錄:
- 安裝及入門
- 使用和調用方法
- 原有TestSuite使用方法
- 斷言的編寫和報告
- Pytest fixtures:清晰 模塊化 易擴展
- 使用Marks標記測試用例
- Monkeypatching,對模塊和環境進行Mock
- 使用tmp目錄和文件
- 捕獲stdout及stderr輸出
- 捕獲警告信息
- 模塊及測試文件中集成doctest測試
- skip及xfail: 處理不能成功的測試用例
- Fixture方法及測試用例的參數化
- 緩存: 使用跨執行狀態
- unittest.TestCase支持
- 運行Nose用例
- 安裝和使用插件
- 插件編寫
- 編寫鉤子(hook)方法
- API參考
- 優質集成實踐
- 片狀測試
- Pytest導入機制及sys.path/PYTHONPATH
- 配置選項
- 示例及自定義技巧
- Bash自動補全設置
unittest.TestCase支持
pytest
支持unittest
開箱即用的基于Python 的測試。它旨在利用現有unittest
的測試套件將pytest用作測試運行器,并允許逐步調整測試套件以充分利用pytest的功能。
要使用運行現有unittest
樣式的測試套件pytest
,請鍵入:
pytest tests
pytest將自動收集unittest.TestCase
子類及其test
方法test_*.py
或*_test.py
文件。
幾乎所有unittest
功能都受支持:
-
@unittest.skip
風格裝飾; -
setUp/tearDown
; -
setUpClass/tearDownClass
; -
setUpModule/tearDownModule
;
到目前為止,pytest不支持以下功能:
- load_tests協議 ;
- 分測驗 ;
開箱即用的好處
通過使用pytest運行測試套件,你可以使用多種功能,在大多數情況下無需修改現有代碼:
- 獲得更多信息性的追溯 ;
- stdout和stderr捕獲;
-
使用
-k
和-m
標記測試選擇選項 ; - 在第一次(或N次)故障后停止 ;
- -pdb命令行選項,用于調試測試失?。▍⒁娤旅娴?a target="_blank" rel="nofollow">注釋);
- 使用pytest-xdist插件將測試分發給多個CPU ;
- 使用普通的assert-statements而不是
self.assert*
函數(unittest2pytest對此非常有幫助);
unittest.TestCase
子類中的pytest特性
以下pytest功能適用于unittest.TestCase
子類:
下面pytest功能不工作,也許永遠也因不同的設計理念:
第三方插件可能運行也可能不運行,具體取決于插件和測試套件。
unittest.TestCase
使用標記將pytest燈具混合到子類中
運行unittest pytest
允許你使用其 夾具機制進行unittest.TestCase
樣式測試。假設你至少瀏覽了pytest fixture功能,讓我們跳轉到一個集成pytest db_class
fixture,設置類緩存數據庫對象,然后從unittest樣式測試中引用它的示例:
# content of conftest.py
# we define a fixture function below and it will be "used" by
# referencing its name from tests
import pytest
@pytest.fixture(scope="class")
def db_class(request):
class DummyDB(object):
pass
# set a class attribute on the invoking test context
request.cls.db = DummyDB()
這定義了一個fixture函數db_class
- 如果使用的話 - 為每個測試類調用一次,并將class-level db
屬性設置為一個DummyDB
實例。fixture函數通過接收一個特殊request
對象來實現這一點,該對象允許訪問請求測試上下文,例如cls
屬性,表示使用該fixture的類。該架構將夾具寫入與實際測試代碼分離,并允許通過最小參考(夾具名稱)重新使用夾具。那么讓unittest.TestCase
我們使用fixture定義編寫一個實際的類:
# content of test_unittest_db.py
import unittest
import pytest
@pytest.mark.usefixtures("db_class")
class MyTest(unittest.TestCase):
def test_method1(self):
assert hasattr(self, "db")
assert 0, self.db # fail for demo purposes
def test_method2(self):
assert 0, self.db # fail for demo purposes
在@pytest.mark.usefixtures("db_class")
類的裝飾可確保pytest固定函數db_class
被調用每一次班。由于故意失敗的斷言語句,我們可以看看self.db
回溯中的值:
$ pytest test_unittest_db.py
=========================== test session starts ============================
platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y
cachedir: $PYTHON_PREFIX/.pytest_cache
rootdir: $REGENDOC_TMPDIR
collected 2 items
test_unittest_db.py FF [100%]
================================= FAILURES =================================
___________________________ MyTest.test_method1 ____________________________
self = <test_unittest_db.MyTest testMethod=test_method1>
def test_method1(self):
assert hasattr(self, "db")
> assert 0, self.db # fail for demo purposes
E AssertionError: <conftest.db_class.<locals>.DummyDB object at 0xdeadbeef>
E assert 0
test_unittest_db.py:9: AssertionError
___________________________ MyTest.test_method2 ____________________________
self = <test_unittest_db.MyTest testMethod=test_method2>
def test_method2(self):
> assert 0, self.db # fail for demo purposes
E AssertionError: <conftest.db_class.<locals>.DummyDB object at 0xdeadbeef>
E assert 0
test_unittest_db.py:12: AssertionError
========================= 2 failed in 0.12 seconds =========================
這個默認的pytest回溯顯示兩個測試方法共享同一個self.db
實例,這是我們在編寫上面的類范圍的fixture函數時的意圖。
使用autouse燈具和訪問其他燈具
雖然通常更好地明確聲明對給定測試需要使用的燈具,但有時你可能想要在給定的上下文中自動使用燈具。畢竟,傳統的unittest-setup風格要求使用這種隱含的夾具編寫,而且很有可能,你習慣它或者喜歡它。
你可以使用標記夾具功能@pytest.fixture(autouse=True)
并在要使用它的上下文中定義夾具功能。讓我們看一個initdir
夾具,它使一個TestCase
類的所有測試方法都 在一個預先初始化的臨時目錄中執行samplefile.ini
。我們的initdir
fixture本身使用pytest builtin tmpdir fixture來委托創建一個per-test臨時目錄:
# content of test_unittest_cleandir.py
import pytest
import unittest
class MyTest(unittest.TestCase):
@pytest.fixture(autouse=True)
def initdir(self, tmpdir):
tmpdir.chdir() # change to pytest-provided temporary directory
tmpdir.join("samplefile.ini").write("# testdata")
def test_method(self):
with open("samplefile.ini") as f:
s = f.read()
assert "testdata" in s
由于該autouse
標志,initdir
fixture函數將用于定義它的類的所有方法。這是@pytest.mark.usefixtures("initdir")
在類中使用標記的快捷方式,如上例所示。
運行此測試模塊......:
$ pytest -q test_unittest_cleandir.py
. [100%]
1 passed in 0.12 seconds
...給我們一個通過測試,因為initdir
夾具功能在之前執行test_method
。
注意
unittest.TestCase
方法不能直接接收fixture參數作為實現可能會導致運行通用unittest.TestCase測試套件的能力。
以上usefixtures
和autouse
示例應該有助于將pytest燈具混合到unittest套件中。
你也可以逐步從子類化轉移unittest.TestCase
到普通斷言 ,然后開始逐步從完整的pytest功能集中受益。
注意
從unittest.TestCase
子類運行測試--pdb
將禁用針對發生異常的情況的tearDown和cleanup方法。這允許對所有在其tearDown機器中具有重要邏輯的應用程序進行適當的事后調試。但是,支持此功能會產生以下副作用:如果人們覆蓋unittest.TestCase
__call__
或者run
需要以debug
相同的方式覆蓋(對于標準unittest也是如此)。
注意
由于兩個框架之間的架構差異,在unittest
測試call
階段而不是在pytest
標準setup
和teardown
階段中執行基于測試的設置和拆卸。在某些情況下,這一點非常重要,特別是在推理錯誤時。例如,如果unittest
基于a 的套件在設置期間出現錯誤,pytest
則在其setup
階段期間將報告沒有錯誤, 并且將在此期間引發錯誤call
。