16
5

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.

[Python] pytest mocker.patchがやっと動いたので、わかったことを勢いだけで書いておく

Posted at

Pythonのimportは、自名前空間に名前を導入するものだと、頭ではわかっていました。
それがやっと実地でもわかるようになりましたので、忘れないように書いておきます。すごい勢いで。

ファイル構成

このようなファイル構成になっています。
ex_mockモジュールの下に、ExMockクラスやその他のクラスがあります。

.
├── README.md
├── ex_mock
│   ├── __init__.py
│   ├── __main__.py
│   ├── creator.py
│   ├── exmock.py
│   ├── greeter.py
│   └── outputter.py
├── poetry.lock
├── pyproject.toml
└── tests
    ├── __init__.py
    ├── test_ex_mock.py
    ├── test_exmock.py
    └── test_greeter.py

テスト対象

テスト対象のクラスです。
コンストラクタのなかで、GreeterクラスとOutputterクラスをインスタンス化しています。

exmock.py
from ex_mock.outputter import Outputter
from ex_mock.greeter import Greeter


class ExMock:
    def __init__(self):
        self.__greeter = Greeter('Hello', Outputter())

    def exec(self, name):
        self.__greeter.greet(name)

テストクラス

テストクラスです。
ExMockをインスタンス化し、GreeterクラスとOutputterクラスが呼ばれていることをテストしています。

test_exmock.py
from ex_mock.exmock import ExMock


class TestExmock:
    def test_init(self, mocker):
        # Given
        outputter = mocker.patch('ex_mock.exmock.Outputter')
        greeter = mocker.patch('ex_mock.exmock.Greeter')

        # When
        instance = ExMock()

        # Then
        outputter.assert_called_once()
        greeter.assert_called_once()

試したこと

mocker.patchの書き方を色々試しました。

NGなパターン 1

実際にあるクラス名にしました。

outputter = mocker.patch('ex_mock.outputter.Outputter')

モックは作成されましたが、assert_called_once()で失敗しました。

NGなパターン 2

それではと、モジュール名+クラス名にしました。

outputter = mocker.patch('ex_mock.Outputter')

モック作成時に、そんなもん存在しないぜとエラーになりました。

NGなパターン 3

クラス名だけにしてみました。

outputter = mocker.patch('Outputter')

ターゲットパス名がよろしくないぜとエラーになりました。

NGなパターン 4

パスにしてみました。

outputter = mocker.patch('.Outputter')

モジュール名が空だとエラーになりました。

OKなパターン

モジュール名 + importが書いてあるファイル名 + クラス名にしました。

outputter = mocker.patch('ex_mock.exmock.Outputter')

うまくいきました。

わかったこと

Pythonのimportは、名前を導入するものだということです。

テスト対象クラスにある下記importは、モジュール名+ファイル名であるところのex_mock.exmockOutputterという名前を導入しています。

exmock.py
from ex_mock.outputter import Outputter

したがって、テストクラスの中ではex_mock.exmock.Outputterという名前で参照することになるのです。

ということは?

もしかして、importの書き方によって、mocker.patchの書き方も変わる?

以上です

勢いだけでお届けしました。
Pythonを知っている人にとっては、常識的な話なんでしょうか?
プログラムの中から自分自身の構文木をいじれる言語っておもしろいですね。

ソースコード

ソース全体は github に置いてあります。何かの参考になれば。

16
5
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
16
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?