我想在我正在编写的代码中添加一些命令行参数,当我包含了argparse内容时,测试就会失败。
下面是基类的精简版本:
import argparse
import sys
class PreProcessor:
def parse_args(self, args):
parser = argparse.ArgumentParser(description='Arguments for PreProcessor scripts.')
parser.add_argument('-i', '--ignore-pid', help='If the script is already running, it will not re-run. This over-rides that.', action="store_true")
parser.add_argument('-v', '--verbose', type=int, choices=[0,1,2,3], default=1, help='Be noisy when running [0 is completely silent, 3 is debug-level. defaults to 1].')
return parser.parse_args()
def __init__(
self,
code,
):
if not code:
raise ValueError("A code must be defined")
self.code = code
# These two lines
self.args = self.parse_args(sys.argv)
print(f"type: {type(self.args)}, data: {self.args}")……下面是它的测试文件:
import pytest
from .example import PreProcessor
def test_base_initialisation():
foo = PreProcessor(code="foo")
assert foo.code == "foo"因此,我得到的错误是:
platform linux -- Python 3.6.9, pytest-3.3.2, py-1.5.2, pluggy-0.6.0 -- /usr/bin/python3
cachedir: .cache
rootdir: /home/kiz/development/FindingStudySpaces/preprocessors, inifile: pytest.ini
plugins: cov-2.5.1
collected 1 item
preprocessors/test_example.py::test_base_initialisation FAILED [100%]
generated xml file: /home/kiz/development/FindingStudySpaces/preprocessors/pytest-results.xml
----------- coverage: platform linux, python 3.6.9-final-0 -----------
Name Stmts Miss Cover
----------------------------------------------------
preprocessors/__init__.py 0 0 100%
preprocessors/example.py 14 2 86%
preprocessors/preprocessors.py 140 140 0%
----------------------------------------------------
TOTAL 154 142 8%
Coverage HTML written to dir htmlcov
======================================== FAILURES ========================================
________________________________ test_base_initialisation ________________________________
self = ArgumentParser(prog='pytest-3', usage=None, description='Arguments for PreProcessor scripts.', formatter_class=<class 'argparse.HelpFormatter'>, conflict_handler='error', add_help=True)
action = _StoreAction(option_strings=['-v', '--verbose'], dest='verbose', nargs=None, const=None, default=1, type=<class 'int'>...es=[0, 1, 2, 3], help='Be noisy when running [0 is completely silent, 3 is debug-level. defaults to 1].', metavar=None)
arg_string = 'preprocessors/test_example.py'
def _get_value(self, action, arg_string):
type_func = self._registry_get('type', action.type, action.type)
if not callable(type_func):
msg = _('%r is not callable')
raise ArgumentError(action, msg % type_func)
# convert the value to the appropriate type
try:
> result = type_func(arg_string)
E ValueError: invalid literal for int() with base 10: 'preprocessors/test_example.py'
... <snip loads of stuff> ...
# TypeErrors or ValueErrors also indicate errors
except (TypeError, ValueError):
name = getattr(action.type, '__name__', repr(action.type))
args = {'type': name, 'value': arg_string}
msg = _('invalid %(type)s value: %(value)r')
> raise ArgumentError(action, msg % args)
E argparse.ArgumentError: argument -v/--verbose: invalid int value: 'preprocessors/test_example.py'
... <snip loads more stuff> ...我尝试过在sys.argv[1:]方法中传递init --没有什么不同。
如果我注释掉对argparse的调用(也就是其中写着# These two lines的行),那么我就可以传递..。
我真的不想在每个测试方法中添加一个模拟/补丁程序,而不是在活动代码中添加一些子句来测试def parse_args(self, args)是否已经被测试例程调用了。
……我的google发现了一些关于测试参数的讨论--传递(这很好)--但是我找不到argparse在这个级别上失败的任何地方。
发布于 2020-01-17 11:53:45
我感谢这两位..。这才是真正对我起作用的。
让__init__在sys.argv[0]中查找pytest (诚实地说,它也应该查找unittest或node ),并将空列表传递给an解析器函数,如果这样做的话:
import argparse
import re
import sys
class PreProcessor:
def parse_args(self, args):
parser = argparse.ArgumentParser(description='Arguments for PreProcessor scripts.')
parser.add_argument('-i', '--ignore-pid', help='If the script is already running, it will not re-run. This over-rides that.', action="store_true")
parser.add_argument('-v', '--verbose', type=int, choices=[0,1,2,3], default=1, help='Be noisy when running [0 is completely silent, 3 is debug-level. defaults to 1].')
return parser.parse_args(args)
def __init__(
self,
code,
):
if not code:
raise ValueError("A code must be defined")
self.code = code
if re.search('pytest', sys.argv[0]):
self.args = self.parse_args([])
else:
self.args = self.parse_args(sys.argv[1:])现在,在我的测试中,我可以根据需要patch sys对象:
import pytest
import re
import sys
from unittest.mock import patch
from .example import PreProcessor
def test_base_initialisation():
foo = PreProcessor(code="foo")
assert foo.code == "foo"
def test_known_command_line_options(capsys):
foo = PreProcessor(code="foo")
test_args = ["fake", "-h"]
with patch.object(sys, 'argv', test_args):
with pytest.raises(SystemExit):
foo.parse_args(sys.argv)
captured = capsys.readouterr()
assert re.match(captured, "usage: fake [-h] [-i] [-v {0,1,2,3}]")
assert re.search(captured, "Arguments for PreProcessor scripts")
test_args = ["fake", "--help"]
with patch.object(sys, 'argv', test_args):
with pytest.raises(SystemExit):
foo.parse_args(sys.argv)
captured = capsys.readouterr()
assert re.match(captured, "usage: fake [-h] [-i] [-v {0,1,2,3}]")
assert re.search(captured, "Arguments for PreProcessor scripts")
def test_unknown_command_line_options(capsys):
foo = PreProcessor(code="foo")
test_args = ["fake", "-a"]
with patch.object(sys, 'argv', test_args):
with pytest.raises(SystemExit):
foo.parse_args(sys.argv)
captured = capsys.readouterr()
assert re.match(captured, "usage: fake [-h] [-i] [-v {0,1,2,3}]")
assert re.search(captured, "unrecognized arguments: -a")此外,作为参考,and解析中的帮助文本如下:
$> python3 labmon.py -h
usage: labmon.py [-h] [-i] [-v {0,1,2,3}]
Arguments for PreProcessor scripts.
optional arguments:
-h, --help show this help message and exit
-i, --ignore-pid If the script is already running, it will not re-run.
This over-rides that.
-v {0,1,2,3}, --verbose {0,1,2,3}
Be noisy when running [0 is completely silent, 3 is
debug-level. defaults to 1].和
$> python3 labmon.py -a
usage: labmon.py [-h] [-i] [-v {0,1,2,3}]
labmon.py: error: unrecognized arguments: -a发布于 2020-01-15 18:04:56
这一行:
return parser.parse_args()应该是
return parser.parse_args(args)否则,parser.parse_args默认为sys.argv[1:],这可能不是您想要的。
另外,传递给它的sys.argv是调用pytest的值--您可能希望将它设置为对程序有意义的东西。
你有两种选择
from unittest import mock
def test():
with mock.patch.object(sys, 'argv', ['yourprog', 'args', 'here']):
...class C:
def __init__(self, code, args=None):
...
self.parse_args(args)
def parse_args(self, args=None):
...
return parser.parse_args(args)def test():
thing = C(..., args=['args', 'here'])https://stackoverflow.com/questions/59750480
复制相似问题