Immagina un programma simile a questo in Python:
import subprocess
class Example():
_cmd_args = (['ls', '-a', '/usr/bin/'], ['ls', '-al', '/usr/local/bin/'])
_default_args = 0
def init(self):
pass
def run_ls_command(self):
p = subprocess.Popen(self.get_command(), stdout=subprocess.PIPE)
out, err = p.communicate()
return err
def get_command(self):
return self._cmd_args[self._default_args]
def set_args(self, args):
self._default_args = args
def do_magical_stuff(self):
#do some stuff
self._default_args = 0
self.run_ls_command()
Questo è un semplice esempio - ma immagina un programma in cui le "interazioni" primarie saranno eseguite eseguendo i comandi attraverso il sottoprocesso contro il sistema operativo host.
I comandi e gli argomenti specifici verranno creati come risultato di una varietà di altre configurazioni e dello stato del programma in un dato momento.
Il codice sopra riportato è orribilmente non verificabile.
Sembra che potrebbe essere meglio progettarlo in modo tale da avere oggetti come:
class MyArgs():
def __init__(self, _cmd, _cmd_args, _cmd_path):
self.cmd = _cmd
self.cmd_args = _cmd_args
self.cmd_path = _cmd_path
#more manipulation methods
def get_command(self):
return ([self.cmd, self.cmd_args, self.cmd_path])
e
class Example():
args = MyArgs()
def __init__(self):
pass
def run_ls_command(self):
print self.get_command()
p = subprocess.Popen(self.get_command(), stdout=subprocess.PIPE)
out, err = p.communicate()
return err
def set_args(self, c, a, p):
#this would be more complicated logic in future and likely not just one method
self.args.set_args(c,a,p)
def get_command(self):
return self.args.get_command()
Sarei quindi in grado di verificare che MyArgs.get_command()
funzioni correttamente, direttamente sulla classe stessa, per i suoi input dati (specialmente perché dubito che stia costruendo un singolo comando "imposta tutte le variabili").
Questo mi permetterebbe di modificare i miei test rispetto a Example
per testare principalmente cosa Example.get_command()
restituisce qualunque altra manipolazione possa accadere ad Esempio.
Questo non è ancora bello per me, dal momento che sto testando quali dovrebbero essere i membri privati - a parte il test, get_command
dovrebbe essere privato.
Intendo principalmente provare che i comandi corretti sono attivati, non se vengono eseguiti correttamente. Quindi, per esempio, se un utente passa in ['ls', '-a', '/a/dir/that/does/not/exist']
non mi interessa a questo punto che il ls
fallirà - Voglio convalidare il comando risultante (in realtà l'esecuzione dei comandi richiederà più tempo di quello che voglio fare per l'unità test suite). Sapendo in questo caso che il Popen
tentato ls -a /a/dir/that/does/not/exist
è sufficiente.
C'è un modo migliore per progettare questa architettura per facilitare la testabilità?