2009-06-22 17 views
37

Tengo un módulo que importa unittest y tiene algunos TestCases. Me gustaría para aceptar algunas opciones de línea de comando (por ejemplo a continuación, el nombre de un archivo de datos), pero cuando intento pasar la opción obtengo el mensaje "opción -i no reconocida". ¿Es posible tener opciones de prueba unittest + para la aplicación (nota: estoy usando optparse para manejar las opciones)? Gracias.python, unittest: hay una manera de pasar opciones de línea de comandos a la aplicación

$ python test_app_data.py -i data_1.txt 

option -i not recognized 

=====================

seguimiento: se trata de una implementación de la solución sugerida:

import cfg_master #has the optparse option-handling code 

... 

if __name__ == '__main__':  
    #add you app's options here... 
    options_tpl = ('-i', '--in_dir', '-o', '--out_dir') 
    del_lst = [] 
    for i,option in enumerate(sys.argv): 
     if option in options_tpl: 
      del_lst.append(i) 
      del_lst.append(i+1) 

    del_lst.reverse() 
    for i in del_lst: 
     del sys.argv[i] 

    unittest.main() 
+0

En términos generales, sí. En este caso, la respuesta parece depender en gran medida de los detalles que no haya proporcionado. –

+0

@jd. Su "seguimiento" debe publicarse como respuesta; su pregunta debe contener solo la ... bien ... pregunta. – user1251007

Respuesta

45

Sobre la base de la respuesta de Alex, en realidad es bastante fácil de hacer usando argparse:

if __name__ == '__main__': 
    parser = argparse.ArgumentParser() 
    parser.add_argument('--input', default='My Input') 
    parser.add_argument('filename', default='some_file.txt') 
    parser.add_argument('unittest_args', nargs='*') 

    args = parser.parse_args() 
    # TODO: Go do something with args.input and args.filename 

    # Now set the sys.argv to the unittest_args (leaving sys.argv[0] alone) 
    sys.argv[1:] = args.unittest_args 
    unittest.main() 

no he probado todas las banderas se puede pasar a unittest para ver si funcionan o no, pero al pasar la prueba nombres en funciona, por ejemplo:

python test.py --input=foo data.txt MyTest 

ejecuta MyTest con foo y data.txt.

+3

¡Agradable! Aún mejor, 'unittest.main()' acepta un parámetro argv para que no tenga que meterse con el sys.argv global, p. Ej. como ese: 'unit_argv = [sys.argv [0]] + args.unittest_args; unittest.main (argv = unit_argv) ' – wutz

+3

Puede usar' .parse_known_args() 'en su lugar y no necesita usar una opción' nargs = '*' '; ver [Python: ejecutar un test.TestCase unittest sin llamar a unittest.main()?] (http://stackoverflow.com/a/17259773) para mi versión. –

+0

Relacioné esta respuesta con la pregunta a la que hacía referencia @MartijnPieters, porque el enfoque me atraía. Sin embargo, cuando implementé esta respuesta no funcionó para mí al pasar banderas (--failfast y --catch), así que volví a la respuesta de Martijn. –

31

En su sección if __name__ == '__main__':, que no nos está mostrando, que necesitará para optparse y luego del sys.argv[1:] antes de pasar el control a unittest código, por lo que este último código no trata de interpretar las opciones de línea de comandos de nuevo cuando tu Ya has tratado con ellos. (Es un poco más difícil tener algunas opciones propias y que también se transfieren a unittest, aunque se puede hacer si tiene necesidades tan complejas).

+0

genial, gracias; solo para confirmar: primero, permitir que optparse maneje las opciones de la aplicación (posiblemente múltiples y variables), luego eliminarlas de sys.argv, y finalmente permitir que unittest se haga cargo. –

+0

@jd sí, esa es la esencia de eso! –

+0

Brillante, gracias Alex! No pude resolver esto: P – Skilldrick

-7

No debe tomar argumentos y opciones para ejecutar pruebas de unidad, ya que las hace ejecutar en condiciones diferentes y menos predecibles de esta manera. Debería averiguar por qué necesita ejecutar pruebas con diferentes datos y hacer que el conjunto de pruebas sea lo suficientemente completo como para cubrir el terreno de todos los conjuntos de datos sin que se ejecute de manera diferente cada vez.

+0

recibo informes de datos semanales (archivos); Me gustaría alimentar estos nuevos informes a los unittest, antes de generar informes públicos. Si por alguna razón la estructura o el tipo de datos ha cambiado (por ejemplo, se ha agregado un nuevo campo de columna, se ha cambiado un rango de datos y se ha descubierto un error) me gustaría verlos con las pruebas. Espero que esto tenga sentido. –

+2

seguro, pero esa es la validación de datos, no la prueba unitaria. – ironfroggy

+2

¿Qué tal para el salto de prueba condicional?Ejecuto todos mis casos de prueba haciendo el descubrimiento de prueba de unittest, pero sería bueno poder tener anotaciones en ciertas pruebas como @skipUnless ('- full' en sys.argv) para que pueda tener una línea de comando fácil de ejecutar todas las pruebas, o solo algunas. –

1

Para pequeñas aplicaciones independientes, utilizo una opción centinela inicial (-t) y llamo unittest.main() antes de llamar argparse.ArgumentParser()

if __name__ == "__main__": 
    if len(sys.argv) > 1 and sys.argv[1] in ["-t", "--test"]: 
     del(sys.argv[1]) 
     sys.exit(unittest.main()) # pass sys.argv[ 

    p = argparse.ArgumentParser() 
    . . . 
Cuestiones relacionadas