TEISHOTOKU-P
@TEISHOTOKU-P (低所得 -P)

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

Pytest os.mkdirs('パス', exist_ok=true)で何らかのエラーを起こさせたい。

解決したいこと

現在Pytestでos.mkdirs('パス', exist_ok=true)という記述をテストできず困っています。

困っている点

・exist_ok=trueというオプションを付けると、指定したパスのディレクトリが存在していてもエラーを吐かなず通ってしまう。
・作りたいフォルダを格納するディレクトリの名前を変更しても同じくエラーを吐かず通ってしまう。

try:
    os.mkdirs('パス', exist_ok=true)
except Exception:
    return

何か方法があれば教えていただきたいです。
モックで良い方法があるのかもしれませんが、モックが苦手で分からない状況です。

0

2Answer

os.makedirsをモックするのはどうでしょうか。より詳しい使い方は「python モック 例外」といったキーワードでググってください。

main.py
import os


def my_makedirs(path: str):
    os.makedirs(path, exist_ok=True)
test_main.py
from main import my_makedirs
from unittest.mock import patch


def test_my_makedirs():
    path = "/tmp/dir"
    # *path* が何だろうが、os.makedirsはFileExistsError例外を送出する
    with patch("os.makedirs", side_effect=FileExistsError()):
        my_makedirs(path)


def test_my_makedirs_with_expected_dir():
    expect_path = "/tmp/expect/dir"

    # *path* が *expect_path* と一致した場合のみ、FileExistsError例外を送出する
    def raise_with_expect_path(path: str, *args, **kargs):
        if path == expect_path:
            raise FileExistsError()
        else:
            raise Exception(f"os.makedirs was called with unexpected arguments")

    # *path_to_be_made* の内容を変えて結果を確認してください
    path_to_be_made = "/tmp/expect/dir"
    with patch("os.makedirs", side_effect=raise_with_expect_path):
        my_makedirs(path_to_be_made)

$ pytest test_main.py
0Like

Comments

  1. exists_ok=Trueとしているので、起こるとすればFileExistsErrorではなくOSErrorとかですかね。
  2. @TEISHOTOKU-P

    Questioner

    def test_my_makedirs():
    path = "/tmp/dir"
    # *path* が何だろうが、os.makedirsはFileExistsError例外を送出する
    with patch("os.makedirs", side_effect=FileExistsError()):
    my_makedirs(path)

    こちらでエラーを解消することができました。
    ありがとうございます。
    また、os.mkdirsではなくos.makedirsが正しかったです。申し訳ありません。

エラーを起こしたいだけであれば、同名のファイルを予め作っておけばFileExistsErrorを起こせます

In [1]: import os

In [2]: import pathlib

In [3]: pathlib.Path('dir').touch()

In [4]: os.makedirs('dir', exist_ok=True)
---------------------------------------------------------------------------
FileExistsError                           Traceback (most recent call last)
<ipython-input-5-36b0073d72b6> in <module>
----> 1 os.makedirs('dir', exist_ok=True)

/usr/local/Cellar/python@3.8/3.8.12/Frameworks/Python.framework/Versions/3.8/lib/python3.8/os.py in makedirs(name, mode, exist_ok)
    221             return
    222     try:
--> 223         mkdir(name, mode)
    224     except OSError:
    225         # Cannot rely on checking for EEXIST, since the operating system

FileExistsError: [Errno 17] File exists: 'dir'
0Like

Your answer might help someone💌