Pytest官方教程-02-使用和調用方法

目錄:

  1. 安裝及入門
  2. 使用和調用方法
  3. 原有TestSuite使用方法
  4. 斷言的編寫和報告
  5. Pytest fixtures:清晰 模塊化 易擴展
  6. 使用Marks標記測試用例
  7. Monkeypatching/對模塊和環(huán)境進行Mock
  8. 使用tmp目錄和文件
  9. 捕獲stdout及stderr輸出
  10. 捕獲警告信息
  11. 模塊及測試文件中集成doctest測試
  12. skip及xfail: 處理不能成功的測試用例
  13. Fixture方法及測試用例的參數化
  14. 緩存: 使用跨執(zhí)行狀態(tài)
  15. unittest.TestCase支持
  16. 運行Nose用例
  17. 經典xUnit風格的setup/teardown
  18. 安裝和使用插件
  19. 插件編寫
  20. 編寫鉤子(hook)方法
  21. 運行日志
  22. API參考
    1. 方法(Functions)
    2. 標記(Marks)
    3. 鉤子(Hooks)
    4. 裝置(Fixtures)
    5. 對象(Objects)
    6. 特殊變量(Special Variables)
    7. 環(huán)境變量(Environment Variables)
    8. 配置選項(Configuration Options)
  23. 優(yōu)質集成實踐
  24. 片狀測試
  25. Pytest導入機制及sys.path/PYTHONPATH
  26. 配置選項
  27. 示例及自定義技巧
  28. Bash自動補全設置

使用和調用方法

使用python -m pytest調用pytest

2.0版本新增
你可以在命令行中通過Python編譯器來調用pytest執(zhí)行測試

python -m pytest [...]

通過python調用會將當前目錄也添加到sys.path中蓖扑,除此之外,這幾乎等同于命令行直接調用pytest [...]

可能出現的執(zhí)行退出code

執(zhí)行pytest可能會出現6中不同的退出code:

  • 退出code 0: 收集并成功通過所有測試用例
  • 退出code 1: 收集并運行了測試根穷,部分測試用例執(zhí)行失敗
  • 退出code 2: 測試執(zhí)行被用戶中斷
  • 退出code 3: 執(zhí)行測試中發(fā)生內部錯誤
  • 退出code 4: pytest命令行使用錯誤
  • 退出code 5: 沒有收集到測試用例

獲取版本路徑、命令行選項及環(huán)境變量相關幫助

pytest --version   # 顯示pytest導入位置
pytest --fixtures  # 顯示可用的內置方法參數
pytest -h | --help # 顯示命令行及配置文件選項幫助信息

第1(N)次失敗后停止測試

在第1(N)次用例失敗后停止測試執(zhí)行:

pytest -x            # 第1次失敗后停止
pytest --maxfail=2    # 2次失敗后停止

指定及選擇測試用例

Pytest支持多種從命令行運行和選擇測試用例的方法弃理。
運行模塊內所有用例

pytest test_mod.py

運行目錄內所有用例

pytest testing/

按關鍵字表達式運行測試

pytest -k "MyClass and not method"

這將運行包含與給定字符串表達式匹配的名稱的測試用例,其中可以包括文件名屎蜓、類名和函數名作為變量及Python運算符操作痘昌。上面的示例將運行TestMyClass.test_something但不運行TestMyClass.test_method_simple
按節(jié)點id運行測試
每次執(zhí)行收集到的測試集合都會被分配一個唯一的nodeid梆靖,其中包含模塊文件名控汉,后跟說明符,如類名返吻、函數名及參數姑子,由:: 字符分隔。
執(zhí)行模塊中某條指定的測試用例:

pytest test_mod.py::test_func

另一個通過命令行挑選所執(zhí)行測試方法的示例:

pytest test_mod.py::TestClass::test_method

通過標記表達式運行測試

pytest -m slow

這將會執(zhí)行所有帶@pytest.mark.slow裝飾器的用例测僵。
有關更多信息街佑,請參閱標記
從包中運行測試

pytest --pyargs pkg.testing

這將會導入pkg.testing并使用其文件系統(tǒng)位置來查找和運行測試。

修改Python追溯(traceback)信息

修改回追溯信息示例:

pytest --showlocals # 在追溯信息中顯示局部變量
pytest -l           # 顯示局部變量 (簡寫)

pytest --tb=auto    # (默認) 第1和最后1條使用詳細追溯信息捍靠,其他使用簡短追溯信息

pytest --tb=long    # 詳盡沐旨,信息豐富的追溯信息格式
pytest --tb=short   # 簡短的追溯信息格式
pytest --tb=line    # 每個失敗信息一行
pytest --tb=native  # Python標準庫格式
pytest --tb=no      # 不使用追溯信息

詳盡的摘要報告

2.9版本新增
-r標志可用于在測試會話結束時顯示測試結果摘要,從而可以在大型測試套件中輕松獲得所有失敗榨婆、跳過磁携、標記失敗(xfails)等測試結果的清晰圖像。
例如:

$ pytest -ra
=========================== test session starts ============================
platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y
rootdir: $REGENDOC_TMPDIR, inifile:
collected 0 items

======================= no tests ran in 0.12 seconds =======================

-r選項接受后面的多個字符良风,上面使用的a表示“除了執(zhí)行通過(Pass)以外所有的結果”谊迄。
以下是可以使用的可用字符的完整列表:
-f - 失敗的用例
-E - 出錯的用例
-s - 跳過的用例
-x - 標記失敗的用例
-X - 標記成功的用例
-p - 成功用例
-P - 成功用例并輸出信息
-a - 所有pP狀態(tài)以外的用例

可以使用多個字符闷供,例如,只查看失敗和跳過的用例统诺,你可以執(zhí)行:

$ pytest -rfs
=========================== test session starts ============================
platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y
rootdir: $REGENDOC_TMPDIR, inifile:
collected 0 items

======================= no tests ran in 0.12 seconds =======================

執(zhí)行失敗時進入PDB (Python調試器)

Python附帶一個名為PDB的內置Python調試器歪脏。 pytest允許通過命令行選項進入PDB提示符:

pytest --pdb

這將在每次失敗(或KeyboardInterrupt)時調用Python調試器。一般粮呢,你可能只希望在第一次失敗的測試中執(zhí)行此操作以了解某種故障情況:

pytest -x --pdb   # 在第一次用例失敗時進入PDB
pytest --pdb --maxfail=3  # 在前3次失敗是進入PDB

注意婿失,在任何失敗時,異常信息都存儲在`sys.last_value1啄寡,1sys.last_type1和1sys.last_traceback1中豪硅。在交互模式中,這允許用戶使用任何調試工具進行事后調試这难。也可以手動訪問異常信息舟误,例如:

>>> import sys
>>> sys.last_traceback.tb_lineno
42
>>> sys.last_value
AssertionError('assert result == "ok"',)

測試開始時進入PDB(Python調試器)

pytest允許用戶通過命令行選項在每次測試開始時立即進入PDB提示符:

pytest --trace

這將在每次測試開始時調用Python調試器葡秒。

設置斷點

要在代碼中設置斷點姻乓,需要在代碼中使用Python原生import pdb; pdb.set_trace()進行調用,pytest會自動禁用顯示并捕獲該用例輸出結果:

  • 其他測試中的輸出捕獲不受影響眯牧。
  • 任何先前的測試輸出已經被捕獲并將被處理蹋岩。
  • 在同一測試中生成的任何后續(xù)輸出都不會被捕獲,而是直接發(fā)送到sys.stdout学少。注意:即使是退出交互式PDB跟蹤會話并繼續(xù)常規(guī)測試后發(fā)生的測試輸出剪个,這也適用。

使用內置斷點方法

Python 3.7引入了內置breakpoint()函數版确。 Pytest支持以下幾種使用breakpoint()的方式:

  • PYTHONBREAKPOINT設置為默認值扣囊,調用breakpoint()時,pytest將使用其內部PDB跟蹤交互界面(PDB trace UI)而不是Python自帶的Pdb绒疗。
  • 測試完成后侵歇,默認會重置為Python自帶的PDB跟蹤交互界面。
  • 在pytest后使用--pdb參數吓蘑,在失敗的測試/未處理異常中惕虑,pytest內部PDB跟蹤交互界面與breakpoint()同時使用。
  • --pdbcls參數可指定要使用的調試器類磨镶。

分析測試執(zhí)行持續(xù)時間

顯示執(zhí)行最慢的10條測試用例:

pytest --durations=10

除非在命令行上傳遞-vv溃蔫,默認情況下,否則pytest不會顯示<0.01s的測試時間琳猫。

創(chuàng)建JUnitXML格式文件

要創(chuàng)建可由Jenkins或其他持續(xù)集成軟件讀取的XML測試報告伟叛,可以使用:

pytest --junitxml=path

運行結束后,在指定路徑path下創(chuàng)建一個XML報告文件
3.1版本新增
可以通過修改配置中junit_suite_name字段的名稱來更改XML報告中root test suite的名稱脐嫂。

[pytest]
junit_suite_name = my_suite

record_property(添加新屬性)
版本2.8新增
版本3.5更改: 在所有報告生成器(reporter)中用戶屬性record_xml_property項已改為record_property统刮,record_xml_property現已棄用侄榴。
可以使用record_property項來在XML報告中增加更多的日志信息:

def test_function(record_property):
    record_property("example_key", 1)
    assert True

在生成的testcase標簽是會添加一個額外的屬性example_key="1"

<testcase classname="test_function" file="test_function.py" line="0" name="test_function" time="0.0009">
  <properties>
    <property name="example_key" value="1" />
  </properties>
</testcase>

或者,你可以將此功能集成在自定義標記裝飾器中:

# conftest.py文件內容

def pytest_collection_modifyitems(session, config, items):
    for item in items:
        for marker in item.iter_markers(name="test_id"):
            test_id = marker.args[0]
            item.user_properties.append(("test_id", test_id))

在你的測試用例中使用:

# test_function.py文件內容
import pytest

@pytest.mark.test_id(1501)
def test_function():
    assert True

這將導致:

<testcase classname="test_function" file="test_function.py" line="0" name="test_function" time="0.0009">
  <properties>
    <property name="test_id" value="1501" />
  </properties>
</testcase>

警告:
record_property是一個實驗性功能网沾,將來可能會發(fā)生變化癞蚕。
另外,這將破壞一些XML結構驗證辉哥,與某些持續(xù)集成軟件一起使用時桦山,可能會導致一些問題。

record_xml_attribute(修改xml節(jié)點屬性)
3.4版本新增
可以使用record_xml_attribute fixture向testcase`標簽中添加其他xml屬性醋旦。也可以用來覆蓋原有屬性值:

def test_function(record_xml_attribute):
    record_xml_attribute("assertions", "REQ-1234")
    record_xml_attribute("classname", "custom_classname")
    print("hello world")
    assert True

record_property不同恒水, 它不會在節(jié)點下添加子元素,而是在生成的testcase標簽內添加一個屬性assertions ="REQ-1234"饲齐,并使用classname = custom_classname覆蓋默認的classname屬性:

<testcase classname="custom_classname" file="test_function.py" line="0" name="test_function" time="0.003" assertions="REQ-1234">
    <system-out>
        hello world
    </system-out>
</testcase>

警告:
record_xml_attribute也是一個實驗性功能钉凌,其界面可能會被更強大,更通用的未來版本所取代捂人。但是御雕,將保留功能本身。

通過使用record_xml_property可以為在使用持續(xù)集成工具解析xml報告時提供幫助滥搭。 但是酸纲,一些解析器對允許的元素和屬性非常嚴格。 許多工具使用xsd模式(如下例所示)來驗證傳入的xml瑟匆。 確保使用解析器允許的屬性名稱闽坡。

以下是Jenkins用于驗證xml報告的結構:

<xs:element name="testcase">
    <xs:complexType>
        <xs:sequence>
            <xs:element ref="skipped" minOccurs="0" maxOccurs="1"/>
            <xs:element ref="error" minOccurs="0" maxOccurs="unbounded"/>
            <xs:element ref="failure" minOccurs="0" maxOccurs="unbounded"/>
            <xs:element ref="system-out" minOccurs="0" maxOccurs="unbounded"/>
            <xs:element ref="system-err" minOccurs="0" maxOccurs="unbounded"/>
        </xs:sequence>
        <xs:attribute name="name" type="xs:string" use="required"/>
        <xs:attribute name="assertions" type="xs:string" use="optional"/>
        <xs:attribute name="time" type="xs:string" use="optional"/>
        <xs:attribute name="classname" type="xs:string" use="optional"/>
        <xs:attribute name="status" type="xs:string" use="optional"/>
    </xs:complexType>
</xs:element>

LogXML: add_global_property
3.0版本新增
如果要在testsuite級別添加屬性節(jié)點,該節(jié)點可能包含與所有測試用例相關的屬性愁溜,則可以使用LogXML.add_global_properties

import pytest


@pytest.fixture(scope="session")
def log_global_env_facts(f):

    if pytest.config.pluginmanager.hasplugin("junitxml"):
        my_junit = getattr(pytest.config, "_xml", None)

    my_junit.add_global_property("ARCH", "PPC")
    my_junit.add_global_property("STORAGE_TYPE", "CEPH")

@pytest.mark.usefixtures(log_global_env_facts.__name__)
def start_and_prepare_env():
    pass

class TestMe(object):
    def test_foo(self):
        assert True

這會在生成的xml中的testsuite節(jié)點下的屬性節(jié)中添加:

<testsuite errors="0" failures="0" name="pytest" skips="0" tests="1" time="0.006">
  <properties>
    <property name="ARCH" value="PPC"/>
    <property name="STORAGE_TYPE" value="CEPH"/>
  </properties>
  <testcase classname="test_me.TestMe" file="test_me.py" line="16" name="test_foo" time="0.000243663787842"/>
</testsuite>

警告:
這仍然是一個實驗性功能疾嗅,其界面也可能會被更強大,更通用的未來版本所取代冕象, 但也將保留該功能代承。

創(chuàng)建結果日志格式文件

3.0版本之后不推薦使用,計劃在4.0版本中刪除交惯。

對于仍然需要類似功能的用戶來說次泽,可以使用提供測試數據流的pytest-tap插件。

如有任何疑慮席爽,可以建立一個問題(open an issue)意荤。

pytest --resultlog=path

執(zhí)行后,在path路徑中會創(chuàng)建一個純文本結果日志文件只锻,這些文件可以用于:例如玖像,在PyPy-test網頁顯示多個修訂版的測試結果。

將測試報告發(fā)送到在線pastebin服務

為每條測試失敗用例建立一個日志URL鏈接:

pytest --pastebin=failed

這會將測試運行信息提交到一個提供粘貼服務的遠程服務器上,并為每條測試失敗用例提供一個URL捐寥。 您可以像平常一樣查看搜集結果笤昨,或者使用-x參數,來只顯示某個特定的測試失敗結果握恳。

為整個測試執(zhí)行日志建立一個URL鏈接:

pytest --pastebin=all

目前只實現了粘貼到http://bpaste.net網站的服務瞒窒。

禁用插件

可以通過-p選項與前綴no:一起使用,來在運行時禁用加載特定插件乡洼。

例如:要禁用加載從文本文件執(zhí)行doctest測試的doctest插件崇裁,可以通過以下方式運行pytest:

pytest -p no:doctest

在Python代碼調用pytest

版本2.0新增
你可以在Python代碼中直接調用pytest:

pytest.main()

這就和你從命令行調用“pytest”一樣。但它不會引發(fā)SystemExit束昵,而是返回exitcode拔稳。 你可以傳入選項和參數。

pytest.main(['-x', 'mytestdir'])

您可以為pytest.main指定其他插件:

# myinvoke.py文件內容
import pytest
class MyPlugin(object):
    def pytest_sessionfinish(self):
        print("*** test run reporting finishing")

pytest.main(["-qq"], plugins=[MyPlugin()])

運行它將顯示已添加MyPlugin并調用其中的hook方法:

$ python myinvoke.py
.                                                                    [100%]*** test run reporting finishing 

注意:
調用pytest.main()將會導入所有測試用例及其導入的其他模塊锹雏。由于python導入系統(tǒng)的緩存機制巴比,從同一進程后續(xù)調用pytest.main()不會反映調用之間對這些文件的更改。 因此礁遵,不建議從同一進程(例如轻绞,為了新運行測試)多次調用pytest.main()

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末榛丢,一起剝皮案震驚了整個濱河市铲球,隨后出現的幾起案子,更是在濱河造成了極大的恐慌晰赞,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,482評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件选侨,死亡現場離奇詭異掖鱼,居然都是意外死亡,警方通過查閱死者的電腦和手機援制,發(fā)現死者居然都...
    沈念sama閱讀 88,377評論 2 382
  • 文/潘曉璐 我一進店門戏挡,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人晨仑,你說我怎么就攤上這事褐墅。” “怎么了洪己?”我有些...
    開封第一講書人閱讀 152,762評論 0 342
  • 文/不壞的土叔 我叫張陵妥凳,是天一觀的道長。 經常有香客問我答捕,道長逝钥,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,273評論 1 279
  • 正文 為了忘掉前任拱镐,我火速辦了婚禮艘款,結果婚禮上持际,老公的妹妹穿的比我還像新娘。我一直安慰自己哗咆,他們只是感情好蜘欲,可當我...
    茶點故事閱讀 64,289評論 5 373
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著晌柬,像睡著了一般芒填。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上空繁,一...
    開封第一講書人閱讀 49,046評論 1 285
  • 那天殿衰,我揣著相機與錄音,去河邊找鬼盛泡。 笑死闷祥,一個胖子當著我的面吹牛,可吹牛的內容都是我干的傲诵。 我是一名探鬼主播凯砍,決...
    沈念sama閱讀 38,351評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼拴竹!你這毒婦竟也來了悟衩?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 36,988評論 0 259
  • 序言:老撾萬榮一對情侶失蹤栓拜,失蹤者是張志新(化名)和其女友劉穎座泳,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體幕与,經...
    沈念sama閱讀 43,476評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡挑势,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 35,948評論 2 324
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現自己被綠了啦鸣。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片潮饱。...
    茶點故事閱讀 38,064評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖诫给,靈堂內的尸體忽然破棺而出香拉,到底是詐尸還是另有隱情,我是刑警寧澤中狂,帶...
    沈念sama閱讀 33,712評論 4 323
  • 正文 年R本政府宣布凫碌,位于F島的核電站,受9級特大地震影響吃型,放射性物質發(fā)生泄漏证鸥。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,261評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望枉层。 院中可真熱鬧泉褐,春花似錦、人聲如沸鸟蜡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽揉忘。三九已至跳座,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間泣矛,已是汗流浹背疲眷。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留您朽,地道東北人狂丝。 一個月前我還...
    沈念sama閱讀 45,511評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像哗总,于是被迫代替她去往敵國和親几颜。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,802評論 2 345

推薦閱讀更多精彩內容