devo patchare tre metodi (_send_reply
, _reset_watchdog
e _handle_set_watchdog
) con metodi finte prima di testare una chiamata a un quarto metodo (_handle_command
) in un test di unità di mine.modo preferito di patch diversi metodi in Python unit test
Guardando la documentazione per il pacchetto mock, ci sono alcuni modi che potrei andare a questo proposito:
Con patch.multiple
come decoratrice
@patch.multiple(MBG120Simulator,
_send_reply=DEFAULT,
_reset_watchdog=DEFAULT,
_handle_set_watchdog=DEFAULT,
autospec=True)
def test_handle_command_too_short_v1(self,
_send_reply,
_reset_watchdog,
_handle_set_watchdog):
simulator = MBG120Simulator()
simulator._handle_command('XA99')
_send_reply.assert_called_once_with(simulator, 'X?')
self.assertFalse(_reset_watchdog.called)
self.assertFalse(_handle_set_watchdog.called)
simulator.stop()
Con patch.multiple
come contesto direttore
def test_handle_command_too_short_v2(self):
simulator = MBG120Simulator()
with patch.multiple(simulator,
_send_reply=DEFAULT,
_reset_watchdog=DEFAULT,
_handle_set_watchdog=DEFAULT,
autospec=True) as mocks:
simulator._handle_command('XA99')
mocks['_send_reply'].assert_called_once_with('X?')
self.assertFalse(mocks['_reset_watchdog'].called)
self.assertFalse(mocks['_handle_set_watchdog'].called)
simulator.stop()
Con multipla patch.object
decoratorations
@patch.object(MBG120Simulator, '_send_reply', autospec=True)
@patch.object(MBG120Simulator, '_reset_watchdog', autospec=True)
@patch.object(MBG120Simulator, '_handle_set_watchdog', autospec=True)
def test_handle_command_too_short_v3(self,
_handle_set_watchdog_mock,
_reset_watchdog_mock,
_send_reply_mock):
simulator = MBG120Simulator()
simulator._handle_command('XA99')
_send_reply_mock.assert_called_once_with(simulator, 'X?')
self.assertFalse(_reset_watchdog_mock.called)
self.assertFalse(_handle_set_watchdog_mock.called)
simulator.stop()
metodi che sostituiscono manualmente utilizzando create_autospec
def test_handle_command_too_short_v4(self):
simulator = MBG120Simulator()
# Mock some methods.
simulator._send_reply = create_autospec(simulator._send_reply)
simulator._reset_watchdog = create_autospec(simulator._reset_watchdog)
simulator._handle_set_watchdog = create_autospec(simulator._handle_set_watchdog)
# Exercise.
simulator._handle_command('XA99')
# Check.
simulator._send_reply.assert_called_once_with('X?')
self.assertFalse(simulator._reset_watchdog.called)
self.assertFalse(simulator._handle_set_watchdog.called)
Personalmente penso che l'ultimo è più chiaro da leggere, e non si tradurrà in orribilmente lunghe file se il numero dei metodi derisi crescono. Evita anche di passare in simulator
come il primo argomento (self
) a assert_called_once_with
.
Ma non li trovo particolarmente belli. Soprattutto l'approccio multiplo patch.object
, che richiede un'accurata corrispondenza dell'ordine dei parametri con le decorazioni nidificate.
C'è qualche approccio che ho perso, o un modo per renderlo più leggibile? Che cosa fai quando hai bisogno di applicare più metodi all'istanza/classe sotto test?
Grazie mille per la risposta completa. In ordine: 1) Buon punto sul fatto che il mio caso è speciale (che ho accesso all'istanza et.c.). 2) Grazie per il consiglio su QUALSIASI. 3) Sì, forse sto esagerando con la fragilità dell'ordine delle argomentazioni quando uso i decoratori. 4) Domanda: Quindi '@patch ('package.module.Class.some_method', autospec = True)' è equivalente a '@ patch.object (package.module.Class, 'some_method', autospec = True)'? È carino, e se è così preferisco anche il tuo modo di farlo. ... – estan
... 5) sono un po 'titubante per usare '' setUp' e tearDown' come mi piace il mio test di essere completamente autonomo, nonostante sapessero che vorrà dire un po' di battitura. Ma questa è solo una preferenza personale. 6) .. e su quella nota, sì mi dispiace per aver fatto una domanda che ha solo risposte prevalentemente soggettive! 7) Prenderò in considerazione ciò che hai detto sul test dei metodi privati. Mi piace essere in grado di farlo facilmente con Python ed è importante che questo codice abbia una copertura della linea del 100%. Ma prenderò in considerazione la possibilità di suddividerli in collaboratori. La classe sotto test è abbastanza piccola però. Ancora una volta, grazie per l'ottima risposta. – estan
Gah. Scusa per la formattazione orribile. Non sono davvero amico della funzionalità dei commenti SO. Ad ogni modo, accettando la tua risposta in quanto è molto buona. – estan