web-dev-qa-db-ja.com

pythonで一時ファイルシステムを使用してos.walkをモックする方法は?

Os.walkを使用するコードをテストしようとしています。 os.walkが返すサンプル(空の)ファイルとディレクトリを入力できる一時的なメモリ内ファイルシステムを作成したいと思います。これにより、再帰をシミュレートするためにos.walk呼び出しをモックする複雑さが軽減されます。

具体的には、テストしたいコードは次のとおりです。

if recursive:
    log.debug("Recursively searching for files under %s" % path)

    for (dir_path, dirs, files) in os.walk(path):
        log.debug("Found %d files in %s: %s" % (len(files), path, files))
        for f in [os.path.join(dir_path, f) for f in files
                  if not re.search(exclude, f)]:
            yield f
else:
    log.debug("Non-recursively searching for files under %s" % path)

    for (dir_path, dirs, files) in os.walk(path):
        log.debug("Found %d files in %s: %s" % (len(files), path, files))
        for f in [os.path.join(dir_path, f) for f in files
                    if not re.search(exclude, f)]:
            yield f

これはPythonで可能ですか?

27
jbrown

いいえ。os.walk()は、os.listdir()os.path.islink()の助けを借りて、完全に os.path.isdir() を中心に構築されます。これらは本質的にシステムコールであるため、ファイルシステムをモックする必要がありますシステムレベルでFuseプラグイン を書きたくない限り、これは簡単にモックすることはできません。

os.walk()が返す必要があるのは、実際にはタプルのリストだけです。 dirsコンポーネントの操作をテストしていない限り、これ以上簡単なことはありません。

with mock.patch('os.walk') as mockwalk:
    mockwalk.return_value = [
        ('/foo', ('bar',), ('baz',)),
        ('/foo/bar', (), ('spam', 'eggs')),
    ]

これにより、次のディレクトリ構造が模倣されます。

/foo
 ├── baz
 └── bar 
     ├── spam
     └── eggs
39
Martijn Pieters