У меня есть модуль Python, который использует библиотеку argparse. Как написать тесты для этого раздела базы данных?
Как вы пишете тесты для части argparse модуля python?
Ответ 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()