Skip to content

Commit a6a28a0

Browse files
committed
add pytest --import-mode=importlib
1 parent d278db4 commit a6a28a0

File tree

8 files changed

+61
-1
lines changed

8 files changed

+61
-1
lines changed

docs/posts/2021/2021-06-12-python-unittest-cheat-sheet.md

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ categories:
77
comments: true
88
date:
99
created: 2021-06-12
10-
updated: 2024-12-27
10+
updated: 2025-02-17
1111
description: ''
1212
---
1313

@@ -783,3 +783,28 @@ after_yield_1
783783

784784
[Each atomic operation should be in a separate fixture](https://docs.pytest.org/en/stable/how-to/fixtures.html#safe-fixture-structure) and separating it from other.
785785
But not a big fixutre with many teardown operations after `yield`.
786+
787+
### no **init**.py files needed in test directories
788+
789+
With `--import-mode=importlib`, pytest can discover test files without needing `__init__.py` files in the test directories. This allows for a cleaner directory structure and avoids issues with same-named test files in different directories.
790+
791+
Without `--import-mode=importlib`, `tests/unit/entrypoints/test_health.py` and `tests/unit/services/test_health.py` both has the same module name `test_health`, which causes import conflicts. With `--import-mode=importlib`, pytest treats them as separate modules based on their file paths, allowing both to coexist without issues.
792+
793+
If `ruff` is used for linting, we can add the following configuration in `pyproject.toml` to ignore the `INP001` error (implicit-namespace-package) for test files, since we don't need `__init__.py` files in test directories.
794+
795+
```toml title="file pyproject.toml"
796+
[tool.ruff.lint.per-file-ignores]
797+
"tests*/**/*.py" = [
798+
"S101", # asserts allowed in tests...
799+
"INP001", # implicit-namespace-package
800+
]
801+
802+
[tool.pytest.ini_options]
803+
# --import-mode=importlib for same-named test files in different directories
804+
addopts = """
805+
-s
806+
-vv
807+
--import-mode=importlib
808+
"""
809+
asyncio_mode = "auto"
810+
```

temp1/lib_1/README.md

Whitespace-only changes.

temp1/lib_1/pyproject.toml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
[project]
2+
name = "lib-1"
3+
version = "0.1.0"
4+
description = "Add your description here"
5+
readme = "README.md"
6+
authors = [
7+
{ name = "Xiang ZHU", email = "xiang.zhu@outlook.com" }
8+
]
9+
requires-python = ">=3.13"
10+
dependencies = []
11+
12+
[build-system]
13+
requires = ["uv_build>=0.8.0,<0.9"]
14+
build-backend = "uv_build"

temp1/lib_1/src/lib_1/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
def hello() -> str:
2+
return "Hello from lib-1!"

temp1/lib_1/src/lib_1/py.typed

Whitespace-only changes.

temp1/pkg_1/README.md

Whitespace-only changes.

temp1/pkg_1/pyproject.toml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
[project]
2+
name = "pkg-1"
3+
version = "0.1.0"
4+
description = "Add your description here"
5+
readme = "README.md"
6+
authors = [
7+
{ name = "Xiang ZHU", email = "xiang.zhu@outlook.com" }
8+
]
9+
requires-python = ">=3.13"
10+
dependencies = []
11+
12+
[project.scripts]
13+
pkg-1 = "pkg_1:main"
14+
15+
[build-system]
16+
requires = ["uv_build>=0.8.0,<0.9"]
17+
build-backend = "uv_build"

temp1/pkg_1/src/pkg_1/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
def main() -> None:
2+
print("Hello from pkg-1!")

0 commit comments

Comments
 (0)