python unittest для argparse

У меня есть функция внутри модуля, который создает argparse :

 def get_options(prog_version='1.0', prog_usage='', misc_opts=None): options = [] if misc_opts is None else misc_opts parser = ArgumentParser(usage=prog_usage) if prog_usage else ArgumentParser() parser.add_argument('-v', '--version', action='version', version='%(prog)s {}'.format(prog_version)) parser.add_argument('-c', '--config', dest='config', required=True, help='the path to the configuration file') for option in options: if 'option' in option and 'destination' in option: parser.add_argument(option['option'], dest=option.get('destination', ''), default=option.get('default', ''), help=option.get('description', ''), action=option.get('action', 'store')) return parser.parse_args() 

Образец myapp.py будет выглядеть следующим образом:

 my_options = [ { "option": "-s", "destination": "remote_host", "default": "127.0.0.1", "description": "The remote server name or IP address", "action": "store" }, ] # Get Command Line Options options = get_options(misc_opts=my_options) print options.config print options.remote_host 

и это будет называться как:

 $> python myapp.py -c config.yaml $> config.yaml 127.0.0.1 

Теперь я пытаюсь создать единичный тест для этой функции, но моя проблема в том, что я не могу передать параметры командной строки с помощью тестового кода.

 # mytest.py import unittest from mymodule import get_options class argParseTestCase(unittest.TestCase): def test_parser(self): options = get_options() # ...pass the command line arguments... self.assertEquals('config.yaml', options.config) # ofcourse this fails because I don't know how I will pass the command line arguments 

Моя проблема в том, что мне нужно передать аргументы командной строки get_options() но я не знаю, как это сделать правильно.

Ожидаемый правильный вызов: python mytest.py ( -c config.yaml должен быть передан внутри тестового кода.)

Что «работает» / не работает прямо сейчас:

  1. python mytest.py -c config.yaml также не работает. Возвращает AttributeError: 'module' object has no attribute 'config' поскольку он ожидает, что я вместо этого вызову argParseTestCase . Другими словами, python mytest.py -c argParseTestCase «работает», но, конечно, будет возвратом AssertionError: 'config.yaml' != 'argParseTestCase'
  2. python mytest.py -v для запуска модульного теста в подробном режиме также не работает. Он возвращает:

    test_parser ( main .argParseTestCase) … mytest.py 1.0 ОШИБКА ОШИБКИ: test_parser ( main .argParseTestCase)
    Traceback (последний последний вызов): Файл «tests / unit_tests / mytest.py», строка 376, в параметрах test_parser = get_options () Файл «/root/test/lib/python2.7/site-packages/mymodule.py» , строка 61, в get_options возвращает parser.parse_args ()
    Файл «/usr/local/lib/python2.7/argparse.py», строка 1701, в parse_args args, argv = self.parse_known_args (args, namespace)
    Файл «/usr/local/lib/python2.7/argparse.py», строка 1733, в пространстве имен parse_known_args, args = self._parse_known_args (args, namespace)
    Файл «/usr/local/lib/python2.7/argparse.py», строка 1939, в _parse_known_args start_index = consume_optional (start_index)
    Файл «/usr/local/lib/python2.7/argparse.py», строка 1879, в consume_optional take_action (action, args, option_string)
    Файл «/usr/local/lib/python2.7/argparse.py», строка 1807, в действии take_action (self, namespace, arguments_values, option_string)
    Файл «/usr/local/lib/python2.7/argparse.py», строка 1022, в вызове parser.exit (message = formatter.format_help ())
    Файл «/usr/local/lib/python2.7/argparse.py», строка 2362, в конце _sys.exit (status) SystemExit: 0

2 Solutions collect form web for “python unittest для argparse”

Я предпочитаю явно передавать аргументы вместо того, чтобы полагаться на глобально доступные атрибуты, такие как sys.argv (который parser.parse_args() делает внутренне). Таким образом, я обычно использую argparse , передавая список аргументов самостоятельно (to main() а затем get_options() и везде, где они вам нужны):

 def get_options(args, prog_version='1.0', prog_usage='', misc_opts=None): # ... return parser.parse_args(args) 

а затем передать аргументы

 def main(args): get_options(args) if __name__ == "__main__": main(sys.argv[1:]) 

таким образом я могу заменить и проверить любой список аргументов, которые мне нравятся

 options = get_options(['-c','config.yaml']) self.assertEquals('config.yaml', options.config) 

Ваш стек сообщений об ошибках трудно читать, поскольку он находится в кавычках, а не в коде. Но я думаю, что аргумент -v создает sys.exit . version похожа на help – она ​​должна отображать сообщение, а затем выйти. -v используется unittest , но также читается вашим парсером.

Существует модуль argparse argparse, test/test_argparse.py . Для этого вам может понадобиться установка Python для разработки. Некоторые тесты просты, другие используют специализированную структуру тестирования. Некоторые из этого специального кода создают аргументы так же, как и с options .

Это два специальных вопроса:

  • генерируя вход. parse_args использует sys.argv[1:] если его параметр argv не является None . Таким образом, вы можете протестировать парсер, либо изменив список sys.argv ( unittest уже использовал ваши значения в командной строке), либо передав аргумент argv=None в вашу функцию и на parse_args . Попытка сделать unittest предназначенную для кода unittest для работы с get_options , слишком сложна.

  • захват вывода, особенно sys.exit сгенерированный ошибками. Один из вариантов заключается в подклассе ArgumentParser и дает ему другую error и / или метод exit . Другим является завершение вызова функции в блоке try .

unittest принимает аргумент -c , но с другим синтаксисом и значением

  -c, --catch Catch control-C and display results 

и -v является verbose , а не version .

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

Это проверяет аргумент config (в отдельной форме файла)

 import unittest import sys #from mymodule import get_options def get_options(argv=None, prog_version='1.0', prog_usage='', misc_opts=None): # argv is optional test list; uses sys.argv[1:] is not provided from argparse import ArgumentParser options = [] if misc_opts is None else misc_opts parser = ArgumentParser(usage=prog_usage) if prog_usage else ArgumentParser() parser.add_argument('-v', '--version', action='version', version='%(prog)s {}'.format(prog_version)) parser.add_argument('-c', '--config', dest='config', help='the path to the configuration file') for option in options: if 'option' in option and 'destination' in option: parser.add_argument(option['option'], dest=option.get('destination', ''), default=option.get('default', ''), help=option.get('description', ''), action=option.get('action', 'store')) args = parser.parse_args(argv) print('args',args) return args class argParseTestCase(unittest.TestCase): def test_config(self): sys.argv[1:]=['-c','config.yaml'] options = get_options() self.assertEquals('config.yaml', options.config) def test_version(self): sys.argv[1:]=['-v'] with self.assertRaises(SystemExit): get_options() # testing version message requires redirecting stdout # similarly for a misc_opts test if __name__=='__main__': unittest.main() 
  • Доступ к атрибуту подтверждения для экземпляра mock
  • Python unittest - словарь со списками
  • Как организовать тест python таким образом, чтобы я мог запускать все тесты в одной команде?
  • Издевательская конструкция класса
  • Очередь задач работает с представлением, но UnknownQueueError при запуске от модульных тестов
  • Проверить формы django, поднятые ValidationError
  • Предоставление тестовых данных в python
  • Как может кусок кода python сказать, работает ли он под unittest
  • Python - лучший язык программирования в мире.