[英]Moved from pip to poetry and now pytest-cov won't collect coverage data
我最近開始使用poetry
來管理項目依賴項,而不是使用requirements.txt
和test-requirements.txt
和pip
。
由於進行了更改,我無法讓覆蓋測試正常工作。 在這兩種情況下,我都使用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-cov
和tox
的一個老問題(在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.