如何在单元测试期间测试所需的 argparse 参数?
How to test required argparse arguments during unittests?
我正在为 argparser 做 TDD 测试。如何使用选项 required 测试参数?我需要测试所有选项,例如:
- 参数太多,
- 没有给出参数,
- 给出了错误的参数。
我可以引发 SystemExit,但这并不是我真正需要的:
def test_no_arguments(self):
with patch.object(sys, 'exit') as mock_method:
self.parser.parse_arguments()
self.assertTrue(mock_method.called)
但是,如果不引发系统退出,我总是会遇到这样的错误:
zbx-check-mount.py
class CommandLine:
def __init__(self):
self.args_parser = argparse.ArgumentParser(description="Monitoring mounted filesystems",
formatter_class=argparse.RawTextHelpFormatter)
self.parsed_args = None
self.add_arguments()
def add_arguments(self):
"""
Add arguments to parser.
"""
try:
self.args_parser._action_groups.pop() # pylint: disable=protected-access
required = self.args_parser.add_argument_group('required arguments')
required.add_argument('--fs_name', required=True, help='Given filesystem')
except argparse.ArgumentError as err:
log.error('argparse.ArgumentError: %s', err)
sys.exit(1)
def parse_arguments(self, args=None):
"""
Parse added arguments. Then run private method to return values
"""
self.parsed_args = self.args_parser.parse_args()
return self.parsed_args.fs_name,
测试
from pyfakefs.fake_filesystem_unittest import TestCase
import os
import sys
try:
from StringIO import StringIO
except ImportError:
from io import StringIO
if sys.version_info[0] == 3:
from unittest.mock import MagicMock, patch
else:
from mock import MagicMock, patch
sys.path.extend([os.path.join(os.path.dirname(os.path.abspath(__file__)),'..','..', "bin")])
module_name = __import__('zbx-check-mount')
class TestCommandLine(TestCase):
def setUp(self):
"""
Method called to prepare the test fixture. This is called immediately before calling the test method
"""
self.parser = module_name.CommandLine()
def test_no_arguments(self):
opts = self.parser.parse_arguments([])
assert opts.fs_name
def tearDown(self):
"""
Method called immediately after the test method has been called and the result recorded.
"""
pass
如何避免这种情况并测试其他选项?
如果我正确地解释了你的症状,那么你在测试工具中遇到了问题,因为你的猴子修补了 sys.exit
的实现,实际上 returns,argparse 库没有预料到这一点。
引入引发异常的 side_effect,然后您可以在单元测试中捕获并验证该异常,这可能足以解决问题。
在 def parse_arguments(self, args=None):
中,您应该将 args
传递给解析器,如:
self.args_parser.parse_args(args)
parse_args()
解析 sys.argv[1:]
,或者如果给定的参数是 None
。否则它会解析提供的列表。
在 python
的完整分发版中,有一个 argparse
(test_argparse.py
) 的单元测试文件。有点复杂,定义了一个ArgumentParser
的子类,用于捕获错误和重定向错误信息。
测试 argparse
是棘手的,因为它会查看 sys.argv
,unittest
脚本也使用。它通常会尝试在出现错误时退出。这已经在许多 SO 问题中进行了讨论。
我正在为 argparser 做 TDD 测试。如何使用选项 required 测试参数?我需要测试所有选项,例如:
- 参数太多,
- 没有给出参数,
- 给出了错误的参数。
我可以引发 SystemExit,但这并不是我真正需要的:
def test_no_arguments(self):
with patch.object(sys, 'exit') as mock_method:
self.parser.parse_arguments()
self.assertTrue(mock_method.called)
但是,如果不引发系统退出,我总是会遇到这样的错误:
zbx-check-mount.py
class CommandLine:
def __init__(self):
self.args_parser = argparse.ArgumentParser(description="Monitoring mounted filesystems",
formatter_class=argparse.RawTextHelpFormatter)
self.parsed_args = None
self.add_arguments()
def add_arguments(self):
"""
Add arguments to parser.
"""
try:
self.args_parser._action_groups.pop() # pylint: disable=protected-access
required = self.args_parser.add_argument_group('required arguments')
required.add_argument('--fs_name', required=True, help='Given filesystem')
except argparse.ArgumentError as err:
log.error('argparse.ArgumentError: %s', err)
sys.exit(1)
def parse_arguments(self, args=None):
"""
Parse added arguments. Then run private method to return values
"""
self.parsed_args = self.args_parser.parse_args()
return self.parsed_args.fs_name,
测试
from pyfakefs.fake_filesystem_unittest import TestCase
import os
import sys
try:
from StringIO import StringIO
except ImportError:
from io import StringIO
if sys.version_info[0] == 3:
from unittest.mock import MagicMock, patch
else:
from mock import MagicMock, patch
sys.path.extend([os.path.join(os.path.dirname(os.path.abspath(__file__)),'..','..', "bin")])
module_name = __import__('zbx-check-mount')
class TestCommandLine(TestCase):
def setUp(self):
"""
Method called to prepare the test fixture. This is called immediately before calling the test method
"""
self.parser = module_name.CommandLine()
def test_no_arguments(self):
opts = self.parser.parse_arguments([])
assert opts.fs_name
def tearDown(self):
"""
Method called immediately after the test method has been called and the result recorded.
"""
pass
如何避免这种情况并测试其他选项?
如果我正确地解释了你的症状,那么你在测试工具中遇到了问题,因为你的猴子修补了 sys.exit
的实现,实际上 returns,argparse 库没有预料到这一点。
引入引发异常的 side_effect,然后您可以在单元测试中捕获并验证该异常,这可能足以解决问题。
在 def parse_arguments(self, args=None):
中,您应该将 args
传递给解析器,如:
self.args_parser.parse_args(args)
parse_args()
解析 sys.argv[1:]
,或者如果给定的参数是 None
。否则它会解析提供的列表。
在 python
的完整分发版中,有一个 argparse
(test_argparse.py
) 的单元测试文件。有点复杂,定义了一个ArgumentParser
的子类,用于捕获错误和重定向错误信息。
测试 argparse
是棘手的,因为它会查看 sys.argv
,unittest
脚本也使用。它通常会尝试在出现错误时退出。这已经在许多 SO 问题中进行了讨论。