Pytest官方教程-02-使用和調(diào)用方法

使用和調(diào)用方法

使用python -m pytest調(diào)用pytest

2.0版本新增

你可以在命令行中通過Python編譯器來調(diào)用pytest執(zhí)行測試


python -m pytest [...]

通過python調(diào)用會將當(dāng)前目錄也添加到sys.path中,除此之外,這幾乎等同于命令行直接調(diào)用pytest [...]炫乓。


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

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


退出code 0: 收集并成功通過所有測試用例

退出code 1: 收集并運(yùn)行了測試吐绵,部分測試用例執(zhí)行失敗

退出code 2: 測試執(zhí)行被用戶中斷

退出code 3: 執(zhí)行測試中發(fā)生內(nèi)部錯誤

退出code 4: pytest命令行使用錯誤

退出code 5: 沒有收集到測試用例獲取版本路徑、命令行選項及環(huán)境變量相關(guān)幫助

pytest --version? # 顯示pytest導(dǎo)入位置

pytest --fixtures? # 顯示可用的內(nèi)置方法參數(shù)

pytest -h | --help # 顯示命令行及配置文件選項幫助信息

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

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


pytest -x? ? ? ? ? ? # 第1次失敗后停止

pytest --maxfail=2? ? # 2次失敗后停止

指定及選擇測試用例

Pytest支持多種從命令行運(yùn)行和選擇測試用例的方法孟害。

運(yùn)行模塊內(nèi)所有用例


pytest test_mod.py

運(yùn)行目錄內(nèi)所有用例


pytest testing/

按關(guān)鍵字表達(dá)式運(yùn)行測試pytest -k "MyClass and not method"

這將運(yùn)行包含與給定字符串表達(dá)式匹配的名稱的測試用例,其中可以包括文件名、類名和函數(shù)名作為變量及Python運(yùn)算符操作虑乖。上面的示例將運(yùn)行TestMyClass.test_something但不運(yùn)行TestMyClass.test_method_simple。

按節(jié)點id運(yùn)行測試

每次執(zhí)行收集到的測試集合都會被分配一個唯一的nodeid晾虑,其中包含模塊文件名疹味,后跟說明符,如類名帜篇、函數(shù)名及參數(shù)糙捺,由:: 字符分隔。

執(zhí)行模塊中某條指定的測試用例:


pytest test_mod.py::test_func

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


pytest test_mod.py::TestClass::test_method

通過標(biāo)記表達(dá)式運(yùn)行測試


pytest -m slow

這將會執(zhí)行所有帶@pytest.mark.slow裝飾器的用例笙隙。

有關(guān)更多信息洪灯,請參閱標(biāo)記

從包中運(yùn)行測試pytest --pyargs pkg.testing

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


修改Python追溯(traceback)信息

修改回追溯信息示例:


pytest --showlocals # 在追溯信息中顯示局部變量

pytest -l? ? ? ? ? # 顯示局部變量 (簡寫)


pytest --tb=auto? ? # (默認(rèn)) 第1和最后1條使用詳細(xì)追溯信息竟痰,其他使用簡短追溯信息


pytest --tb=long? ? # 詳盡签钩,信息豐富的追溯信息格式

pytest --tb=short? # 簡短的追溯信息格式

pytest --tb=line? ? # 每個失敗信息一行

pytest --tb=native? # Python標(biāo)準(zhǔn)庫格式

pytest --tb=no? ? ? # 不使用追溯信息

詳盡的摘要報告

2.9版本新增

-r標(biāo)志可用于在測試會話結(jié)束時顯示測試結(jié)果摘要掏呼,從而可以在大型測試套件中輕松獲得所有失敗、跳過边臼、標(biāo)記失敗(xfails)等測試結(jié)果的清晰圖像哄尔。

例如:


$ 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)以外所有的結(jié)果”柠并。以下是可以使用的可用字符的完整列表:

-f - 失敗的用例

-E - 出錯的用例

-s - 跳過的用例

-x - 標(biāo)記失敗的用例

-X - 標(biāo)記成功的用例

-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í)行失敗時進(jìn)入PDB (Python調(diào)試器)

Python附帶一個名為PDB的內(nèi)置Python調(diào)試器鸣戴。 pytest允許通過命令行選項進(jìn)入PDB提示符:


pytest --pdb

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


pytest -x --pdb? # 在第一次用例失敗時進(jìn)入PDB

pytest --pdb --maxfail=3? # 在前3次失敗是進(jìn)入PDB

注意窄锅,在任何失敗時,異常信息都存儲在`sys.last_value1缰雇,1sys.last_type1和1sys.last_traceback1中入偷。在交互模式中,這允許用戶使用任何調(diào)試工具進(jìn)行事后調(diào)試械哟。也可以手動訪問異常信息疏之,例如:>>> import sys

>>> sys.last_traceback.tb_lineno

42

>>> sys.last_value

AssertionError('assert result == "ok"',)

測試開始時進(jìn)入PDB(Python調(diào)試器)

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


pytest --trace

這將在每次測試開始時調(diào)用Python調(diào)試器。


設(shè)置斷點

要在代碼中設(shè)置斷點暇咆,需要在代碼中使用Python原生import pdb; pdb.set_trace()進(jìn)行調(diào)用锋爪,pytest會自動禁用顯示并捕獲該用例輸出結(jié)果:


其他測試中的輸出捕獲不受影響。

任何先前的測試輸出已經(jīng)被捕獲并將被處理爸业。

在同一測試中生成的任何后續(xù)輸出都不會被捕獲其骄,而是直接發(fā)送到sys.stdout。注意:即使是退出交互式PDB跟蹤會話并繼續(xù)常規(guī)測試后發(fā)生的測試輸出扯旷,這也適用拯爽。

使用內(nèi)置斷點方法要創(chuàng)建可由Jenkins或其他持續(xù)集成軟件讀取的XML測試報告,可以使用:


pytest --junitxml=path

運(yùn)行結(jié)束后钧忽,在指定路徑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現(xiàn)已棄用惰瓜。

可以使用record_property項來在XML報告中增加更多的日志信息:


def test_function(record_property):

? ? record_property("example_key", 1)

? ? assert True

在生成的testcase標(biāo)簽是會添加一個額外的屬性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>

或者,你可以將此功能集成在自定義標(biāo)記裝飾器中:Python 3.7引入了內(nèi)置breakpoint()函數(shù)汉矿。 Pytest支持以下幾種使用breakpoint()的方式:


當(dāng)PYTHONBREAKPOINT設(shè)置為默認(rèn)值崎坊,調(diào)用breakpoint()時,pytest將使用其內(nèi)部PDB跟蹤交互界面(PDB trace UI)而不是Python自帶的Pdb洲拇。

測試完成后奈揍,默認(rèn)會重置為Python自帶的PDB跟蹤交互界面曲尸。

在pytest后使用--pdb參數(shù),在失敗的測試/未處理異常中男翰,pytest內(nèi)部PDB跟蹤交互界面與breakpoint()同時使用另患。

--pdbcls參數(shù)可指定要使用的調(diào)試器類。

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

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


pytest --durations=10

除非在命令行上傳遞-vv蛾绎,默認(rèn)情況下昆箕,否則pytest不會顯示<0.01s的測試時間。


創(chuàng)建JUnitXML格式文件# conftest.py文件內(nèi)容


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文件內(nèi)容

import pytest


@pytest.mark.test_id(1501)

def test_function():

? ? assert True

這將導(dǎo)致:


<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結(jié)構(gòu)驗證顽爹,與某些持續(xù)集成軟件一起使用時纤泵,可能會導(dǎo)致一些問題。


record_xml_attribute(修改xml節(jié)點屬性)

3.4版本新增

可以使用record_xml_attribute fixture向testcase`標(biāo)簽中添加其他xml屬性镜粤。也可以用來覆蓋原有屬性值:3.4版本新增

可以使用record_xml_attribute fixture向testcase`標(biāo)簽中添加其他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標(biāo)簽內(nèi)添加一個屬性assertions ="REQ-1234"公荧,并使用classname = custom_classname覆蓋默認(rèn)的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也是一個實驗性功能,其界面可能會被更強(qiáng)大黄虱,更通用的未來版本所取代稚矿。但是,將保留功能本身捻浦。


通過使用record_xml_property可以為在使用持續(xù)集成工具解析xml報告時提供幫助晤揣。 但是,一些解析器對允許的元素和屬性非常嚴(yán)格朱灿。 許多工具使用xsd模式(如下例所示)來驗證傳入的xml昧识。 確保使用解析器允許的屬性名稱。以下是Jenkins用于驗證xml報告的結(jié)構(gòu):


<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é)點可能包含與所有測試用例相關(guān)的屬性跪楞,則可以使用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>警告:

這仍然是一個實驗性功能,其界面也可能會被更強(qiáng)大侣灶,更通用的未來版本所取代甸祭, 但也將保留該功能。


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

3.0版本之后不推薦使用褥影,計劃在4.0版本中刪除池户。


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


如有任何疑慮校焦,可以建立一個問題(open an issue)赊抖。


pytest --resultlog=path

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


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

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


pytest --pastebin=failed

這會將測試運(yùn)行信息提交到一個提供粘貼服務(wù)的遠(yuǎn)程服務(wù)器上耸成,并為每條測試失敗用例提供一個URL报亩。 您可以像平常一樣查看搜集結(jié)果,或者使用-x參數(shù)墓猎,來只顯示某個特定的測試失敗結(jié)果捆昏。


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

目前只實現(xiàn)了粘貼到http://bpaste.net網(wǎng)站的服務(wù)。


禁用插件

可以通過-p選項與前綴no:一起使用毙沾,來在運(yùn)行時禁用加載特定插件骗卜。


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


pytest -p no:doctest

在Python代碼調(diào)用pytest

版本2.0新增

你可以在Python代碼中直接調(diào)用pytest:


pytest.main()

這就和你從命令行調(diào)用“pytest”一樣左胞。但它不會引發(fā)SystemExit寇仓,而是返回exitcode。 你可以傳入選項和參數(shù)烤宙。


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

您可以為pytest.main指定其他插件:# myinvoke.py文件內(nèi)容

import pytest

class MyPlugin(object):

? ? def pytest_sessionfinish(self):

? ? ? ? print("*** test run reporting finishing")


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

運(yùn)行它將顯示已添加MyPlugin并調(diào)用其中的hook方法:


$ python myinvoke.py

.

注意:

調(diào)用pytest.main()將會導(dǎo)入所有測試用例及其導(dǎo)入的其他模塊遍烦。由于python導(dǎo)入系統(tǒng)的緩存機(jī)制,從同一進(jìn)程后續(xù)調(diào)用pytest.main()不會反映調(diào)用之間對這些文件的更改躺枕。 因此服猪,不建議從同一進(jìn)程(例如,為了新運(yùn)行測試)多次調(diào)用pytest.main()拐云。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末罢猪,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子叉瘩,更是在濱河造成了極大的恐慌膳帕,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,482評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件薇缅,死亡現(xiàn)場離奇詭異危彩,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)泳桦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評論 2 382
  • 文/潘曉璐 我一進(jìn)店門汤徽,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人灸撰,你說我怎么就攤上這事谒府∑岣幔” “怎么了?”我有些...
    開封第一講書人閱讀 152,762評論 0 342
  • 文/不壞的土叔 我叫張陵狱掂,是天一觀的道長。 經(jīng)常有香客問我亲轨,道長趋惨,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,273評論 1 279
  • 正文 為了忘掉前任惦蚊,我火速辦了婚禮器虾,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘蹦锋。我一直安慰自己兆沙,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,289評論 5 373
  • 文/花漫 我一把揭開白布莉掂。 她就那樣靜靜地躺著葛圃,像睡著了一般。 火紅的嫁衣襯著肌膚如雪憎妙。 梳的紋絲不亂的頭發(fā)上库正,一...
    開封第一講書人閱讀 49,046評論 1 285
  • 那天,我揣著相機(jī)與錄音厘唾,去河邊找鬼褥符。 笑死,一個胖子當(dāng)著我的面吹牛抚垃,可吹牛的內(nèi)容都是我干的喷楣。 我是一名探鬼主播,決...
    沈念sama閱讀 38,351評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼鹤树,長吁一口氣:“原來是場噩夢啊……” “哼铣焊!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起魂迄,我...
    開封第一講書人閱讀 36,988評論 0 259
  • 序言:老撾萬榮一對情侶失蹤粗截,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后捣炬,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體熊昌,經(jīng)...
    沈念sama閱讀 43,476評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,948評論 2 324
  • 正文 我和宋清朗相戀三年湿酸,在試婚紗的時候發(fā)現(xiàn)自己被綠了婿屹。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,064評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡推溃,死狀恐怖昂利,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤蜂奸,帶...
    沈念sama閱讀 33,712評論 4 323
  • 正文 年R本政府宣布犁苏,位于F島的核電站,受9級特大地震影響扩所,放射性物質(zhì)發(fā)生泄漏围详。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,261評論 3 307
  • 文/蒙蒙 一祖屏、第九天 我趴在偏房一處隱蔽的房頂上張望助赞。 院中可真熱鬧,春花似錦袁勺、人聲如沸雹食。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽群叶。三九已至,卻和暖如春咐汞,著一層夾襖步出監(jiān)牢的瞬間盖呼,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評論 1 262
  • 我被黑心中介騙來泰國打工化撕, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留几晤,地道東北人。 一個月前我還...
    沈念sama閱讀 45,511評論 2 354
  • 正文 我出身青樓植阴,卻偏偏與公主長得像蟹瘾,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子掠手,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,802評論 2 345

推薦閱讀更多精彩內(nèi)容