pytest7.4版本的一個變更,可能會影響你的專案

2023-07-10 18:01:08

pytest7.4版本的一個變更,可能會影響你的專案

本文撰寫於 2023.7.10

準備工作

  • 專案結構如下

    D:\Gitee\DemoRepo (17.97MB)
    +-- testCases (1.03KB)
    |   +-- conftest.py (252b)
    |   +-- pmCases (574b)
    |   |   +-- conftest.py (259b)
    |   |   `-- test_logout.py (315b)
    
  • 頂層conftest.py內容

    import pytest
    
    @pytest.fixture(scope='session')
    def fix_all():
        print('fix_all')
    
  • pmCases下的conftest.py內容

    import pytest
    
    @pytest.fixture(scope='session', autouse=True)
    def fix_all2():
        print('fix_all2')
    
    
  • test_logout.py內容

    import pytest
    
    
    def test_logout(fix_all):
        print('test_logout')
    
    if __name__ == '__main__':
        pytest.main(['-sv',__file__])
    

Pytest7.4之前

用的Pytest7.3.1,而實際7.4.0之前也就只有一個7.3.2了

  • 你是可以執行test_logout.py的

  • 效果如下

    test_logout.py::test_logout fix_all2
    fix_all
    test_logout
    PASSED
    
  • 所以按照以前的認識

    • conftest可以存在多個
    • 測試用例可以看到上級目錄的conftest
    • 但看不到下級目錄的conftest(此處沒有演示)

Pytest4.0

執行效果

注意把pytest更新到pytest7.4.0

  • 同樣執行test_logout.py

  • 效果如下

    D:\Gitee\DemoRepo\venv\Scripts\python.exe D:/Gitee/DemoRepo/testCases/pmCases/test_logout.py
    ============================= test session starts =============================
    platform win32 -- Python 3.9.6, pytest-7.4.0, pluggy-1.2.0 -- D:\Gitee\DemoRepo\venv\Scripts\python.exe
    cachedir: .pytest_cache
    rootdir: D:\Gitee\DemoRepo\testCases\pmCases
    collecting ... collected 1 item
    
    test_logout.py::test_logout fix_all2
    ERROR
    
    =================================== ERRORS ====================================
    ________________________ ERROR at setup of test_logout ________________________
    file D:\Gitee\DemoRepo\testCases\pmCases\test_logout.py, line 10
      def test_logout(fix_all):
    E       fixture 'fix_all' not found
    >       available fixtures: cache, capfd, capfdbinary, caplog, capsys, capsysbinary, doctest_namespace, fix_all2, monkeypatch, pytestconfig, record_property, record_testsuite_property, record_xml_attribute, recwarn, tmp_path, tmp_path_factory, tmpdir, tmpdir_factory
    >       use 'pytest --fixtures [testpath]' for help on them.
    
    D:\Gitee\DemoRepo\testCases\pmCases\test_logout.py:10
    =========================== short test summary info ===========================
    ERROR test_logout.py::test_logout
    ============================== 1 error in 0.01s ===============================
    
    程序已結束,退出程式碼為 0
    
    
  • 很清楚的提示

    E       fixture 'fix_all' not found
    
  • 子目錄無法去參照上級目錄的fixture

  • 而同級目錄不受影響

  • 我們的實戰課就會用到子目錄下的測試檔案呼叫上級目錄的fixture,是沒問題的,但現在會受影響。

  • 這是為何呢?第一個想法就是版本變動了。但覺得不太可以理解,正常版本變動對這些邏輯不應該去大改,除非是大版本的改變。因為一旦出現這樣的參照,你以前的專案會無法呼叫。


  • 很多的時候你是在終端下執行

  • 修改test_logout.py

    def test_logout(fix_all):
        print('test_logout')
    
  • 終端下執行

    D:\Gitee\DemoRepo\testCases>pytest
    # 這是成功的
    
  • 這樣執行

    D:\Gitee\DemoRepo\testCases\pmCases>pytest
    # 報錯跟上面一樣  E       fixture 'fix_all' not found
    
    
  • 基於此,如果你是終端下執行的話,其實是沒啥影響的。

  • 只有你要在子目錄下測試或者單獨執行子測試用例時可能會有問題


  • 帶著這樣的疑問去官方檔案找原因。

changlog Of pytest 7.4.0

https://docs.pytest.org/en/7.4.x/changelog.html

釋出時間 (2023-06-23)

Features

Improvements

  • #10872: Update test log report annotation to named tuple and fixed inconsistency in docs for pytest_report_teststatus hook.

  • #10907: When an exception traceback to be displayed is completely filtered out (by mechanisms such as __tracebackhide__, internal frames, and similar), now only the exception string and the following message are shown:

    「All traceback entries are hidden. Pass --full-trace to see hidden and internal frames.」.

    Previously, the last frame of the traceback was shown, even though it was hidden.

  • #10940: Improved verbose output (-vv) of skip and xfail reasons by performing text wrapping while leaving a clear margin for progress output.

    Added TerminalReporter.wrap_write() as a helper for that.

  • #10991: Added handling of %f directive to print microseconds in log format options, such as log-date-format.

  • #11005: Added the underlying exception to the cache provider’s path creation and write warning messages.

  • #11013: Added warning when testpaths is set, but paths are not found by glob. In this case, pytest will fall back to searching from the current directory.

  • #11043: When --confcutdir is not specified, and there is no config file present, the conftest cutoff directory (--confcutdir) is now set to the rootdir. Previously in such cases, conftest.py files would be probed all the way to the root directory of the filesystem. If you are badly affected by this change, consider adding an empty config file to your desired cutoff directory, or explicitly set --confcutdir.

  • #11081: The norecursedirs check is now performed in a pytest_ignore_collect implementation, so plugins can affect it.

    If after updating to this version you see that your norecursedirs setting is not being respected, it means that a conftest or a plugin you use has a bad pytest_ignore_collect implementation. Most likely, your hook returns False for paths it does not want to ignore, which ends the processing and doesn’t allow other plugins, including pytest itself, to ignore the path. The fix is to return None instead of False for paths your hook doesn’t want to ignore.

  • #8711: caplog.set_level() and caplog.at_level() will temporarily enable the requested level if level was disabled globally via logging.disable(LEVEL).

Bug Fixes

  • #10831: Terminal Reporting: Fixed bug when running in --tb=line mode where pytest.fail(pytrace=False) tests report None.
  • #11068: Fixed the --last-failed whole-file skipping functionality (「skipped N files」) for non-python test files.
  • #11104: Fixed a regression in pytest 7.3.2 which caused to testpaths to be considered for loading initial conftests, even when it was not utilized (e.g. when explicit paths were given on the command line). Now the testpaths are only considered when they are in use.
  • #1904: Fixed traceback entries hidden with __tracebackhide__ = True still being shown for chained exceptions (parts after 「… the above exception …」 message).
  • #7781: Fix writing non-encodable text to log file when using --debug.

Improved Documentation

Trivial/Internal Changes

  • #11031: Enhanced the CLI flag for -c to now include --config-file to make it clear that this flag applies to the usage of a custom config file.

抓重點

  • 原文

    When `--confcutdir` is not specified, and there is no config file present, the conftest cutoff directory (`--confcutdir`) is now set to the [rootdir](https://docs.pytest.org/en/7.4.x/reference/customize.html). Previously in such cases, `conftest.py` files would be probed all the way to the root directory of the filesystem. If you are badly affected by this change, consider adding an empty config file to your desired cutoff directory, or explicitly set `--confcutdir`.
    
  • 譯文

    當未指定--confcutdir並且沒有組態檔存在時,conftest截斷目錄(--confcutdir)現在被設定為rootdir。在以前的情況下,conftest.py檔案會一直被探測到檔案系統的根目錄。如果你受到這個變化的嚴重影響,考慮在所需的截斷目錄中新增一個空的組態檔,或者明確地設定--confcutdir。
    

解決方式

  • 指定引數--confcutdir

  • 範例1: test_logout.py執行

    import pytest
    
    
    def test_logout(fix_all):
        print('test_logout')
    
    if __name__ == '__main__':
        pytest.main(['-sv','--confcutdir=..',__file__]) # 意思是設定conftest.py的搜尋根目錄是當前目錄上級
    
  • 範例2: 終端執行

    # 你在pmCases下執行
    # 如果在專案根目錄下,本來就是ok的
    pytest --confcutdir=..
    
  • 範例3: pytest.ini

    [pytest]
    # 改為實際的專案根目錄即可
    addopts = --confcutdir="D:\Gitee\DemoRepo" 
    
    • 注意不要寫成--confcutdir=.(因為你是把pytest.ini放在根目錄下的)

補充說明

  • 截止到撰寫本文的時候(2023-7-10)發現

  • pip install pytest會安裝最新的Pytest7.4.0

  • 而通過pycharm安裝則是Pytest7.3.1

  • 對於這個引數,命令列--help的解釋是

      --confcutdir=dir      Only load conftest.py's relative to specified dir