python 모듈의 argparse 부분에 대한 테스트는 어떻게 작성합니까?
argparse 라이브러리를 사용하는 Python 모듈을 가지고 있습니다.코드 베이스의 해당 섹션에 대한 테스트는 어떻게 작성해야 합니까?
코드를 리팩터링하고 파싱을 함수로 이동해야 합니다.
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
스크립트명을 나타내는 것은, CLI 조작중에 추가 스위치로서 송신하지 않기 위해서 삭제됩니다).
그런 다음 테스트하는 인수 목록을 사용하여 파서 함수를 호출할 수 있습니다.
def test_parser(self):
parser = parse_args(['-l', '-m'])
self.assertTrue(parser.long)
# ...and so on.
이렇게 하면 파서를 테스트하기 위해 애플리케이션 코드를 실행할 필요가 없습니다.
나중에 응용 프로그램에서 파서를 변경하거나 옵션을 추가해야 할 경우 공장 출하 시 메서드를 만듭니다.
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')
"parse partes parts"는 약간 애매하기 때문에 이 답변은 한 부분에 초점을 맞추고 있습니다.parse_args
방법.이는 명령줄과 상호 작용하여 전달된 모든 값을 가져오는 방법입니다.기본적으로, 당신은 무엇을 조롱할 수 있다.parse_args
명령줄에서 실제로 값을 가져올 필요가 없도록 를 반환합니다.그mock
python 버전 2.6-3.2의 경우 pip을 통해 패키지를 설치할 수 있습니다.표준 라이브러리의 일부입니다.unittest.mock
버전 3.3 이후입니다.
import argparse
try:
from unittest import mock # python 3.3+
except ImportError:
import mock # python 2.6-3.2
@mock.patch('argparse.ArgumentParser.parse_args',
return_value=argparse.Namespace(kwarg1=value, kwarg2=value))
def test_command(mock_args):
pass
명령어 메서드의 arg를 모두 포함해야 합니다.Namespace
통과되지 못하더라도요이 args에 값을 부여합니다.None
. (문서 참조)이 스타일은 메서드 인수마다 다른 값이 전달되는 경우 신속하게 테스트를 수행할 때 유용합니다.조롱하고 싶다면Namespace
테스트에 대한 완전한 argparse 비의존성을 위해 실제와 동일하게 동작하는지 확인합니다.Namespace
학급.
argparse 라이브러리의 첫 번째 스니펫을 사용하는 예를 다음에 나타냅니다.
# test_mock_argparse.py
import argparse
try:
from unittest import mock # python 3.3+
except ImportError:
import mock # python 2.6-3.2
def main():
parser = argparse.ArgumentParser(description='Process some integers.')
parser.add_argument('integers', metavar='N', type=int, nargs='+',
help='an integer for the accumulator')
parser.add_argument('--sum', dest='accumulate', action='store_const',
const=sum, default=max,
help='sum the integers (default: find the max)')
args = parser.parse_args()
print(args) # NOTE: this is how you would check what the kwargs are if you're unsure
return args.accumulate(args.integers)
@mock.patch('argparse.ArgumentParser.parse_args',
return_value=argparse.Namespace(accumulate=sum, integers=[1,2,3]))
def test_command(mock_args):
res = main()
assert res == 6, "1 + 2 + 3 = 6"
if __name__ == "__main__":
print(main())
를 만듭니다.main()
함수 테이크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')
저는 원래 서빙 스크립트를 수정하고 싶지 않아서 그냥 조롱했어요.sys.argv
아르파르세로 나누다
from unittest.mock import patch
with patch('argparse._sys.argv', ['python', 'serve.py']):
... # your test code here
argparse 구현이 변경되지만 빠른 테스트스크립트에 충분할 경우 이 문제는 해결됩니다.어쨌든 테스트 대본에서는 특정성보다 감성이 훨씬 더 중요하다.
- 하려면 arg를 합니다.
sys.argv.append()
에 전화해요.parse()
이치노 - 플래그와 덤프 args 플래그가 있는 배치/배시 파일에서 호출합니다.
- 은 모두 .
if __name__ == "__main__":
콜 해석과 덤프/다운로드 결과를 배치/다운로드 파일에서 테스트합니다.
parse_args
SystemExit
두 가지를 수 .
import contextlib
import io
import sys
@contextlib.contextmanager
def captured_output():
new_out, new_err = io.StringIO(), io.StringIO()
old_out, old_err = sys.stdout, sys.stderr
try:
sys.stdout, sys.stderr = new_out, new_err
yield sys.stdout, sys.stderr
finally:
sys.stdout, sys.stderr = old_out, old_err
def validate_args(args):
with captured_output() as (out, err):
try:
parser.parse_args(args)
return True
except SystemExit as e:
return False
합니다(stderr를 사용).err.seek(0); err.read()
하지만 일반적으로 이러한 세분화는 필요하지 않습니다.
이제 또는 원하는 테스트를 사용할 수 있습니다.
assertTrue(validate_args(["-l", "-m"]))
, 다른 에러를 .SystemExit
def validate_args(args):
with captured_output() as (out, err):
try:
return parser.parse_args(args)
except SystemExit as e:
err.seek(0)
raise argparse.ArgumentError(err.read())
파서를 테스트하는 간단한 방법은 다음과 같습니다.
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
에서 할 때argparse.ArgumentParser.parse_args
함수에 , 는 가끔 떤떤함, 는는 a a를 사용한다.namedtuple
실험용 논거를 조롱하기 위해.
import unittest
from collections import namedtuple
from my_module import main
class TestMyModule(TestCase):
args_tuple = namedtuple('args', 'arg1 arg2 arg3 arg4')
def test_arg1(self):
args = TestMyModule.args_tuple("age > 85", None, None, None)
res = main(args)
assert res == ["55289-0524", "00591-3496"], 'arg1 failed'
def test_arg2(self):
args = TestMyModule.args_tuple(None, [42, 69], None, None)
res = main(args)
assert res == [], 'arg2 failed'
if __name__ == '__main__':
unittest.main()
명령어 출력이 아닌 CLI(커맨드 라인 인터페이스) 테스트용으로 다음과 같은 작업을 수행했습니다.
import pytest
from argparse import ArgumentParser, _StoreAction
ap = ArgumentParser(prog="cli")
ap.add_argument("cmd", choices=("spam", "ham"))
ap.add_argument("-a", "--arg", type=str, nargs="?", default=None, const=None)
...
def test_parser():
assert isinstance(ap, ArgumentParser)
assert isinstance(ap, list)
args = {_.dest: _ for _ in ap._actions if isinstance(_, _StoreAction)}
assert args.keys() == {"cmd", "arg"}
assert args["cmd"] == ("spam", "ham")
assert args["arg"].type == str
assert args["arg"].nargs == "?"
...
언급URL : https://stackoverflow.com/questions/18160078/how-do-you-write-tests-for-the-argparse-portion-of-a-python-module
'source' 카테고리의 다른 글
사전 매핑 반전/반전 (0) | 2022.11.08 |
---|---|
URL을 완료하기 위한 HttpServletRequest (0) | 2022.11.08 |
403 오류 페이지를 에뮬레이트합니다. (0) | 2022.11.08 |
PHP - 어레이 값의 키 이름 가져오기 (0) | 2022.11.08 |
선택 상자의 모든 옵션을 제거한 다음 하나의 옵션을 추가하고 jQuery를 사용하여 선택하려면 어떻게 해야 합니까? (0) | 2022.11.08 |