Considera un modulo con una funzione "pubblica" simile a questa:
def func(arg):
val = _generate_something(arg)
_do_something(val)
Come puoi vedere questa è una 'funzione del vuoto'. La sua logica di base è in _generate_something
.
Voglio scrivere test unitari per questa funzione. Posso pensare a diversi approcci per farlo. Mi piacerebbe sapere qual è il migliore, sia in termini di pratiche di programmazione generale che di best practice in Python.
Essenzialmente questa domanda riguarda il modo Pythonico di prendere in giro una funzione privata (denaro che si sta rammendo? Iniezione della funzione? Iniezione di un oggetto? Ecc.)
Opzione A
Nel test monkeypatch _do_something
(che è una funzione 'privata' del modulo), così posso verificare che riceva un buon valore.
Opzione B
Inietti _do_something
come argomento a func
, in questo modo:
def func(arg, do_something=None):
do_something = do_something or _do_something # in production use default
val = _generate_something(arg)
do_something(val)
Poi nel mio do_something
mock posso controllare di aver ricevuto il valore corretto.
Opzione C
Avere func
essere un metodo di una classe, e avere quella classe prendere do_something
come argomento a __init__
:
class Something(object):
def __init__(self, do_something=None):
self._do_something = do_something or _production_default
def func(self, arg):
val = self._generate_something(arg)
self.do_something(val)
# ... omitted for brevity ...
Opzione D
Mi piace l'opzione B o C, ma do_something
è iniettato come un oggetto 'pieno', non una funzione nuda. Ad esempio:
def func(arg, something_doer=None):
something_doer = something_doer or _something_doer # in production use default
val = _generate_something(arg)
something_doer.do_something(val)
Come ho detto, mi piacerebbe sapere quale sia l'opzione migliore, anche per quanto riguarda "Pythonicness". Ad esempio, è 'accettabile' in Python per deridere le funzioni nude (piuttosto che gli oggetti che le contengono)?