英文:
pytest multiple apps with similar package and module structure
问题
我有以下的项目结构:
project/
├── src/
| ├── app_a/
│ │ ├── routes/
│ │ │ ├── get.py
│ │ │ └── post.py
│ │ └── app.py
| └── app_b/
│ ├── routes/
│ │ ├── get.py
│ │ └── post.py
│ └── app.py
└── test/
├── test_app_a.py
└── test_app_b.py
我通常会像这样组织我的代码,有一个单独的 "src" 和 "test" 目录。到目前为止,我从未在此方面遇到过任何问题。但在这个项目中,我有多个小型应用程序,它们具有相似的结构。来自 app_a 和 app_b 的 "app.py" 模块都导入了 "routes" 包中的模块 (get.py 和 post.py)。这些小应用在它们的容器中完全正常运行,运行时一切都很好。但现在我想使用 pytest 添加一些测试。
我将两个应用程序目录都添加到了 "proproject.toml" 中的 "pythonpath" 字段中,像这样:
```plaintext
[tool.pytest.ini_options]
pythonpath = [".", "src/app_a", "src/app_b"]
现在测试可以正常运行,但来自测试 app_b 的 "app.py" 正在导入来自 app_a 的 "get.py" 和 "post.py",这很明显是因为 app_a 的路径在 app_b 之前。我完全明白为什么会发生这种情况,但我不知道如何解决这个问题!
你们这些厉害的 Python 程序员中有谁能帮助我吗?
更新:在不同的应用程序之间进行相互导入并非必要。
<details>
<summary>英文:</summary>
i have the following project structure:
project/
├── src/
| ├── app_a/
│ │ ├── routes/
│ │ │ ├── get.py
│ │ │ └── post.py
│ │ └── app.py
| └── app_b/
│ ├── routes/
│ │ ├── get.py
│ │ └── post.py
│ └── app.py
└── test/
├── test_app_a.py
└── test_app_b.py
I usually structure my code like this where i have a separate "src" and "test" directory, and until now i never had any problems with this. But in this project i have multiple small apps which have a similar structure. The "app.py" modules from app_a and app_b both import the modules from package routes (get.py and post.py). The small apps run totally fine in their container and everything is good regarding the runtime. But now i want to add some tests with pytest.
I added both app directories in the proproject.toml under the pythonpath field like this:
[tool.pytest.ini_options]
pythonpath = [".", "src/app_a", "src/app_b"]
Now the tests run fine but the app.py from testing the app_b is importing the get.py and post.py from app_a which is clear because the path to app_a i before the path to app_b. I think i totally understand why this is happening but i don't know how to solve this problem!
Can someone of you awesome pythonistas help me with this?
UPDATE: It is not necessary to to cross import between different apps.
</details>
# 答案1
**得分**: 2
*Solution*: 从项目目录运行您的测试,不要添加任何内容到路径中。
像这样:
cd project
pytest test
然后您必须相对于该项目目录进行导入,例如在 `test_app_a.py` 中:
import src.app_a.routes.get as get_a
def test_get_a():
get_a.function_in_get_dot_py()
如果您在 `app.py` 中有像 `import routes.get` 这样的东西,重要的是将其更改为
from .routes import get
使用这种方法。
还要注意,现在您不能再运行 `python src/app_a/app.py`,而是必须运行
python -m src.app_a.app
作为模块来运行。
您可能需要为 `src` 或 `app_a` 文件夹添加一个 `__init__.py` 文件,以使其正常工作。
-------
如果应用程序需要彼此导入,例如如果 `app_b` 做了像 `from app_a...` 这样的导入,有几种解决方案。
1) 应用程序可以更改为引用相同目录,`from src.app_a...`,并在独立运行时使用 `-m` 标志运行该目录
python -m src.app_a.app
2) 相对于 .py 文件的相对导入也可以工作,例如在 `app_a/routes/get.py` 中,您可以有 `from ...app_b import`。这仅在使用 `python -m ..` 运行时有效。
3) 将 `src` 添加到路径。
------
想法:
- 我确信还有其他解决方案,可以完全不同的方式做一些事情,Python 导入系统肯定有一定的学习曲线。
- 最初我认为您可以在不将应用程序更改为模块并以那种方式运行的情况下做到这一点,也许有一种方法,但至少这应该可以工作。
- 如果将东西添加到全局路径中是混乱的,但这里没有发生这种情况。总的来说,我尽量避免更改路径,如果有可能的话。
- 分别具有独立的 src 和 test 文件夹非常好。
- 在我的项目中,只需执行 `import src`,然后执行例如 `src.py_file_there.function()` 就可以了,但由于某种原因,在这里测试时没有起作用。
<details>
<summary>英文:</summary>
*Solution*: Run your tests from the project directory and don't add anything to the path.
Like this:
cd project
pytest test
Then you have to do the imports relative to that project directory, e.g. in `test_app_a.py`:
import src.app_a.routes.get as get_a
def test_get_a():
get_a.function_in_get_dot_py()
It is important if you have things like `import routes.get` in `app.py` to change that to
from .routes import get
with this method.
Also note, now you can't run `python src/app_a/app.py` anymore but have to run
python -m src.app_a.app
to run as a module.
You might have to add an `__init__.py` file to `src` or `app_a` folder for this to work.
-------
If the apps need to import from each other, e.g if app_b does an import like `from app_a...` there are a few solutions.
1) The apps could be changed to reference from the same directory, `from src.app_a...` and run from that directory when run on their own using the `-m` flag
python -m src.app_a.app
2) Relative imports relative to the .py files would work as well, e.g. in `app_a/routes/get.py` you could have `from ...app_b import`. This only works when run with `python -m ..`
3) Add `src` to path.
------
Thoughts:
- I'm sure there are other solutions as well doing something completely different, the python import system certainly has a learning curve.
- Initially I thought you could do this without changing app to a module and running it like that, perhaps there's a way, but at least this should work.
- Adding things to the path if it's global is messy, but that's not what is going on here. In general though I try to avoid changing the path if at all possible.
- Very good to have separate src and test folders.
- In my project it works to do just `import src` and then do e.g. `src.py_file_there.function()` but for some reason it didn't work when testing this here.
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论