管理 pytest 的輸出

修改 Python 追蹤回溯列印

修改追蹤回溯列印的範例

pytest --showlocals     # show local variables in tracebacks
pytest -l               # show local variables (shortcut)
pytest --no-showlocals  # hide local variables (if addopts enables them)

pytest --capture=fd  # default, capture at the file descriptor level
pytest --capture=sys # capture at the sys level
pytest --capture=no  # don't capture
pytest -s            # don't capture (shortcut)
pytest --capture=tee-sys # capture to logs but also output to sys level streams

pytest --tb=auto    # (default) 'long' tracebacks for the first and last
                     # entry, but 'short' style for the other entries
pytest --tb=long    # exhaustive, informative traceback formatting
pytest --tb=short   # shorter traceback format
pytest --tb=line    # only one line per failure
pytest --tb=native  # Python standard library formatting
pytest --tb=no      # no traceback at all

當發生錯誤時,--full-trace 會導致列印非常長的追蹤(比 --tb=long 長)。它也會確保在 KeyboardInterrupt(Ctrl+C)上列印堆疊追蹤。如果測試花費太長的時間,而您使用 Ctrl+C 中斷它們以找出測試在哪裡掛起時,這會非常有用。預設不會顯示任何輸出(因為 KeyboardInterrupt 會被 pytest 捕捉)。使用這個選項可以確保顯示追蹤。

詳細程度

修改列印詳細程度的範例

pytest --quiet          # quiet - less verbose - mode
pytest -q               # quiet - less verbose - mode (shortcut)
pytest -v               # increase verbosity, display individual test names
pytest -vv              # more verbose, display more details from the test output
pytest -vvv             # not a standard , but may be used for even more detail in certain setups

在各個方面,-v 旗標控制 pytest 輸出的詳細程度:測試階段進度、測試失敗時的斷言詳細資料、使用 --fixtures 的固定裝置詳細資料等。

考慮這個簡單的檔案

# content of test_verbosity_example.py
def test_ok():
    pass


def test_words_fail():
    fruits1 = ["banana", "apple", "grapes", "melon", "kiwi"]
    fruits2 = ["banana", "apple", "orange", "melon", "kiwi"]
    assert fruits1 == fruits2


def test_numbers_fail():
    number_to_text1 = {str(x): x for x in range(5)}
    number_to_text2 = {str(x * 10): x * 10 for x in range(5)}
    assert number_to_text1 == number_to_text2


def test_long_text_fail():
    long_text = "Lorem ipsum dolor sit amet " * 10
    assert "hello world" in long_text

正常執行 pytest 會提供我們這個輸出(我們跳過標頭,專注於其餘部分)

$ pytest --no-header
=========================== test session starts ============================
collected 4 items

test_verbosity_example.py .FFF                                       [100%]

================================= FAILURES =================================
_____________________________ test_words_fail ______________________________

    def test_words_fail():
        fruits1 = ["banana", "apple", "grapes", "melon", "kiwi"]
        fruits2 = ["banana", "apple", "orange", "melon", "kiwi"]
>       assert fruits1 == fruits2
E       AssertionError: assert ['banana', 'a...elon', 'kiwi'] == ['banana', 'a...elon', 'kiwi']
E
E         At index 2 diff: 'grapes' != 'orange'
E         Use -v to get more diff

test_verbosity_example.py:8: AssertionError
____________________________ test_numbers_fail _____________________________

    def test_numbers_fail():
        number_to_text1 = {str(x): x for x in range(5)}
        number_to_text2 = {str(x * 10): x * 10 for x in range(5)}
>       assert number_to_text1 == number_to_text2
E       AssertionError: assert {'0': 0, '1':..., '3': 3, ...} == {'0': 0, '10'...'30': 30, ...}
E
E         Omitting 1 identical items, use -vv to show
E         Left contains 4 more items:
E         {'1': 1, '2': 2, '3': 3, '4': 4}
E         Right contains 4 more items:
E         {'10': 10, '20': 20, '30': 30, '40': 40}
E         Use -v to get more diff

test_verbosity_example.py:14: AssertionError
___________________________ test_long_text_fail ____________________________

    def test_long_text_fail():
        long_text = "Lorem ipsum dolor sit amet " * 10
>       assert "hello world" in long_text
E       AssertionError: assert 'hello world' in 'Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ips... sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet '

test_verbosity_example.py:19: AssertionError
========================= short test summary info ==========================
FAILED test_verbosity_example.py::test_words_fail - AssertionError: asser...
FAILED test_verbosity_example.py::test_numbers_fail - AssertionError: ass...
FAILED test_verbosity_example.py::test_long_text_fail - AssertionError: a...
======================= 3 failed, 1 passed in 0.12s ========================

請注意

  • 檔案中的每個測試都由輸出中的單一字元顯示:通過為 .,失敗為 F

  • test_words_fail 失敗,我們看到一個簡短的摘要,指出兩個清單的索引 2 不同。

  • test_numbers_fail 失敗,我們看到字典項目上左右差異的摘要。相同的項目會被省略。

  • test_long_text_fail 失敗,in 陳述式的右側被 ...` 截斷,因為它比內部閾值(目前為 240 個字元)長。

現在我們可以增加 pytest 的詳細程度

$ pytest --no-header -v
=========================== test session starts ============================
collecting ... collected 4 items

test_verbosity_example.py::test_ok PASSED                            [ 25%]
test_verbosity_example.py::test_words_fail FAILED                    [ 50%]
test_verbosity_example.py::test_numbers_fail FAILED                  [ 75%]
test_verbosity_example.py::test_long_text_fail FAILED                [100%]

================================= FAILURES =================================
_____________________________ test_words_fail ______________________________

    def test_words_fail():
        fruits1 = ["banana", "apple", "grapes", "melon", "kiwi"]
        fruits2 = ["banana", "apple", "orange", "melon", "kiwi"]
>       assert fruits1 == fruits2
E       AssertionError: assert ['banana', 'a...elon', 'kiwi'] == ['banana', 'a...elon', 'kiwi']
E
E         At index 2 diff: 'grapes' != 'orange'
E
E         Full diff:
E           [
E               'banana',
E               'apple',...
E
E         ...Full output truncated (7 lines hidden), use '-vv' to show

test_verbosity_example.py:8: AssertionError
____________________________ test_numbers_fail _____________________________

    def test_numbers_fail():
        number_to_text1 = {str(x): x for x in range(5)}
        number_to_text2 = {str(x * 10): x * 10 for x in range(5)}
>       assert number_to_text1 == number_to_text2
E       AssertionError: assert {'0': 0, '1':..., '3': 3, ...} == {'0': 0, '10'...'30': 30, ...}
E
E         Omitting 1 identical items, use -vv to show
E         Left contains 4 more items:
E         {'1': 1, '2': 2, '3': 3, '4': 4}
E         Right contains 4 more items:
E         {'10': 10, '20': 20, '30': 30, '40': 40}
E         ...
E
E         ...Full output truncated (16 lines hidden), use '-vv' to show

test_verbosity_example.py:14: AssertionError
___________________________ test_long_text_fail ____________________________

    def test_long_text_fail():
        long_text = "Lorem ipsum dolor sit amet " * 10
>       assert "hello world" in long_text
E       AssertionError: assert 'hello world' in 'Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet '

test_verbosity_example.py:19: AssertionError
========================= short test summary info ==========================
FAILED test_verbosity_example.py::test_words_fail - AssertionError: asser...
FAILED test_verbosity_example.py::test_numbers_fail - AssertionError: ass...
FAILED test_verbosity_example.py::test_long_text_fail - AssertionError: a...
======================= 3 failed, 1 passed in 0.12s ========================

現在請注意

  • 檔案中的每個測試都在輸出中取得自己的行。

  • test_words_fail 現在完整顯示兩個失敗的清單,以及哪些索引不同。

  • test_numbers_fail 現在顯示兩個字典的文字差異,已截斷。

  • test_long_text_fail 不再截斷 in 陳述式的右側,因為內部截斷門檻現在較大(目前為 2400 個字元)。

現在,如果我們進一步增加詳細程度

$ pytest --no-header -vv
=========================== test session starts ============================
collecting ... collected 4 items

test_verbosity_example.py::test_ok PASSED                            [ 25%]
test_verbosity_example.py::test_words_fail FAILED                    [ 50%]
test_verbosity_example.py::test_numbers_fail FAILED                  [ 75%]
test_verbosity_example.py::test_long_text_fail FAILED                [100%]

================================= FAILURES =================================
_____________________________ test_words_fail ______________________________

    def test_words_fail():
        fruits1 = ["banana", "apple", "grapes", "melon", "kiwi"]
        fruits2 = ["banana", "apple", "orange", "melon", "kiwi"]
>       assert fruits1 == fruits2
E       AssertionError: assert ['banana', 'apple', 'grapes', 'melon', 'kiwi'] == ['banana', 'apple', 'orange', 'melon', 'kiwi']
E
E         At index 2 diff: 'grapes' != 'orange'
E
E         Full diff:
E           [
E               'banana',
E               'apple',
E         -     'orange',
E         ?      ^  ^^
E         +     'grapes',
E         ?      ^  ^ +
E               'melon',
E               'kiwi',
E           ]

test_verbosity_example.py:8: AssertionError
____________________________ test_numbers_fail _____________________________

    def test_numbers_fail():
        number_to_text1 = {str(x): x for x in range(5)}
        number_to_text2 = {str(x * 10): x * 10 for x in range(5)}
>       assert number_to_text1 == number_to_text2
E       AssertionError: assert {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4} == {'0': 0, '10': 10, '20': 20, '30': 30, '40': 40}
E
E         Common items:
E         {'0': 0}
E         Left contains 4 more items:
E         {'1': 1, '2': 2, '3': 3, '4': 4}
E         Right contains 4 more items:
E         {'10': 10, '20': 20, '30': 30, '40': 40}
E
E         Full diff:
E           {
E               '0': 0,
E         -     '10': 10,
E         ?       -    -
E         +     '1': 1,
E         -     '20': 20,
E         ?       -    -
E         +     '2': 2,
E         -     '30': 30,
E         ?       -    -
E         +     '3': 3,
E         -     '40': 40,
E         ?       -    -
E         +     '4': 4,
E           }

test_verbosity_example.py:14: AssertionError
___________________________ test_long_text_fail ____________________________

    def test_long_text_fail():
        long_text = "Lorem ipsum dolor sit amet " * 10
>       assert "hello world" in long_text
E       AssertionError: assert 'hello world' in 'Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet '

test_verbosity_example.py:19: AssertionError
========================= short test summary info ==========================
FAILED test_verbosity_example.py::test_words_fail - AssertionError: assert ['banana', 'apple', 'grapes', 'melon', 'kiwi'] == ['banana', 'apple', 'orange', 'melon', 'kiwi']

  At index 2 diff: 'grapes' != 'orange'

  Full diff:
    [
        'banana',
        'apple',
  -     'orange',
  ?      ^  ^^
  +     'grapes',
  ?      ^  ^ +
        'melon',
        'kiwi',
    ]
FAILED test_verbosity_example.py::test_numbers_fail - AssertionError: assert {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4} == {'0': 0, '10': 10, '20': 20, '30': 30, '40': 40}

  Common items:
  {'0': 0}
  Left contains 4 more items:
  {'1': 1, '2': 2, '3': 3, '4': 4}
  Right contains 4 more items:
  {'10': 10, '20': 20, '30': 30, '40': 40}

  Full diff:
    {
        '0': 0,
  -     '10': 10,
  ?       -    -
  +     '1': 1,
  -     '20': 20,
  ?       -    -
  +     '2': 2,
  -     '30': 30,
  ?       -    -
  +     '3': 3,
  -     '40': 40,
  ?       -    -
  +     '4': 4,
    }
FAILED test_verbosity_example.py::test_long_text_fail - AssertionError: assert 'hello world' in 'Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet '
======================= 3 failed, 1 passed in 0.12s ========================

現在請注意

  • 檔案中的每個測試都在輸出中取得自己的行。

  • test_words_fail 在這種情況下會提供與之前相同的輸出。

  • test_numbers_fail 現在會顯示兩個字典的完整文字差異。

  • test_long_text_fail 也不會像之前那樣在右側截斷,但現在 pytest 根本不會截斷任何文字,無論其大小如何。

這些是詳細程度如何影響正常測試階段輸出的範例,但詳細程度也用於其他情況,例如,如果你使用 pytest --fixtures -v,你甚至會看到以 _ 開頭的固定裝置。

支援使用較高的詳細程度層級 (-vvv-vvvv、…),但目前在 pytest 本身中沒有作用,不過有些外掛程式可能會使用較高的詳細程度。

細緻的詳細程度

除了指定應用程式的詳細程度層級之外,也可以獨立控制特定面向。這會透過在輸出特定面向的設定檔中設定詳細程度層級來完成。

verbosity_assertions:控制執行 pytest 時,斷言輸出的詳細程度。執行 pytest --no-header,其值為 2,其輸出與前一個範例相同,但檔案中的每個測試都會在輸出中以單一字元顯示。

verbosity_test_cases:控制執行 pytest 時,測試執行輸出的詳細程度。執行 pytest --no-header,其值為 2,其輸出與第一個詳細程度範例相同,但檔案中的每個測試都會在輸出中取得自己的行。

產生詳細摘要報告

可以使用 -r 旗標在測試階段結束時顯示「簡短測試摘要資訊」,這讓大型測試套件可以輕易地清楚掌握所有失敗、略過、xfail 等情況。

預設為 fE,用於列出失敗和錯誤。

範例

# content of test_example.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
$ pytest -ra
=========================== test session starts ============================
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y
rootdir: /home/sweet/project
collected 6 items

test_example.py .FEsxX                                               [100%]

================================== ERRORS ==================================
_______________________ ERROR at setup of test_error _______________________

    @pytest.fixture
    def error_fixture():
>       assert 0
E       assert 0

test_example.py:6: AssertionError
================================= FAILURES =================================
________________________________ test_fail _________________________________

    def test_fail():
>       assert 0
E       assert 0

test_example.py:14: AssertionError
================================ XFAILURES =================================
________________________________ test_xfail ________________________________

    def test_xfail():
>       pytest.xfail("xfailing this test")
E       _pytest.outcomes.XFailed: xfailing this test

test_example.py:26: XFailed
================================= XPASSES ==================================
========================= short test summary info ==========================
SKIPPED [1] test_example.py:22: skipping this test
XFAIL test_example.py::test_xfail - reason: xfailing this test
XPASS test_example.py::test_xpass - always xfail
ERROR test_example.py::test_error - assert 0
FAILED test_example.py::test_fail - assert 0
== 1 failed, 1 passed, 1 skipped, 1 xfailed, 1 xpassed, 1 error in 0.12s ===

-r 選項後面可以接受多個字元,上面使用的 a 表示「全部,除了通過」。

以下是可用的完整字元清單

  • f - 失敗

  • E - 錯誤

  • s - 略過

  • x - xfail

  • X - xpass

  • p - 通過

  • P - 通過,並有輸出

群組(去)選取的特殊字元

  • a - 全部,除了 pP

  • A - 全部

  • N - 無,這可以用於不顯示任何內容(因為 fE 是預設值)

可以使用多個字元,例如,若要只看失敗和略過的測試,可以執行

$ pytest -rfs
=========================== test session starts ============================
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y
rootdir: /home/sweet/project
collected 6 items

test_example.py .FEsxX                                               [100%]

================================== ERRORS ==================================
_______________________ ERROR at setup of test_error _______________________

    @pytest.fixture
    def error_fixture():
>       assert 0
E       assert 0

test_example.py:6: AssertionError
================================= FAILURES =================================
________________________________ test_fail _________________________________

    def test_fail():
>       assert 0
E       assert 0

test_example.py:14: AssertionError
========================= short test summary info ==========================
FAILED test_example.py::test_fail - assert 0
SKIPPED [1] test_example.py:22: skipping this test
== 1 failed, 1 passed, 1 skipped, 1 xfailed, 1 xpassed, 1 error in 0.12s ===

使用 p 會列出通過的測試,而 P 會新增一個額外的區段「通過」,其中包含通過但有擷取輸出的測試

$ pytest -rpP
=========================== test session starts ============================
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y
rootdir: /home/sweet/project
collected 6 items

test_example.py .FEsxX                                               [100%]

================================== ERRORS ==================================
_______________________ ERROR at setup of test_error _______________________

    @pytest.fixture
    def error_fixture():
>       assert 0
E       assert 0

test_example.py:6: AssertionError
================================= FAILURES =================================
________________________________ test_fail _________________________________

    def test_fail():
>       assert 0
E       assert 0

test_example.py:14: AssertionError
================================== PASSES ==================================
_________________________________ test_ok __________________________________
--------------------------- Captured stdout call ---------------------------
ok
========================= short test summary info ==========================
PASSED test_example.py::test_ok
== 1 failed, 1 passed, 1 skipped, 1 xfailed, 1 xpassed, 1 error in 0.12s ===

建立 resultlog 格式檔案

若要建立純文字機器可讀的結果檔案,您可以執行

pytest --resultlog=path

並查看 path 位置的內容。此類檔案會由 PyPy-test 網頁使用,以顯示多個修訂版本的測試結果。

警告

此選項很少使用,且已排定在 pytest 6.0 中移除。

如果您使用此選項,請考慮改用新的 pytest-reportlog 外掛程式。

請參閱 淘汰文件 以取得更多資訊。

建立 JUnitXML 格式檔案

若要建立可由 Jenkins 或其他持續整合伺服器讀取的結果檔案,請使用此呼叫

pytest --junit-xml=path

path 建立 XML 檔案。

若要設定根測試套件 xml 項目名稱,您可以在設定檔中設定 junit_suite_name 選項

[pytest]
junit_suite_name = my_suite

於 4.0 版新增。

JUnit XML 規格似乎指出 "time" 屬性應報告總測試執行時間,包括設定和清除 (1, 2)。這是 pytest 的預設行為。若要僅報告呼叫持續時間,請像這樣設定 junit_duration_report 選項

[pytest]
junit_duration_report = call

record_property

如果您想要記錄測試的額外資訊,可以使用 record_property 固定裝置

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

這會將額外的屬性 example_key="1" 新增到產生的 testcase 標籤

<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>

或者,您可以將此功能與自訂標記整合

# content of 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))

在您的測試中

# content of 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>

警告

請注意,使用此功能將會中斷最新 JUnitXML schema 的 schema 驗證。在與某些 CI 伺服器一起使用時,這可能會造成問題。

record_xml_attribute

若要將其他 xml 屬性新增至測試案例元素,您可以使用 record_xml_attribute 固定裝置。這也可以用於覆寫現有值

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 不同,這不會新增新的子元素。相反地,這會在產生的 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 是實驗性功能,其介面可能會在未來版本中被更強大且通用的功能取代。不過,其功能本身將會保留。

在使用 CI 工具來解析 XML 報告時,使用此功能取代 record_xml_property 會有所幫助。但是,有些解析器對於允許的元素和屬性相當嚴格。許多工具使用 xsd schema(如下面的範例)來驗證輸入的 XML。請務必使用解析器允許的屬性名稱。

以下是 Jenkins 用來驗證 XML 報告的 Schema

<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>

警告

請注意,使用此功能將會中斷最新 JUnitXML schema 的 schema 驗證。在與某些 CI 伺服器一起使用時,這可能會造成問題。

record_testsuite_property

在版本 4.5 中新增。

如果您想要在測試套件層級新增屬性節點,其中可能包含與所有測試相關的屬性,您可以使用 record_testsuite_property 會話範圍固定裝置

可以將 record_testsuite_property 會話範圍固定裝置用於新增與所有測試相關的屬性。

import pytest


@pytest.fixture(scope="session", autouse=True)
def log_global_env_facts(record_testsuite_property):
    record_testsuite_property("ARCH", "PPC")
    record_testsuite_property("STORAGE_TYPE", "CEPH")


class TestMe:
    def test_foo(self):
        assert True

固定裝置是一個可呼叫的物件,它接收在生成的 XML 的測試套件層級中新增的 <property> 標籤的 namevalue

<testsuite errors="0" failures="0" name="pytest" skipped="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>

name 必須是字串,value 會轉換成字串並適當地進行 XML 轉譯。

record_propertyrecord_xml_attribute 相反,所產生的 XML 與最新的 xunit 標準相容。

將測試報告傳送至線上貼上服務

為每個測試失敗建立 URL:

pytest --pastebin=failed

這會將測試執行資訊提交至遠端貼上服務,並為每個失敗提供 URL。您可以像往常一樣選擇測試,或新增例如 -x,如果您只想傳送一個特定的失敗。

為整個測試階段記錄建立 URL:

pytest --pastebin=all

目前只實作貼上至 https://bpaste.net/ 服務。

在版本 5.2 中變更。

如果建立 URL 因任何原因而失敗,會產生警告,而不是讓整個測試套件失敗。