2010-05-11 7 views
11

Ho uno script che fa varie cose e accede ai paramenter usando sys.argv ma quando lo script arriva alla parte più semplice del codice dice che non c'è modulo per questo. Lo script che ho è:Problema con sys.argv [1] quando il modulo unittest è in uno script

class MyScript(): 

    def __init__(self): 
     self.value = sys.argv[1] 

    def hello(self): 
     print self.value 

    def suite(self): 
     modules_to_test = ('external_sanity_onvif', 'starttest') 
     alltests = unittest.TestSuite() 
     for module in map(__import__, modules_to_test): 
      alltests.addTest(unittest.findTestCases(module)) 
     return alltests 


if __name__ == '__main__': 
    Run = MyScript() 
    Run.hello() 
    log_file = 'log_file.txt' 
    test_file = open(log_file, "w") 
    runner = unittest.TextTestRunner(test_file) 
    unittest.main(defaultTest='Run.suite', testRunner=runner) 

Say Entro ./script.py Hello nella riga di comando. L'errore che ottengo è:

AttributeError: 'module' object has no attribute 'Hello' 

Se rimuovo il modulo unittest, funziona. Anche se rimuovo il registro testrunner e lo lascio a:

unittest.main(defaultTest='Run.suite') 

Questo ancora non funziona.

Qualcuno può aiutare.

Grazie

Ho provato questo hack, ma cerca ancora di leggere il sys.argv.

project = sys.argv[4:] 
sys.argv = sys.argv[0:4] 

Ho provato questo con un solo argv ma ancora i pneumatici di leggere i parametri extra.

+1

Potrebbe inviare il messaggio di errore completo (con l'analisi dello stack)? Ci dirà su quale riga si è verificato l'errore "AttributeError". – unutbu

risposta

16

Il problema è che vuole il vostro unittest.main() argv prezioso per il proprio uso! Usa l'argv come parametro di funzione, oppure sys.argv se non lo si assegna esplicitamente e prova a caricare i test con gli argomenti che si danno. In questo caso, questo significa che è alla ricerca di un sottomodulo chiamato Hello, una classe TestCase nome Hello, un metodo di test case all'interno di una classe test case di nome Hello, o un oggetto richiamabile chiamato Hello che restituisce un'istanza TestCase o TestSuite, il tutto all'interno del vostro modulo 'script'.

Ci sono diversi modi per risolvere questo:

  • Bypass unittest.main() e call-livello inferiore unittest te funzioni per impostare ed eseguire i casi di test che avete in mente.
  • Rimuovere la dipendenza del codice su sys.argv e utilizzare il comportamento unittest.main() a proprio vantaggio. Se il tuo modulo non è pensato per essere eseguito indipendentemente eccetto come test di unità, questo probabilmente ha senso, poiché i chiamanti del tuo modulo potrebbero non aspettarti di leggere dal loro argv!
  • Separare il codice di test e la routine principale in un modulo di test separato.Dovresti ancora capire come ottenere il giusto argv nel tuo codice attraverso il modulo di test.
  • Specificare argv=[sys.argv[0]] come argomento su unittest.main(); questo dovrebbe impedirti di leggere il tuo.
-1

Python fornisce tutte le informazioni possibili e, a meno che non si desideri pubblicare l'intero set di cose che si sta tentando di testare, è possibile indovinare solo ciò che si sta tentando di realizzare. L'errore dice che non c'è un attributo chiamato "Ciao", quindi forse i moduli che stai cercando di testare dovrebbero avere una variabile, una funzione o altro.

C'è qualche ragione per cui non stai usando solo unittest.main()?

+2

In questo particolare codice di codice sto cercando di passare Hello in come parametro che funzionerà. Quindi ho una funzione che chiama una serie di test che è separata dalle altre funzioni. Ma quando unittest e sys.argv sono nello stesso script, c'è un problema. I test che sto facendo non contano mentre funzionano, il problema è che quando provo a inserire un parametro in una funzione senza collegamento l'unittest e poi eseguo la funzione unittest più avanti nel file, ottengo l'errore. Il motivo per cui sto usando quel tipo di comando unitario è che sto chiamando una specifica suite di test. – chrissygormley

+0

I test dell'unità non devono prendere parametri dalla riga di comando. Il framework unittest utilizza chiaramente sys.argv per i propri obiettivi, sebbene ci possa essere un modo per sovrascriverlo (ad esempio, forse c'è un parametro 'argv' per le chiamate unittest? Non so se è fuori mano.) Se si desidera parametrizzare i tuoi test, così puoi istanziarli con set di dati diversi, probabilmente dovresti farlo anche tramite "fixtures". Posterò un'altra risposta –

1

In generale, l'idea alla base del test dell'unità è che i test vengano eseguiti senza un driver esterno. Per esempio. non vuoi dipendere da qualche input dalla riga di comando. La soluzione che stai cercando potrebbe essere attraverso l'uso di Fixtures?

import sys 
import unittest 

class MyScript(unittest.TestCase): 
    def setUp(self): 
     self.value = "Default Value" 

    def setHello(self, value): 
     self.value = value 

    def hello(self): 
     return self.value 

class UserA(MyScript): 
    def setUp(self): 
     self.setHello("UserA") 

    def testMyName(self): 
     self.failUnlessEqual(self.hello(), "UserA") 

class UserB(MyScript): 
    def setUp(self): 
     self.setHello("UserB") 

    def testMyName(self): 
     self.failUnlessEqual(self.hello(), "UserB") 

if __name__ == '__main__': 
    unittest.main() 
6

Se non avete bisogno le caratteristiche della riga di comando del modulo unittest, si può fare l'optparse e moduli unittest giocano bene insieme modificando sys.argv poco prima di chiamare unittest.main()

Prova questa appena prima il vostro unittest.main() chiamata:

del sys.argv[1:] 

Ciò elimina i tuoi argomenti della riga di comando prima di unittest li vede.

Se non si utilizza il modulo optparse, si può fare questo, invece:

my_args = sys.argv[1:] 
del sys.argv[1:] 
# do_stuff(my_args) 
unittest.main()