Pruebas unitarias argparse: suprimir el mensaje de ayuda

Estoy escribiendo casos de prueba para la implementación argparse. Tengo la intención de probar la característica ‘-h’. El siguiente código lo hace. Pero también produce el uso para el script. ¿Hay una manera de suprimir eso?

self.assertRaises(SystemExit, arg_parse_obj.parse_known_args, ['-h']) 

Además, ¿podemos verificar el número de excepción lanzado? Por ejemplo, ‘-h’ lanza SystemExit: 0 , mientras que los argumentos no válidos o insuficientes lanzan SystemExit: 2 . ¿Hay alguna forma de verificar el código numérico?

Al probar los códigos de excepción, use self.assertRaises() como administrador de contexto ; esto le da acceso a la excepción .code , lo que le permite probar el atributo .code :

 with self.assertRaises(SystemExit) as cm: arg_parse_obj.parse_known_args(['-h']) self.assertEqual(cm.exception.code, 0) 

Para ‘suprimir’ o probar la salida, tendrás que capturar sys.stdout o sys.stderr , dependiendo de la salida de argparse (el texto de ayuda va a stdout ). Podrías usar un administrador de contexto para eso:

 from contextlib import contextmanager from StringIO import StringIO @contextmanager def capture_sys_output(): capture_out, capture_err = StringIO(), StringIO() current_out, current_err = sys.stdout, sys.stderr try: sys.stdout, sys.stderr = capture_out, capture_err yield capture_out, capture_err finally: sys.stdout, sys.stderr = current_out, current_err 

y usar estos como:

 with self.assertRaises(SystemExit) as cm: with capture_sys_output() as (stdout, stderr): arg_parse_obj.parse_known_args(['-h']) self.assertEqual(cm.exception.code, 0) self.assertEqual(stderr.getvalue(), '') self.assertEqual(stdout.getvalue(), 'Some help value printed') 

Anidé los gestores de contexto aquí, pero en Python 2.7 y más recientes también puedes combinarlos en una línea; Sin embargo, esto tiende a ir más allá del límite de 79 caracteres recomendado en un apuro.

Mock podría hacer esto, permitiéndole la misma funcionalidad que la respuesta de Martijn Pieters, pero sin tener que escribir su propia función:

 from unittest.mock import MagicMock, patch argparse_mock = MagicMock() with patch('argparse.ArgumentParser._print_message', argparse_mock): with self.assertRaises(SystemExit) as cm: arg_parse_obj.parse_known_args(['-h']) 

El parche también funciona como decorador. Si tiene varias instancias en las que se debe suprimir la impresión argparse, puede hacerlo como decorador y evitar el uso de un montón de declaraciones anidadas.

Algunas variaciones en el uso de ['-h'] incluyen:

 parser.print_help() # formats the help, prints it and exits parser.format_help() # format the help without printing or exit parser.exit # can be modified to not exit, such as for a parser subclass parser.error # default print usage and call parser.exit 

Estos son parte de la API pública.

El archivo de prueba argparse ( test_argparse.py ) también da ideas sobre cómo probar cosas. Para muchas pruebas usa una subclase ArgumentParser que tiene su propio método de error .