2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

ディレクトリ構造をMappingとして読み取れるやつ作った

Last updated at Posted at 2021-07-26

ユニットテストを書くとき、ストレージへの書き出し状況が意図通りであるという点を見たい場合があります。
それを簡単にするために、ディレクトリツリーの現在の状況をMappingとして読み出せるクラスを作りました。ライブラリにしてPyPIに出すほどではない規模なのでここにコード書いちゃいますね。ご自由にお使いください。

これで、 assert PathMapping(tmp_dir) == {'xx': b'yyyyyy'} なんていう簡単な式でストレージ書き出しを検証できるようになります。パラメータ化テストならこの右辺をパラメータ化できるので複雑な書き出しがあるモジュールのテストでもパラメータ化していろんな動作条件での出力を簡潔な記述で網羅できるようになりますね。

class PathMapping(Mapping):
    """
    ディレクトリパスを再帰的なマッピングとして扱う
    (文字列をキーに、ディレクトリはマッピング、ファイルはbytes)
    例:
    my_home
    ├ foo
    │ └ bar.txt (内容は "some content")
    └ baz.txt (内容は "another content")
    というディレクトリ構造のとき、以下の等式が成立
    PathMapping(Path('my_home')) == {
        'foo': {
            'bar.txt: b'some content\n'
        },
        'baz.txt': b'another content\n' 
    }
    """
    def __init__(self, path: Path):
        self._path = path

    def __getitem__(self, k: str):
        child = (self._path / k)
        if child.is_dir():
            return PathMapping(child)
        elif child.is_file():
            return child.read_bytes()
        else:
            raise KeyError

    def __len__(self) -> int:
        return len(list(self._path.iterdir()))

    def __iter__(self) -> Iterator[str]:
        for child in self._path.iterdir():
            yield child.name

このクラスのオブジェクトが吐き出すkey-valueデータはオブジェクト生成時点のものではなく、今現在のディレクトリツリー状況です。
そのことがどう生きてくるかというと、pytestのこんなfixtureを作る場合です。

@fixture
def mock_なんかストレージに書き出すモジュール(monkeypatch):
    """
    このfixtureオブジェクトそのものをMappingとしてアクセスすると書き出し結果がみられます
    """
    with TemporaryDirectory as tmp_dir:
        ... # 「なんかストレージに書き出すモジュール」 が tmp_dir に書き出すように
        ... # monkeypatchでいろいろ乗っ取っている

        yield PathMapping(Path(tmp_dir))

こうしておくと、ユニットテスト本文側では

def test_XXX(mock_なんかストレージに書き出すモジュール):
    ... # ターゲットを呼び出している
    ... # ターゲットは「なんかストレージに書き出すモジュール」を叩いている

    # 検証:想定通り書き出されていること
    assert mock_なんかストレージに書き出すモジュール == {'xx': b'yyyyyy'}

と書けます。PathMappingオブジェクトを作った時点ではなく、assertのところまで来た時点でのディレクトリツリー状況が読み出せていますので、こういうことができます。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?