Ccmmutty logo
Commutty IT
4 min read

pytest使う際のフォルダ構成とそれに伴うpath設定について

https://cdn.magicode.io/media/notebox/4c7eb4d5-470a-4154-83dc-f694ed23e614.jpeg

初めに

pythonのコードはちょっとした計算だったりお試し用のプログラムでテストコード書いてきていなかったが、書く必要性が出てきたのでpytestを使うことにした。
ただ、ゼロから学ぶPythonにあるプロジェクト構成の通りに、(project)とtestsを分けた場合にうまく動かなかったので、動かし方を調べた。
(project)
├── (project)  ............ プログラムのソースコードディレクトリ
│  ├── __init__.py
│  └── *.py
└── tests  ................ 単体テストのソースコードディレクトリ
   ├── __init__.py
   └── *.py

環境

お試し用プロジェクト

下記のような構成のプロジェクトを作った。
data.pyでDataクラスを定義し、calc.pyでDataクラスを引数に渡して計算する関数がある。という構成である。
+---pyapp
       calc.py
       data.py
       __init__.py
       __main__.py

data.py
from typing import Self

class Data:
    def __init__(self, value: float) -> None:
        self.value = value
    
    def add(self, other: Self):
        val = self.value + other.value
        return self.__class__(val)
calc.py
from data import Data

def func(d1: Data, d2: Data) -> Data:
    return d1.add(d2)

pytest準備

まずpytestをインストールする。
$ pipenv install pytest
testsフォルダを作成し、test_calc.pyを作る。
+---pyapp
|       calc.py
|       data.py
|       __init__.py
|       __main__.py
|
\---tests
        test_calc.py
        __init__.py
from pyapp.data import Data
from pyapp.calc import func

def test_calc1():
    d1 = Data(1)
    d2 = Data(2)
    d3 = func(d1, d2)
    assert d3.value == 3
VSコード上のTesting(フラスコのアイコン)をクリックすると図のようなwindowが表示されるので、Configure Python Test をクリックする。
pytestを選択し、testsフォルダを選択すれば準備環境。

pytest実行

三角形のアイコンをクリックすれば実行できる。今回はエラー詳細も出したいので虫アイコンの方を押して、Debug Testを実行する。

分析

data.pyをこのようにDataクラスを読み込んで型アノテーションしないように書き換えると動く。
def func(d1, d2):
    return d1.add(d2)
要するに、
  • test_calc.pyからpyapp.calcの読み込みはできている。
  • pyapp.calcを読み込む際に、その先のdataを読み込めていない。
ことがわかり、pathの問題であることがわかる。

解決方法(pathの設定)

二つやり方がある。
  1. conftest.pyで指定する
  2. .envファイルを作る

1. conftest.pyで指定する。

conftest.pyをtests内に配置すると、そのディレクトリ内のテスト時に自動的に読み込まれる。
もともとはフィクスチャというテストの前後処理の仕組みの共通化するためにもの。
フィクスチャはテストの実行前後で行いたい前処理・後処理を記述するために使用する関数のことです。各テストで同じ前処理・後処理を行う必要がある場合に暗黙的にそれが実行できるようになります。
複数のファイルをまたいで共通のフィクスチャを使用したいこともあると思います。そのような時はフィクスチャを conftest.py というファイルに定義しましょう。conftest.py 内のフィクスチャは pytest によって自動的にインポートされ、conftest.py があるディレクトリ配下で暗黙的に参照できるようになります。
今回はtestsフォルダ直下にこのようなconftest.pyを作るとテストが動きます。
import sys 
import os

sys.path.append(os.path.abspath(os.path.dirname(os.path.abspath(__file__)) + "/../pyapp"))

2. .envファイルを作る

プロジェクト直下に.envファイルを作り、下記のように書きます。
PYTHONPATH=./pyapp
そしてVSCodeの設定で作った.envを指定すると、実行時に.envを参照してpyappを追加してくれます。

参考

Discussion

コメントにはログインが必要です。