簡體   English   中英

從 pip 移動到詩歌,現在 pytest-cov 不會收集覆蓋率數據

[英]Moved from pip to poetry and now pytest-cov won't collect coverage data

我最近開始使用poetry來管理項目依賴項,而不是使用requirements.txttest-requirements.txtpip

由於進行了更改,我無法讓覆蓋測試正常工作。 在這兩種情況下,我都使用tox來驅動測試(並且我安裝了tox-poetry擴展)。

我的tox.ini目前看起來像這樣:

[tox]
isolated_build = True
envlist = pep8,unit

[testenv]
whitelist_externals = poetry

[testenv:venv]
commands = {posargs}

[testenv:pep8]
commands =
    poetry run flake8 {posargs:symtool}

[testenv:unit]
commands =
    poetry run pytest --cov=symtool {posargs} tests/unit

以前,它看起來像這樣:

[tox]
envlist = pep8,unit

[testenv]
usedevelop = True
install_command = pip install -U {opts} {packages}
deps = -r{toxinidir}/requirements.txt
    -r{toxinidir}/test-requirements.txt

[testenv:venv]
commands = {posargs}

[testenv:pep8]
commands =
    flake8 {posargs:symtool}

[testenv:unit]
commands =
    pytest --cov=symtool {posargs} tests/unit

自從對poetry進行更改后,當我運行例如tox -e unit時,我看到:

unit run-test: commands[0] | poetry run pytest --cov=symtool tests/unit
===================================== test session starts =====================================
platform linux -- Python 3.9.1, pytest-6.2.2, py-1.10.0, pluggy-0.13.1
cachedir: .tox/unit/.pytest_cache
rootdir: /home/lars/projects/symtool, configfile: tox.ini
plugins: cov-2.11.1
collected 14 items

tests/unit/test_disasm.py .....                                                         [ 35%]
tests/unit/test_symtool.py .........                                                    [100%]r
Coverage.py warning: No data was collected. (no-data-collected)

我試圖找出no-data-collected問題。 根據pytest --help--cov arguments 設置路徑package 名稱:

 --cov=[SOURCE]        Path or package name to measure during execution

存儲庫的根目錄(即上面來自tox的 output 中的rootdir )如下所示:

asm
pyproject.toml
README.md
reference
symtool
tests
tox.ini

那里肯定有一個symtool目錄,其中包含 package。 即使測試沒有在項目根目錄中運行, symtool package 也會安裝在測試環境中,單元測試實際上是通過的事實證明了這一點(所有這些都包括import symtool的一些變體)。

我怎樣才能讓保險再次發揮作用?

將我的評論變成答案:

這是pytest-covtox的一個老問題(在issue #38中首次報告)。 tox將您的項目安裝為第三方 package 和pytest將從站點導入它(例如,如果作業名為unit ,則從.tox/unit/lib/python3.X/site-packages導入),而--cov=symtool指示pytest-cov收集項目根目錄中symtool目錄的覆蓋率。

一種解決方案是切換到src布局:

├── pyproject.toml
├── README.md
├── reference
├── src
|   └── symtool
├── tests
└── tox.ini

在您的pyproject.toml中,您需要將poetry指向源目錄:

[tool.poetry]
...
packages = [
    { include = "symtool", from = "src" },
]

現在src將阻止從源代碼樹導入代碼,因此--cov=symtool將收集已安裝模塊的覆蓋率,這是唯一的選擇。 對於開發過程的 rest,您不應該遇到麻煩,因為poetry install會以可編輯模式安裝項目,因此 rest 應該可以正常工作。

另一種選擇是使用tox跳過 package 安裝並以可編輯模式安裝。 放置在tox.ini中的示例代碼段:

[testenv]
whitelist_externals =
    poetry
skip_install = true
commands_pre =
    poetry install
commands =
    poetry run pytest ...

不過,這幾乎會扼殺對已安裝模塊的測試(您停止明確測試您的項目是否可以安裝在空白 venv 中,而不是使用源代碼樹中的內容),所以我將 go 與src布局選項。

如果您使用的是詩歌,您可能也喜歡在 tox 中使用 pytest、flake8、... 的鎖定依賴項。 這可以通過tox-poetry-installer來實現。

為確保您的測試針對構建和安裝的 package 而不是本地文件運行,您必須對 pytest 使用--import-mode標志並將其設置為importlib

要使用 pytest-cov 測量覆蓋率,您必須指向{envsitepackagesdir}

總而言之,您的tox.ini可能如下所示:

[tox]
isolated_build = true
requires =
    tox-poetry-installer[poetry] == 0.6.0
envlist = py39

[testenv]
locked_deps =
    pytest
    pytest-cov
commands = pytest --cov {envsitepackagesdir}/mypackage --import-mode=importlib

--import-mode在做什么?

要運行測試, pytest需要導入測試模塊。 傳統上,這是通過將發現的測試文件夾所在的根文件夾的路徑添加到sys.path來完成的。 通常測試文件夾和 package 文件夾共享同一個根文件夾。 所以添加到 sys.path 的副作用是,測試針對 package 文件夾而不是安裝的 package 運行,因為 python 首先找到這個文件夾。

而不是預先添加到sys.path ,可以建議pytest到 append 發現的根文件夾。 執行此操作 python 將在嘗試導入時首先查看 site-packages 文件夾。 因此,可以針對已安裝的 package 進行測試。

操縱sys.path幾乎總是一個壞主意,因為它會導致不必要的副作用。 pytest文檔描述了一個:

和 prepend 一樣,當測試目錄樹沒有在包中排列時,要求測試模塊名稱是唯一的,因為模塊在導入后會放在 sys.modules 中。

importlib 的第三個選項是在importlib 6 中引入的。它使用importlib來動態加載測試模塊,而無需操作sys.path 他們計划在未來的版本中將此選項設為默認選項。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM