Почему вы пытаетесь проверить inner_method
? В большинстве случаев вам следует тестировать только части вашего публичного API. outer_method
является частью общедоступного API A
, так что проверьте это. inner_method
- это деталь реализации, которая может измениться: что если вы решите переименовать ее? Что, если вы немного измените рефакторинг, не изменяя внешне видимое поведение outer_method
? Пользователи класса A
не имеют (простого) способа вызова inner_method
. Модульные тесты обычно предназначены только для тестирования вещей, которые могут вызывать пользователи вашего класса (я предполагаю, что они предназначены для модульных тестов, потому что интеграционные тесты такие гранулярные были бы странными - и тот же принцип по-прежнему в основном сохранялся).
Практически у вас возникнут проблемы с извлечением функций, определенных в области действия другой функции, по нескольким причинам, включая захват переменных. У вас нет возможности узнать, захватывает ли inner_method
только self
или outer_method
выполняет некоторую логику и вычисляет некоторые переменные, которые использует inner_method
. Например:
class A:
def outer_method():
b = 1
def inner_method():
return self.a + b
return inner_method()
Кроме того, вы можете иметь управляющие операторы вокруг определения функции, поэтому невозможно решить, какое определение используется, без выполнения outer_method
. Например:
import random
class A:
def outer_method():
if random.random() < 0.5:
def inner_method():
return self.a + 1
else:
def inner_method():
return self.a + 2
return inner_method()
Вы не можете извлечь inner_method
здесь, потому что их два, и вы не знаете, что на самом деле используется, пока не запустите outer_method
.
Итак, просто не проверяйте inner_method
.
Если inner_method
действительно достаточно сложный, чтобы вы хотели протестировать его изолированно (и если вы делаете это, в принципиальном тестировании сказано, что вы должны смоделировать его использование, например, его использование в outer_method
), тогда просто сделайте его метод private-ish для A
:
class A:
def _inner_method(self):
return self.a + 1
def outer_method(self):
return self._inner_method()
Принципиальное тестирование говорит, что вам действительно не следует тестировать методы подчеркивания, но иногда это необходимо. Поступая таким образом, вы можете проверить _inner_method
так же, как и любой другой метод. Затем, при тестировании outer_method
, вы можете выполнить макет, выполнив a._inner_method = Mock()
(где a
- тестируемый объект A
).
Также используйте class A
. Паренсы не нужны, если у вас нет родительских классов.