pytest 用リソースがテストコードと一緒に置いてあると邪魔じゃないですか?
テスト用リソースがテストコードと一緒に置いてあると邪魔じゃないですか?
テスト用リソースを使用するテストはそれほど多くありません
テストコード内にテスト用リソースを配置すると、
エクスプローラーのツリー表示領域がテスト用リソースで埋め尽くされてしまいます:
tests/
└── some_test_package/
├── some_test_module_a/ (テスト用リソース)
├── some_test_module_b/ (テスト用リソース)
├── some_test_module_c.txt (テスト用リソース)
├── some_test_module_a.py
├── some_test_module_a.py
├── some_test_module_c.py
├── some_test_module_d.py
└── some_test_module_e.py
通常時にテストに関係のないファイルやディレクトリーは、
別の場所に隔離して普段は表示しないようにした方が生産性は高まるのではないでしょうか:
tests/
├── some_test_package/
│ ├── some_test_module_a.py
│ ├── some_test_module_b.py
│ └── some_test_module_c.py
│ └── some_test_module_d.py
│ └── some_test_module_e.py
└── testresources/ (テスト用リソース)
そこで、テスト用リソースをテストコードと分離して配置して管理しつつ
テストコードから簡単にアクセスすることが簡単にできる
pytest-resource-path という pytest プラグインを作成しました
pytest-resource-path
pytest-resource-path は分離されたテスト用リソースディレクトリーへのファイルシステムパスを
pytest fixture として提供します
(pytest fixture については理解していなくてもなんとか使えると思います)
この pytest プラグインはデフォルトでは、
テストリソースが tests/testresources
に配置されていることを前提としています
(これらのディレクトリー名は pyproject.toml
や pytest.ini
などでカスタマイズできます)
tests/
├── some_test_package/
│ └── some_test_module.py
└── testresources/
└── some_test_package/
└── some_test_module/
これによりテスト用リソースが隔離され、
テストコードのツリーがテスト用リソースで散らかることはなくなります
インストール方法
pip install pytest-resource-path
使用法
基本
まず実装コードを示します、たったこれだけになります:
def test_method(resource_path):
text_test_resource = (resource_path / 'test_resource.txt').read_text()
上記のように、pytest フィクスチャ: resource_path
を使用できます
- これは pathlib.Path インスタンス (絶対パス) です
上記のメソッド: test_method()
が
tests/some_tests_package/some_test_module.py
にあると仮定すると、
上記のテストコード中で読み取っているテスト用ファイル: test_resource.txt
は
次のディレクトリーに配置する必要があります:
tests/
├── some_test_package/
│ └── some_test_module.py
└── testresources/
└── some_test_package/
└── some_test_module/
└── test_method/
└── test_resource.txt
メソッドごとにディレクトリーを省略したい場合は、次のようにします:
def test_method(resource_path):
text_test_resource = Path(f'{resource_path}.txt').read_text()
この場合、テスト用リソースのファイル名は test_method.txt
となり、
次のディレクトリーに配置する必要があります:
tests/
├── some_test_package/
│ └── some_test_module.py
└── testresources/
└── some_test_package/
└── some_test_module/
└── test_method.txt
クラス名はパスでは使用されないことに注意してください
(冗長で使いにくくなると思われるため、そのような設計にしています)
テストリソースのルートディレクトリーへのパスを取得する方法
testresources
を指す resource_path_root
フィクスチャを使用できます:
def test_method(resource_path_root):
text_test_resource = (resource_path_root / 'test_resource.txt').read_text()
上記の場合、テスト用リソース: test_resource.txt
は
次のディレクトリーに配置する必要があります:
tests/
├── some_test_package/
│ └── some_test_module.py
└── testresources/
└── test_resource.txt
この resource_path_root
は、ディレクトリー構造の移行期間に役立つかもしれません
また、いくつかのテストで共通のディレクトリーを準備するのにも役立ちます:
def test_method(resource_path_root):
text_test_resource = (resource_path_root / 'common/test_resource.txt').read_text()
tests/
├── some_test_package/
│ └── some_test_module.py
└── testresources/
└── common/
└── test_resource.txt
ディレクトリー名をカスタマイズする方法
このプラグインでは、
ディレクトリー構造からファイルを取得するために、
ディレクトリー名を定められた名前にする必要があります
デフォルトは次の通りです:
ディレクトリーの種類 | 定められた名前 |
---|---|
テストコードのディレクトリー | tests |
テスト用リソースのディレクトリー | testresources |
これらのディレクトリー名は、pyproject.toml
や pytest.ini
などでカスタマイズできます
例として、次のようなディレクトリー構造にしたい場合を考えます:
integrationtests/
├── some_test_package/
│ └── some_test_module.py
└── data/
└── some_test_package/
└── some_test_module/
pyproject.toml
の場合
[tool.pytest.ini_options]
"resource-path.directory-name-tests" = "integrationtests"
"resource-path.directory-name-test-resources" = "data"
pytest.ini
の場合
[pytest]
resource-path.directory-name-tests = integrationtests
resource-path.directory-name-test-resources = data
Discussion