Как вы пишете тесты для части argparse модуля python?

У меня есть модуль Python, который использует библиотеку argparse. Как написать тесты для этого раздела базы данных?

Ответ 1

Вы должны реорганизовать свой код и переместить синтаксический анализ на функцию:

def parse_args(args):
    parser = argparse.ArgumentParser(...)
    parser.add_argument...
    # ...Create your parser as you like...
    return parser.parse_args(args)

Затем в вашей функции main вы должны просто вызвать ее с помощью:

parser = parse_args(sys.argv[1:])

(где первый элемент sys.argv, который представляет имя script, удаляется, чтобы не отправлять его в качестве дополнительного коммутатора во время операции CLI.)

В ваших тестах вы можете вызвать функцию парсера с любым списком аргументов, с которым вы хотите протестировать:

def test_parser(self):
    parser = parse_args(['-l', '-m'])
    self.assertTrue(parser.long)
    # ...and so on.

Таким образом, вам никогда не придется выполнять код вашего приложения, чтобы проверить его.

Если вам нужно изменить и/или добавить параметры в свой синтаксический анализатор позже в приложении, создайте метод factory:

def create_parser():
    parser = argparse.ArgumentParser(...)
    parser.add_argument...
    # ...Create your parser as you like...
    return parser

Вы можете позже манипулировать им, если хотите, и тест может выглядеть так:

class ParserTest(unittest.TestCase):
    def setUp(self):
        self.parser = create_parser()

    def test_something(self):
        parsed = self.parser.parse_args(['--something', 'test'])
        self.assertEqual(parsed.something, 'test')

Ответ 2

"часть argparse" немного туманна, поэтому этот ответ фокусируется на одной части: методе parse_args. Это метод, который взаимодействует с вашей командной строкой и получает все переданные значения. В принципе, вы можете высмеивать, что возвращает parse_args, так что ему не нужно фактически получать значения из командной строки.

import argparse
import mock


@mock.patch('argparse.ArgumentParser.parse_args',
            return_value=argparse.Namespace(kwarg1=value, kwarg2=value))
def test_command(mock_args):
    pass

Вы должны включить все аргументы метода команды в Namespace, даже если они не переданы. Дайте этим аргументам значение None. (см. docs). Этот стиль полезен для быстрого выполнения тестирования для случаев, когда для каждого аргумента метода передаются разные значения. Если вы решите издеваться над Namespace для полной неопределенности argparse в своих тестах, убедитесь, что он ведет себя аналогично действительному классу Namespace.

Ответ 3

  • Заполните список ваших аргументов, используя sys.argv.append(), а затем вызовите parse(), проверьте результаты и повторите.
  • Вызов из пакета / bash файла с вашими флагами и флаг args dump.
  • Проведите анализ всех ваших аргументов в отдельном файле и в теге if __name__ == "__main__":, а затем дамп/оцените результаты, затем проверьте это из файла пакета /bash.

Ответ 4

Сделайте main() функцию argv в качестве аргумента, а не читать с sys.argv, как это будет по умолчанию:

# mymodule.py
import argparse
import sys


def main(args):
    parser = argparse.ArgumentParser()
    parser.add_argument('-a')
    process(**vars(parser.parse_args(args)))
    return 0


def process(a=None):
    pass

if __name__ == "__main__":
    sys.exit(main(sys.argv[1:]))

Затем вы можете нормально протестировать.

import mock

from mymodule import main


@mock.patch('mymodule.process')
def test_main(process):
    main([])
    process.assert_call_once_with(a=None)


@mock.patch('foo.process')
def test_main_a(process):
    main(['-a', '1'])
    process.assert_call_once_with(a='1')

Ответ 5

Простым способом тестирования синтаксического анализа является:

parser = ...
parser.add_argument('-a',type=int)
...
argv = '-a 1 foo'.split()  # or ['-a','1','foo']
args = parser.parse_args(argv)
assert(args.a == 1)
...

Другой способ - изменить sys.argv и вызвать args = parser.parse_args()

Существует множество примеров тестирования argparse в lib/test/test_argparse.py

Ответ 6

Я обнаружил, что самый простой способ, по крайней мере для меня, состоял в том, чтобы просто проверить sys.argv [0], поэтому посмотрите, был ли python запущен как python -m unittest и не разбирал ничего, если бы это было так.

import sys
import argparse

parser = argparse.ArgumentParser()

parser.add_argument('--outdir', help='Directory to output to', \
    default='out')
parser.add_argument('--file', help='Input file', \
    default='section')
parser.add_argument('--word', help='Word to look up')

if sys.argv[0] == 'python -m unittest':
    args = parser.parse_args([])
else:
    args = parser.parse_args()