2、pytest中文文檔--使用和調用
- 2019 年 10 月 3 日
- 筆記
目錄
- 1. 通過
python -m pytest調用pytest - 2.
pytest執行結束時返回的狀態碼 - 3. 獲取幫助資訊
- 4. 最多允許失敗的測試用例數
- 5. 執行指定的測試用例
- 6. 修改回溯資訊的輸出模式
- 7. 總結報告
- 8. 失敗時載入PDB(Python Debugger)環境
- 9. 開始執行時就載入
PDB環境 - 10. 設置斷點
- 11. 使用內置的中斷函數
- 12. 分析測試執行時間
- 13. 錯誤句柄
- 14. 創建
JUnitXML格式的測試報告 - 15. 創建純文本格式的測試報告
- 16. 為測試報告提供
URL鏈接 --pastebin服務 - 17. 儘早的載入插件
- 18. 去使能插件
- 19. 在
python程式碼中調用pytest
1. 通過python -m pytest調用pytest
你可以通過python的解釋器來執行測試:
python -m pytest [...] 但是,這和直接執行pytest [...]命令的效果幾乎是一模一樣的;
2. pytest執行結束時返回的狀態碼
pytest命令執行結束,可能會返回以下六種狀態碼:
- 0:(OK)所有收集到的用例測試通過
- 1:(TESTS_FAILED)有用例測試失敗
- 2:(INTERRUPTED)用戶打斷測試執行
- 3:(INTERNAL_ERROR)測試執行的過程中,發生內部錯誤
- 4:(USAGE_ERROR)
pytest命令使用錯誤 - 5:(NO_TESTS_COLLECTED)沒有收集到測試用例
它們在枚舉類 _pytest.main.ExitCode 中聲明。並且,其作為公開API的一部分,能夠直接引入和訪問:
from pytest import ExitCode 3. 獲取幫助資訊
pytest --version # 查看版本號和pytest的引入路徑 pytest -h # 查看幫助資訊 4. 最多允許失敗的測試用例數
當達到最大上限時,退出執行;如未配置,則沒有上限:
pytest -x # 遇到第一個失敗時,退出執行 pytest --maxfail==2 # 遇到第二個失敗時,退出執行 5. 執行指定的測試用例
pytest支援多種方式來執行特定的測試用例:
5.1. 執行指定模組中的測試用例
pytest test_mod.py 5.2. 執行指定目錄下所有的測試用例
pytest testing/ 5.3. 執行文件名、類名或者函數名中包含特定關鍵字的測試用例
執行當前目錄下,名字包含_class但不包含two的測試用例:
pytest -k "_class and not two" . 注意:python的關鍵字不可以應用在
-k選項中,例如,class、def等。
5.4. 執行指定nodeid的測試用例
pytest為每一個收集到的測試用例指定一個唯一的nodeid。其由模組名加說明符構成,中間以::間隔。
其中,說明符可以是類名、函數名以及由parametrize標記賦予的參數:
# src/chapter-2/test_nodeid.py import pytest def test_one(): print('test_one') assert 1 class TestNodeId: def test_one(self): print('TestNodeId::test_one') assert 1 @pytest.mark.parametrize('x,y', [(1, 1), (3, 4)]) def test_two(self, x, y): print(f'TestNodeId::test_two::{x} == {y}') assert x == y 在上述示例中,我們創建了三個測試用例,分別對應不同的說明符:
指定函數名執行
$ pipenv run pytest -q -s src/chapter-2/test_nodeid.py::test_one test_one . 1 passed in 0.01s指定類名+函數名執行
$ pipenv run pytest -q -s src/chapter-2/test_nodeid.py::TestNodeId::test_one TestNodeId::test_one . 1 passed in 0.01s指定由
parametrize標記賦予的參數執行$ pipenv run pytest -q -s src/chapter-2/test_nodeid.py::TestNodeId::test_two[1-1] TestNodeId::test_two::1 == 1 . 1 passed in 0.01s這裡對參數
x、y賦值的形式是[1-1],中間以-間隔;單個或多個參數的賦值形式以此類比;並且,只能為
[1-1]或者[3-4],其它的會報錯;
5.5. 執行指定標記的用例
pytest -m slow 5.6. 執行指定包中的測試用例
pytest --pyargs pkg.testing pytest會引入pkg.testing包,並在它的系統目錄下搜尋測試用例並執行;
6. 修改回溯資訊的輸出模式
pytest回溯資訊的輸出一共有六種模式:auto/long/short/line/native/no,用--tb選項指定:
pytest -l, --showlocals # 列印本地變數 pytest --tb=auto # 默認模式 pytest --tb=long # 儘可能詳細的輸出 pytest --tb=short # 更簡短的輸出 pytest --tb=line # 每個失敗資訊總結在一行中 pytest --tb=native # python的標準輸出 pytest --tb=no # 不列印失敗資訊 --full-trace是一種比--tb=long更詳細的輸出模式。它甚至能觀察到用戶打斷執行(Ctrl+C)時的回溯資訊,而上述六種模式默認是不輸出此類資訊的。
7. 總結報告
-r選項可以在執行結束後,列印一個簡短的總結報告。在執行的測試用例很多時,可以讓你對結果有個清晰的了解:
# src/chapter-2/test_report.py import pytest @pytest.fixture def error_fixture(): assert 0 def test_ok(): print("ok") def test_fail(): assert 0 def test_error(error_fixture): pass def test_skip(): pytest.skip("skipping this test") def test_xfail(): pytest.xfail("xfailing this test") @pytest.mark.xfail(reason="always xfail") def test_xpass(): pass $ pipenv run pytest -q -rA src/chapter-2/test_report.py .FEsxX [100%] ================================ ERRORS ================================= _____________________ ERROR at setup of test_error ______________________ @pytest.fixture def error_fixture(): > assert 0 E assert 0 src/chapter-2/test_report.py:27: AssertionError =============================== FAILURES ================================ _______________________________ test_fail _______________________________ def test_fail(): > assert 0 E assert 0 src/chapter-2/test_report.py:35: AssertionError ================================ PASSES ================================= ________________________________ test_ok ________________________________ ------------------------- Captured stdout call -------------------------- ok ======================== short test summary info ======================== PASSED src/chapter-2/test_report.py::test_ok SKIPPED [1] /Users/yaomeng/Private/Projects/pytest-chinese-doc/src/chapter-2/test_report.py:44: skipping this test XFAIL src/chapter-2/test_report.py::test_xfail reason: xfailing this test XPASS src/chapter-2/test_report.py::test_xpass always xfail ERROR src/chapter-2/test_report.py::test_error - assert 0 FAILED src/chapter-2/test_report.py::test_fail - assert 0 1 failed, 1 passed, 1 skipped, 1 xfailed, 1 xpassed, 1 error in 0.08s -r選項後面要緊接這一個參數,用於過濾顯示測試用例的結果。
以下是所有有效的字元參數:
- f:失敗的
- E:出錯的
- s:跳過執行的
- x:跳過執行,並標記為xfailed的
- X:跳過執行,並標記為xpassed的
- p:測試通過的
- P:測試通過,並且有輸出資訊的;即用例中有
print等 - a:除了測試通過的,其他所有的;即除了
p和P的 - A:所有的
上述字元參數可以疊加使用,例如:我們期望過濾出失敗的和未執行的:
pytest -rfs 8. 失敗時載入PDB(Python Debugger)環境
PDB是python內建的診斷器,pytest允許通過以下命令在執行失敗時進入這個診斷器模式:
pytest --pdb pytest會在測試用例失敗(或者Ctrl+C)時,調用這個診斷器:
# src/chapter-2/test_pdb.py def test_fail(): x = 1 assert x == 0 $ pipenv run pytest -q --pdb src/chapter-2/test_pdb.py F >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> traceback >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> def test_fail(): x = 1 > assert x == 0 E assert 1 == 0 src/chapter-2/test_pdb.py:25: AssertionError >>>>>>>>>>>>>>>>>>>>>>>>>>>>> entering PDB >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>> PDB post_mortem (IO-capturing turned off) >>>>>>>>>>>>>>> > /Users/yaomeng/Private/Projects/pytest-chinese-doc/src/chapter-2/test_pdb.py(25)test_fail() -> assert x == 0 (Pdb) (Pdb) x 1 (Pdb) (Pdb) import sys (Pdb) sys.last_value AssertionError('assert 1 == 0') (Pdb) sys.last_type <class 'AssertionError'> (Pdb) sys.last_traceback <traceback object at 0x1077ec808> 你還可以訪問測試用例的本地變數x;
失敗的資訊存儲在sys.last_value, sys.last_type, sys.last_traceback變數中,你可以在交互環境中訪問它們;
使用exit命令,退出PDB環境;
9. 開始執行時就載入PDB環境
通過以下命令,pytest允許你在每個測試用例開始執行時,就載入PDB環境:
pytest --trace 10. 設置斷點
在測試用例程式碼中添加import pdb;pdb.set_trace(),當其被調用時,pytest會停止這條用例的輸出:
- 其他用例不受影響;
- 通過
continue命令,退出PDB環境,並繼續執行用例;
11. 使用內置的中斷函數
python 3.7介紹了一個內置breakpoint()函數。pytest可以在以下場景中支援使用:
- 當
breakpoint()被調用,並且PYTHONBREAKPOINT為None時,pytest會使用內部自定義的PDB代替系統的; - 測試執行結束時,自動切回系統自帶的
PDB; - 當加上
--pdb選項時,breakpoint()和測試發生錯誤時,都會調用內部自定義的PDB; --pdbcls選項允許指定一個用戶自定義的PDB類;
12. 分析測試執行時間
獲取執行最慢的10個測試用例:
pytest --durations=10 默認情況下,pytest不會顯示執行時間<0.01s的測試用例,可以使用-vv選項查看它們;
13. 錯誤句柄
5.0版本新增特性
在測試執行中發生段錯誤或者超時的情況下,faulthandler標準模組可以轉儲python的回溯資訊;
它在pytest的執行中默認使能,使用-p no:faulthandler選項可以關閉它;
同樣,faulthandler_timeout=X配置項,可用於當測試用例的完成時間超過X秒時,轉儲所有執行緒的python回溯資訊:
# src/chapter-2/pytest.ini [pytest] faulthandler_timeout=5 配置測試執行的超時時間是5秒;
# test_fault_handler.py import time def test_faulthandler(): time.sleep(7) assert 1 測試用例中添加等待7秒的操作;
默認使能
faulthandler的情況:$ pipenv run pytest -q src/chapter-2/test_faulthandler.py Timeout (0:00:05)! Thread 0x000000010ff275c0 (most recent call first): File "/Users/yaomeng/Private/Projects/pytest-chinese-doc/src/chapter-2/test_faulthandler.py", line 26 in test_faulthandler File "/Users/yaomeng/.local/share/virtualenvs/pytest-chinese-doc-EK3zIUmM/lib/python3.7/site-packages/_pytest/python.py", line 170 in pytest_pyfunc_call File "/Users/yaomeng/.local/share/virtualenvs/pytest-chinese-doc-EK3zIUmM/lib/python3.7/site-packages/pluggy/callers.py", line 187 in _multicall File "/Users/yaomeng/.local/share/virtualenvs/pytest-chinese-doc-EK3zIUmM/lib/python3.7/site-packages/pluggy/manager.py", line 86 in <lambda> File "/Users/yaomeng/.local/share/virtualenvs/pytest-chinese-doc-EK3zIUmM/lib/python3.7/site-packages/pluggy/manager.py", line 92 in _hookexec File "/Users/yaomeng/.local/share/virtualenvs/pytest-chinese-doc-EK3zIUmM/lib/python3.7/site-packages/pluggy/hooks.py", line 286 in __call__ File "/Users/yaomeng/.local/share/virtualenvs/pytest-chinese-doc-EK3zIUmM/lib/python3.7/site-packages/_pytest/python.py", line 1423 in runtest File "/Users/yaomeng/.local/share/virtualenvs/pytest-chinese-doc-EK3zIUmM/lib/python3.7/site-packages/_pytest/runner.py", line 117 in pytest_runtest_call File "/Users/yaomeng/.local/share/virtualenvs/pytest-chinese-doc-EK3zIUmM/lib/python3.7/site-packages/pluggy/callers.py", line 187 in _multicall File "/Users/yaomeng/.local/share/virtualenvs/pytest-chinese-doc-EK3zIUmM/lib/python3.7/site-packages/pluggy/manager.py", line 86 in <lambda> File "/Users/yaomeng/.local/share/virtualenvs/pytest-chinese-doc-EK3zIUmM/lib/python3.7/site-packages/pluggy/manager.py", line 92 in _hookexec File "/Users/yaomeng/.local/share/virtualenvs/pytest-chinese-doc-EK3zIUmM/lib/python3.7/site-packages/pluggy/hooks.py", line 286 in __call__ File "/Users/yaomeng/.local/share/virtualenvs/pytest-chinese-doc-EK3zIUmM/lib/python3.7/site-packages/_pytest/runner.py", line 192 in <lambda> File "/Users/yaomeng/.local/share/virtualenvs/pytest-chinese-doc-EK3zIUmM/lib/python3.7/site-packages/_pytest/runner.py", line 220 in from_call File "/Users/yaomeng/.local/share/virtualenvs/pytest-chinese-doc-EK3zIUmM/lib/python3.7/site-packages/_pytest/runner.py", line 192 in call_runtest_hook File "/Users/yaomeng/.local/share/virtualenvs/pytest-chinese-doc-EK3zIUmM/lib/python3.7/site-packages/_pytest/runner.py", line 167 in call_and_report File "/Users/yaomeng/.local/share/virtualenvs/pytest-chinese-doc-EK3zIUmM/lib/python3.7/site-packages/_pytest/runner.py", line 87 in runtestprotocol File "/Users/yaomeng/.local/share/virtualenvs/pytest-chinese-doc-EK3zIUmM/lib/python3.7/site-packages/_pytest/runner.py", line 72 in pytest_runtest_protocol File "/Users/yaomeng/.local/share/virtualenvs/pytest-chinese-doc-EK3zIUmM/lib/python3.7/site-packages/pluggy/callers.py", line 187 in _multicall File "/Users/yaomeng/.local/share/virtualenvs/pytest-chinese-doc-EK3zIUmM/lib/python3.7/site-packages/pluggy/manager.py", line 86 in <lambda> File "/Users/yaomeng/.local/share/virtualenvs/pytest-chinese-doc-EK3zIUmM/lib/python3.7/site-packages/pluggy/manager.py", line 92 in _hookexec File "/Users/yaomeng/.local/share/virtualenvs/pytest-chinese-doc-EK3zIUmM/lib/python3.7/site-packages/pluggy/hooks.py", line 286 in __call__ File "/Users/yaomeng/.local/share/virtualenvs/pytest-chinese-doc-EK3zIUmM/lib/python3.7/site-packages/_pytest/main.py", line 256 in pytest_runtestloop File "/Users/yaomeng/.local/share/virtualenvs/pytest-chinese-doc-EK3zIUmM/lib/python3.7/site-packages/pluggy/callers.py", line 187 in _multicall File "/Users/yaomeng/.local/share/virtualenvs/pytest-chinese-doc-EK3zIUmM/lib/python3.7/site-packages/pluggy/manager.py", line 86 in <lambda> File "/Users/yaomeng/.local/share/virtualenvs/pytest-chinese-doc-EK3zIUmM/lib/python3.7/site-packages/pluggy/manager.py", line 92 in _hookexec File "/Users/yaomeng/.local/share/virtualenvs/pytest-chinese-doc-EK3zIUmM/lib/python3.7/site-packages/pluggy/hooks.py", line 286 in __call__ File "/Users/yaomeng/.local/share/virtualenvs/pytest-chinese-doc-EK3zIUmM/lib/python3.7/site-packages/_pytest/main.py", line 235 in _main File "/Users/yaomeng/.local/share/virtualenvs/pytest-chinese-doc-EK3zIUmM/lib/python3.7/site-packages/_pytest/main.py", line 191 in wrap_session File "/Users/yaomeng/.local/share/virtualenvs/pytest-chinese-doc-EK3zIUmM/lib/python3.7/site-packages/_pytest/main.py", line 228 in pytest_cmdline_main File "/Users/yaomeng/.local/share/virtualenvs/pytest-chinese-doc-EK3zIUmM/lib/python3.7/site-packages/pluggy/callers.py", line 187 in _multicall File "/Users/yaomeng/.local/share/virtualenvs/pytest-chinese-doc-EK3zIUmM/lib/python3.7/site-packages/pluggy/manager.py", line 86 in <lambda> File "/Users/yaomeng/.local/share/virtualenvs/pytest-chinese-doc-EK3zIUmM/lib/python3.7/site-packages/pluggy/manager.py", line 92 in _hookexec File "/Users/yaomeng/.local/share/virtualenvs/pytest-chinese-doc-EK3zIUmM/lib/python3.7/site-packages/pluggy/hooks.py", line 286 in __call__ File "/Users/yaomeng/.local/share/virtualenvs/pytest-chinese-doc-EK3zIUmM/lib/python3.7/site-packages/_pytest/config/__init__.py", line 77 in main File "/Users/yaomeng/.local/share/virtualenvs/pytest-chinese-doc-EK3zIUmM/bin/pytest", line 10 in <module> . [100%] 1 passed in 7.02s在執行剛超過5秒的時候會列印出回溯資訊。但不會中斷測試的執行;
去使能
faulthandler的情況:$ pipenv run pytest -q -p no:faulthandler src/chapter-2/test_faulthandler.py . [100%] 1 passed in 7.02s超時並不會觸發回溯資訊的列印;
注意:
這個功能是從pytest-faulthandler插件合併而來的,但是有兩點不同:
- 去使能時,使用
-p no:faulthandler代替原來的--no-faulthandler;- 使用
faulthandler_timeout配置項代替--faulthandler-timeout命令行選項來配置超時時間。當然,你也可以使用-o faulthandler_timeout=X在命令行配置;
14. 創建JUnitXML格式的測試報告
使用如下命令,可以在指定的path中創建一個能被Jenkins或者其他CI工具讀取的XML格式的測試報告:
pytest --junitxml=path 你可以在項目的pytest.ini文件中,通過設置junit_suite_name的值,自定義XML文件中testsuite根節點的name資訊:
junit_suite_name是4.0版本新增的配置項;
# src/chapter-2/pytest.ini [pytest] junit_suite_name = pytest_chinese_doc 我們來執行一個測試用例test_nodeid.py::test_one看看效果:
pipenv run pytest -q --junitxml=src/chapter-2/report/test_one.xml src/chapter-2/test_nodeid.py::test_one 生成的XML測試報告:
<?xml version="1.0" encoding="utf-8"?> <testsuites> <testsuite errors="0" failures="0" hostname="NJ-LUYAO-T460" name="pytest_chinese_doc" skipped="0" tests="1" time="0.030" timestamp="2019-09-27T14:33:32.459788"> <testcase classname="test_nodeid" file="test_nodeid.py" line="24" name="test_one" time="0.002"> <system-out>test_one </system-out> </testcase> </testsuite> </testsuites> 我們可以看到,<testsuite>節點的name屬性的值,變為我們所期望的pytest_chinese_doc,而不是默認的pytest;
JUnit XML規定time屬性應該表明測試用例執行的全部耗時,包含setup和teardown中的操作,這也是pytest的默認行為;
如果你只想記錄測試用例執行的時間,只需要做如下配置:
# src/chapter-2/pytest.ini junit_duration_report = call 14.1. 在報告中為測試用例附加額外的子節點資訊
我們有兩種方式實現這個功能:
使用
record_property fixture:為
test_record_property用例添加一個額外的test_id:# src/chapter-2/test_xml_report.py def test_record_property(record_property): record_property("test_id", 10010) assert 1在報告中的表現為
<property name="test_id" value="10010" />:<!-- src/chapter-2/report/test_record_property.xml --> <?xml version="1.0" encoding="utf-8"?> <testsuites> <testsuite errors="0" failures="0" hostname="NJ-LUYAO-T460" name="pytest_chinese_doc" skipped="0" tests="1" time="0.024" timestamp="2019-09-27T15:02:41.277369"> <testcase classname="test_xml_report" file="test_xml_report.py" line="22" name="test_record_property" time="0.002"> <properties> <property name="test_id" value="10010" /> </properties> </testcase> </testsuite> </testsuites>解析一個自定義的標記
@pytest.mark.test_id():首先,修改
pytest_collection_modifyitems鉤子方法,添加對test_id標記的支援:# src/chapter-2/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))然後,修改測試用例:
# src/chapter-2/test_xml_report.py import pytest @pytest.mark.test_id(10010) def test_record_property1(): assert 1在報告中的也表現為
<property name="test_id" value="10010" />:<!-- src/chapter-2/report/test_record_property1.xml --> <?xml version="1.0" encoding="utf-8"?> <testsuites> <testsuite errors="0" failures="0" hostname="NJ-LUYAO-T460" name="pytest_chinese_doc" skipped="0" tests="1" time="0.029" timestamp="2019-09-27T15:16:05.309308"> <testcase classname="test_xml_report" file="test_xml_report.py" line="29" name="test_record_property1" time="0.001"> <properties> <property name="test_id" value="10010" /> </properties> </testcase> </testsuite> </testsuites>注意:
這是我們會接收到一個告警:
PytestUnknownMarkWarning: Unknown pytest.mark.test_id - is this a typo? You can register custom marks to avoid this warning - for details, see https://docs.pytest.org/en/latest/mark.html
這是因為我們沒有在
pytest中註冊test_id標記,但不影響正常的執行;如果你想去除這個告警,只需要在
pytest.ini的配置文件中註冊這個標記:[pytest] markers = test_id: 為測試用例添加ID
注意:
變動後的報告可能不符合最新的
JUnitXML的模式檢查規則,導致在某些CI工具上可能會發生未知的錯誤;
14.2. 在報告中為測試用例附加額外的屬性資訊
可以通過record_xml_attribute fixture為測試用例附加額外的屬性,而不像record_property為其添加子節點;
為測試用例添加一個test_id屬性,並修改原先的classname屬性:
# src/chapter-2/test_xml_report.py def test_record_property2(record_xml_attribute): record_xml_attribute('test_id', 10010) record_xml_attribute('classname', 'custom_classname') assert 1 在報告中的表現為<testcase classname="custom_classname" test_id="10010" ...:
<!-- src/chapter-2/report/test_record_property2.xml --> <?xml version="1.0" encoding="utf-8"?> <testsuites> <testsuite errors="0" failures="0" hostname="NJ-LUYAO-T460" name="pytest_chinese_doc" skipped="0" tests="1" time="0.028" timestamp="2019-09-27T15:35:47.093494"> <testcase classname="custom_classname" file="test_xml_report.py" line="34" name="test_record_property2" test_id="10010" time="0.001"></testcase> </testsuite> </testsuites> 注意:
record_xml_attribute目前是一個實驗性的功能,未來可能被更強大的API所替代,但功能本身會被保留。變動後的報告可能不符合最新的
JUnitXML的模式檢查規則,導致在某些CI工具上可能會發生未知的錯誤;
14.3. 在報告中為測試集附加額外的子節點資訊
4.5版本新增功能
可以通過自定義一個session作用域級別的fixture,為測試集添加子節點資訊,並且會作用於所有的測試用例;
這個自定義的fixture需要調用另外一個record_testsuite_property fixture:
record_testsuite_property接收兩個參數name和value以構成<property>標籤,其中,name必須為字元串,value會轉換為字元串並進行XML轉義;
# src/chapter-2/test_xml_report.py @pytest.fixture(scope="session") def log_global_env_facts(record_testsuite_property): record_testsuite_property("EXECUTOR", "luizyao") record_testsuite_property("LOCATION", "NJ") def test_record_property3(log_global_env_facts): assert 1 生成的測試報告表現為:在testsuite節點中,多了一個properties子節點,包含所有新增的屬性節點,而且,它和所有的testcase節點是平級的;
<!-- src/chapter-2/report/test_record_property3.xml --> <?xml version="1.0" encoding="utf-8"?> <testsuites> <testsuite errors="0" failures="0" hostname="NJ-LUYAO-T460" name="pytest_chinese_doc" skipped="0" tests="1" time="0.027" timestamp="2019-09-27T15:52:34.562238"> <properties> <property name="EXECUTOR" value="luizyao" /> <property name="LOCATION" value="NJ" /> </properties> <testcase classname="test_xml_report" file="test_xml_report.py" line="46" name="test_record_property3" time="0.002"> </testcase> </testsuite> </testsuites> 注意:
這樣生成的XML文件是符合最新的
xunit標準的,這點和record_property、record_xml_attribute正好相反;
15. 創建純文本格式的測試報告
不推薦使用,計劃在
pytest 6.0中刪除這個功能
使用如下命令,可以在指定的path中創建一個純文本的測試報告:
pytest --resultlog=path 16. 為測試報告提供URL鏈接 -- pastebin服務
目前,只實現了在http://bpaste.net上的展示功能;
為每一個失敗的測試用例創建一個URL
pytest --pastebin=failed也可以通過添加
-x選項,只為第一個失敗的測試用例創建一個URL;為所有的測試用例創建一個URL
pytest --pastebin=all
17. 儘早的載入插件
你可以在命令行中使用-p選項,來儘早的載入某一個插件:
pytest -p mypluginmodule -p選項接收一個name參數,這個參數可以為:
- 一個完整的本地插件引入,例如:
myproject.plugins,其必須是可以import的。 一個公共插件的名稱,這是其註冊時在
setuptools中賦予的名字,例如:儘早的載入pytest-cov插件:pytest -p pytest_cov
18. 去使能插件
你可以在命令行中使用-p結合no:,來去使能一個插件的載入,例如:
pytest -p no:doctest 19. 在python程式碼中調用pytest
可以直接在程式碼中調用pytest:
pytest.main() 這和你在命令行中執行pytest .幾乎是一樣的,但其也有以下特點:
不會觸發
SystemExit,而是返回exitcode:# src/chapter-2/invoke_via_main.py import time def test_one(): time.sleep(10) if __name__ == '__main__': import pytest ret = pytest.main(['-q', __file__]) print("pytest.main() 返回 pytest.ExitCode.INTERRUPTED:", ret == pytest.ExitCode.INTERRUPTED)用例中有等待10秒的操作,在這期間,打斷執行(
Ctr+C),pytest.main()返回的是INTERRUPTED狀態碼;λ pipenv run python src/chapter-2/invoke_via_main.py !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! KeyboardInterrupt !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! D:Personal FilesProjectspytest-chinese-docsrcchapter-2invoke_via_main.py:26: KeyboardInterrupt (to show a full traceback on KeyboardInterrupt use --full-trace) no tests ran in 1.04s pytest.main() 返回 pytest.ExitCode.INTERRUPTED: True Aborted!傳遞選項和參數:
pytest.main(["-x", "mytestdir"])指定一個插件:
import pytest class MyPlugin: def pytest_sessionfinish(self): print("*** test run reporting finishing") pytest.main(["-qq"], plugins=[MyPlugin()])
注意:
調用
pytest.main()會引入你的測試文件以及其引用的所有模組。由於python引入機制的快取特性,當這些文件發生變化時,後續再調用pytest.main()(在同一個程式執行過程中)時,並不會響應這些文件的變化。基於這個原因,我們不推薦在同一個程式中多次調用
pytest.main()(例如:為了重新執行測試;如果你確實有這個需求,或許可以考慮pytest-repeat插件);