[英]PATH issue with pytest 'ImportError: No module named YadaYadaYada'
我使用 easy_install 在 Mac 上安裝 pytest 並開始為具有如下文件結構的項目編寫測試:
repo/
|--app.py
|--settings.py
|--models.py
|--tests/
|--test_app.py
在 repo 目錄中運行py.test
,一切都如你所料
但是當我在 linux 或 windows 上嘗試同樣的事情時(兩者都有 pytest 2.2.3),每當它從我的應用程序路徑中第一次導入某些東西時,它就會吠叫。 例如from app import some_def_in_app
我是否需要編輯我的 PATH 才能在這些系統上運行 py.test? 有沒有人經歷過這個?
我不確定為什么 py.test 沒有在 PYTHONPATH 本身中添加當前目錄,但這里有一個解決方法(從存儲庫的根目錄執行):
python -m pytest tests/
它之所以有效,是因為 Python 會為您在 PYTHONPATH 中添加當前目錄。
pytest>=7
的推薦方法:使用pythonpath
設置最近, pytest
新增了一個核心插件,支持通過pythonpath
配置值修改sys.path
。 因此,該解決方案現在要簡單得多,並且不再需要任何解決方法:
pyproject.toml
示例:
[tool.pytest.ini_options]
pythonpath = [
"."
]
pytest.ini
示例:
[pytest]
pythonpath = .
路徑條目是相對於根目錄計算的,因此.
在這種情況下,將repo
目錄添加到sys.path
。
還允許多個路徑條目:對於布局
repo/
├── src/
| └── lib.py
├── app.py
└── tests
├── test_app.py
└── test_lib.py
配置
[tool.pytest.ini_options]
pythonpath = [
".", "src",
]
或者
[pytest]
pythonpath = . src
將app
和lib
模塊都添加到sys.path
,所以
import app
import lib
兩者都可以。
pytest<7
): conftest
解決方案侵入性最小的解決方案是在repo/
目錄中添加一個名為conftest.py
的空文件:
$ touch repo/conftest.py
而已。 無需編寫自定義代碼來修改sys.path
或記住拖動PYTHONPATH
或將__init__.py
放入不屬於它的目錄中(使用python -m pytest
如Apteryx的答案中所建議的那樣是一個很好的解決方案!)。
之后的項目目錄:
repo
├── conftest.py
├── app.py
├── settings.py
├── models.py
└── tests
└── test_app.py
pytest
在測試集合上查找conftest
模塊以收集自定義鈎子和固定裝置,為了從中導入自定義對象, pytest
將conftest.py
的父目錄添加到sys.path
(在本例中為repo
目錄) .
如果您有其他項目結構,請將conftest.py
放在包根目錄中(包含包但本身不是包的目錄,因此不包含__init__.py
),例如:
repo
├── conftest.py
├── spam
│ ├── __init__.py
│ ├── bacon.py
│ └── egg.py
├── eggs
│ ├── __init__.py
│ └── sausage.py
└── tests
├── test_bacon.py
└── test_egg.py
src
布局雖然這種方法可以與src
布局一起使用(將conftest.py
放在src
目錄中):
repo
├── src
│ ├── conftest.py
│ ├── spam
│ │ ├── __init__.py
│ │ ├── bacon.py
│ │ └── egg.py
│ └── eggs
│ ├── __init__.py
│ └── sausage.py
└── tests
├── test_bacon.py
└── test_egg.py
請注意,將src
添加到PYTHONPATH
會減輕src
布局的意義和好處! 您最終將測試來自存儲庫的代碼,而不是已安裝的包。 如果你需要這樣做,也許你根本不需要src
目錄。
當然, conftest
模塊不僅僅是一些幫助源代碼發現的文件; 它是pytest
框架的所有特定於項目的增強和測試套件的定制發生的地方。 pytest
有很多關於conftest
模塊的信息,分散在他們的文檔中; 從conftest.py
開始:本地每個目錄插件
此外,SO 對conftest
模塊有一個很好的問題:在 py.test 中,conftest.py 文件有什么用?
我有同樣的問題。 我通過在我的tests
目錄中添加一個空的__init__.py
文件來修復它。
是的,如果您cd
到測試目錄,則源文件夾不在 Python 的路徑中。
您有 2 個選擇:
手動將路徑添加到測試文件中,如下所示:
import sys, os myPath = os.path.dirname(os.path.abspath(__file__)) sys.path.insert(0, myPath + '/../')
使用 env var PYTHONPATH=../
運行測試。
pytest
本身作為一個模塊運行: python -m pytest tests
您可以在項目根目錄中使用 PYTHONPATH 運行
PYTHONPATH=. py.test
或者使用 pip install 作為可編輯的導入
pip install -e . # install package using setup.py in editable mode
我在 Flask 中遇到了同樣的問題。
當我添加:
__init__.py
到測試文件夾,問題消失了:)
可能應用程序無法將文件夾測試識別為模塊
我創建這個是為了回答你的問題和我自己的困惑。 我希望它有所幫助。 注意 py.test 命令行和 tox.ini 中的 PYTHONPATH。
https://github.com/jeffmacdonald/pytest_test
具體來說:您必須告訴 py.test 和 tox 在哪里可以找到您所包含的模塊。
使用 py.test 你可以這樣做:
PYTHONPATH=. py.test
使用 tox,將其添加到您的 tox.ini 中:
[testenv]
deps= -r{toxinidir}/requirements.txt
commands=py.test
setenv =
PYTHONPATH = {toxinidir}
我通過刪除源文件的父文件夾中的頂級__init__.py
來修復它。
我開始變得奇怪ConftestImportFailure: ImportError('No module named ...
錯誤當我不小心將__init__.py
文件添加到我的 src 目錄時(它不應該是 Python 包,只是所有源的容器)。
我在學習 Flask 教程時遇到了同樣的問題,我在 Pytest 官方文檔中找到了答案。這與我(我認為許多其他人)習慣做事的方式有點不同。
您必須在項目的根目錄中創建一個setup.py
文件,其中至少包含以下兩行:
from setuptools import setup, find_packages
setup(name="PACKAGENAME", packages=find_packages())
其中 PACKAGENAME 是您的應用程序的名稱。 然后你必須用 pip 安裝它:
pip install -e .
-e
標志告訴 pip 以可編輯或“開發”模式安裝包。 因此,下次您運行pytest
時,它應該會在標准PYTHONPATH
中找到您的應用程序。
這是python中的一個問題有點遺憾......但只需添加這個環境變量是IMO最舒服的方式:
export PYTHONPATH=$PYTHONPATH:.
只需將其放入您的 .zshrc/.bashrc 中。
我有一個類似的問題。 pytest
無法識別安裝在我工作環境中的模塊。
我通過將pytest
安裝到同一環境中來解決它。
此外,如果您在虛擬環境中運行pytest
,請確保在您的虛擬環境中安裝pytest
模塊。 激活您的虛擬環境並運行pip install pytest
。
對我來說,問題是 Django 生成的tests.py
以及tests
目錄。 刪除tests.py
解決了這個問題。
我收到了這個錯誤,因為我錯誤地使用了相對導入。 在 OP 示例中,test_app.py 應該使用例如導入函數
from repo.app import *
然而 __init__.py 文件散布在文件結構周圍,這不起作用並創建了 ImportError 類型,除非文件和測試文件位於同一目錄中。
from app import *
這是我對我的一個項目所做的一個例子:
這是我的項目結構:
microbit/
microbit/activity_indicator/activity_indicator.py
microbit/tests/test_activity_indicator.py
為了能夠從 test_activity_indicator.py 訪問 activity_indicator.py,我需要:
from microbit.activity_indicator.activity_indicator import *
microbit/
microbit/__init__.py
microbit/activity_indicator/__init__.py
microbit/activity_indicator/activity_indicator.py
microbit/tests/__init__.py
microbit/tests/test_activity_indicator.py
由於更簡單的事情(你甚至可以說微不足道),我得到了這個錯誤。 我沒有安裝pytest
模塊。 所以一個簡單的apt install python-pytest
為我修復了它。
'pytest' 將作為測試依賴項列在 setup.py 中。 確保您也安裝了測試要求。
由於沒有人建議,您也可以在pytest.ini
文件中傳遞測試路徑:
[pytest]
...
testpaths = repo/tests
請參閱文檔: https ://docs.pytest.org/en/6.2.x/customize.html#pytest-ini
VScode 的副作用:它應該在 UI 中進行單元測試。
根據Dirk Avery 在 Medium 上的一篇文章(並得到我個人經驗的支持),如果您在項目中使用虛擬環境,那么您不能使用系統范圍的 pytest 安裝; 您必須在虛擬環境中安裝它並使用該安裝。
特別是,如果您在兩個地方都安裝了它,那么簡單地運行pytest
命令將不起作用,因為它將使用系統安裝。 正如其他答案所描述的,一個簡單的解決方案是運行python -m pytest
而不是pytest
; 這是有效的,因為它使用環境的 pytest 版本。 或者,您可以只卸載系統版本的 pytest; 重新激活虛擬環境后, pytest
命令應該可以工作。
正如Luiz Lezcano Arialdi所指出的,正確的解決方案是將您的包安裝為可編輯的包。
由於我使用的是 pipenv,我考慮在他的答案中逐步添加如何使用 pipenv 將當前路徑安裝為可食用的,從而允許運行 pytest 而無需任何修改代碼或松散文件。
您將需要具有以下最小文件夾結構(文檔):
package/
package/
__init__.py
module.py
tests/
module_test.py
setup.py
setup.py 大多數具有以下最小代碼( 文檔):
import setuptools
setuptools.setup(name='package', # Change to your package name
packages=setuptools.find_packages())
然后你只需要運行pipenv install --dev -e .
並且 pipenv 會將當前路徑安裝為可編輯的包( --dev 標志是可選的)( 文檔)。
現在你應該可以毫無問題地運行pytest
了。
我們通過添加以下環境變量解決了這個問題。
PYTHONPATH=${PYTHONPATH}:${PWD}/src:${PWD}/test
如果這個pytest錯誤出現的不是你自己的包,而是你包的requirements.txt中一個git安裝的包,解決方法是切換到可編輯安裝模式。
例如,假設您的包的 requirements.txt 有以下行:
git+https://github.com/foo/bar.git
您可以將其替換為以下內容:
-e git+https://github.com/foo/bar.git#egg=bar
很多時候由於模塊無法導入而中斷測試,經過研究,我發現系統在錯誤的位置查看文件,我們可以通過復制包含模塊的文件輕松解決問題,在與所述相同的文件夾,以便正確導入。 另一個解決方案建議是更改導入的聲明並向 MutPy 顯示單元的正確路徑。 然而,由於多個單元可以具有這種依賴關系,這意味着我們還需要在它們的聲明中提交更改,我們更喜歡簡單地將單元移動到文件夾中。
我的解決方案:
在test
目錄中創建conftest.py
文件,其中包含:
import os
import sys
sys.path.insert(0,os.path.dirname(os.path.realpath(__file__)) + "/relative/path/to/code/")
這會將感興趣的文件夾添加到 python 路徑中,而無需修改每個測試文件、設置環境變量或弄亂絕對/相對路徑。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.