使用和調(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()拐云。