2010-05-11 12 views
11

Tengo un script que hace varias cosas y accede a los parámetros usando sys.argv pero cuando el script llega a la parte unittest del código dice que no hay módulo para esto. El script que tengo es:Problema con sys.argv [1] cuando el módulo unittest está en un 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 en la línea de comandos. El error que recibo es:

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

Si elimino el módulo unittest, funciona. Además, si elimino el registro testrunner y lo dejo en:

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

Esto todavía no funciona.

¿Alguien puede ayudar.

Gracias

Probé este truco pero todavía intenta leer el sys.argv.

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

He intentado esto con sólo argv pero todavía neumáticos para leer los parámetros extra.

+1

¿podría enviar el mensaje de error completo (con el seguimiento de la pila)? Nos dirá en qué línea se produjo 'AttributeError'. – unutbu

Respuesta

16

El problema es que unittest.main() quiere su precioso argv para su propio uso! Utiliza el argv que le da como parámetro de función o sys.argv si no le da argv explícitamente, e intenta cargar las pruebas denominadas los argumentos que usted da. En este caso, esto significa que está buscando, ya sea para un submódulo denominado Hello, una clase TestCase llamado Hello, un método de caso de prueba dentro de una clase de casos de prueba llamado Hello, o un objeto de llamada denominada Hello que devuelve una instancia TestCase o TestSuite, todo dentro de su módulo 'script'.

Hay varias maneras de solucionar este problema:

  • unittest.main() Bypass y llamar de nivel inferior unittest mismo funciona para configurar y ejecutar los casos de prueba que tiene en mente.
  • Elimine la dependencia de su código en sys.argv, y use el comportamiento unittest.main() para su ventaja. Si su módulo no debe ejecutarse independientemente excepto como prueba unitaria, esto probablemente tenga sentido, ya que las personas que llaman de su módulo pueden no estar esperando que lea de su argv!
  • Separe el código de prueba y la rutina principal en un módulo de prueba separado.Aún así, tendrás que averiguar cómo obtener la argv correcta en tu código desde el módulo de prueba.
  • Especifique argv=[sys.argv[0]] como argumento para unittest.main(); eso debería evitar que trate de leer el tuyo.
-1

Python le brinda toda la información que puede, y a menos que desee publicar toda la serie de cosas que está tratando de probar, solo podemos adivinar lo que está tratando de lograr. El error dice que no hay ningún atributo llamado "Hola", así que tal vez los módulos que intentas probar tengan esa variable, función u otra.

¿Hay alguna razón por la que no solo esté usando unittest.main()?

+2

En este particular código de código, intento pasar Hello in como parámetro que funcionará. Luego tengo una función que llama a una serie de prueba que está separada de las otras funciones. Pero cuando unittest y sys.argv están en el mismo script, hay un problema. Las pruebas que estoy realizando no importan porque funcionan, el problema es que cuando intento ingresar un parámetro en una función sin enlace la prueba unitaria y luego ejecuto la función unittest más abajo en el archivo, obtengo el error. La razón por la que estoy usando ese tipo de comando unitario es porque estoy llamando a un conjunto de pruebas específico. – chrissygormley

+0

Las pruebas de su unidad no deben tomar parámetros de la línea de comando. El marco de prueba unitario claramente usa sys.argv para sus propios objetivos, aunque puede haber una manera de anularlo (por ejemplo, tal vez haya un parámetro 'argv' para las llamadas test de la unidad, no lo sé de forma manual.) Si quiere parametrizar sus pruebas, para que pueda instanciarlas con diferentes conjuntos de datos, probablemente también debería hacerlo a través de "accesorios". Publicaré otra respuesta. –

1

En general, la idea detrás de las pruebas unitarias es que las pruebas se ejecutan sin un controlador externo. P.ej. no quiere depender de alguna entrada desde la línea de comando. La solución que está buscando puede ser mediante el uso de accesorios?

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

Si no necesita las características de línea de comandos del módulo unittest, puede hacer que el optparse y módulos unittest juegan bien juntos modificando sys.argv justo antes de llamar unittest.main()

probar este justo antes unittest.main() su llamada:

del sys.argv[1:] 

Esto elimina los argumentos de línea de comando antes de unittest los ve.

Si no está utilizando el módulo optparse, se puede hacer esto en su lugar:

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