I knew in my head that Python's import
introduces names into my namespace.
I've finally come to understand it in practice, so I'll write it down so I don't forget it. With great momentum.
The file structure is like this. Under the ex_mock module are the ExMock class and other classes.
.
├── 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
The class to be tested.
In the constructor, we instantiate the Greeter
and Outputter
classes.
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)
This is a test class.
We instantiate ExMock
and test that the Greeter
and Outputter
classes are called.
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()
I tried various ways to write mocker.patch
.
I made it an actual class name.
outputter = mocker.patch('ex_mock.outputter.Outputter')
The mock was created but failed with assert_called_once ()
.
Then, I made the module name + class name.
outputter = mocker.patch('ex_mock.Outputter')
When creating a mock, I got an error saying that it doesn't exist.
I tried only the class name.
outputter = mocker.patch('Outputter')
I got an error saying that the target path name is not correct.
I tried to make it a pass.
outputter = mocker.patch('.Outputter')
An error occurred if the module name was empty.
Module name + file name with import + class name.
outputter = mocker.patch('ex_mock.exmock.Outputter')
It went well.
Python's import
means that it introduces a name.
The following import
in the test target class introduces the name Outputter
to ex_mock.exmock
, which is the module name + file name.
exmock.py
from ex_mock.outputter import Outputter
Therefore, in the test class, it will be referred to by the name ex_mock.exmock.Outputter
.
Maybe the way to write mocker.patch
changes depending on how to write import
?
Delivered with just momentum. Is it common sense for anyone who knows Python? It's interesting to have a language in which you can play with your own syntax tree from within a program.
The entire source is on github. I hope it helps.
https://github.com/sengokyu/python-pytest-mock
Recommended Posts