如何 运行 在使用 argparse 的文件上使用指定的测试目录进行 pytest?
How to run pytest with a specified test directory on a file that uses argparse?
- 我正在使用 pytest
为 Python 库编写单元测试
- 我需要为测试文件指定一个目录以避免自动发现测试文件,因为有一个很大的子目录结构,包括库中包含“_test”的许多文件" 或名称中的 "test_" 但不适用于 pytest
- 库中的某些文件使用 argparse 来指定命令行选项
- 问题是将 pytest 的目录指定为命令行参数似乎会干扰使用 argparse 的命令行选项
举个例子,我在根目录下有一个名为script_with_args.py
的文件如下:
import argparse
def parse_args():
parser = argparse.ArgumentParser(description="description")
parser.add_argument("--a", type=int, default=3)
parser.add_argument("--b", type=int, default=5)
return parser.parse_args()
我在根目录中还有一个名为 tests
的文件夹,其中包含一个名为 test_file.py
:
的测试文件
import script_with_args
def test_script_func():
args = script_with_args.parse_args()
assert args.a == 3
如果我从命令行调用 python -m pytest
,测试会顺利通过。如果我从命令行使用 python -m pytest tests
指定测试目录,则会返回以下错误:
============================= test session starts =============================
platform win32 -- Python 3.6.5, pytest-3.5.1, py-1.5.3, pluggy-0.6.0
rootdir: C:\Users\Jake\CBAS\pytest-tests, inifile:
plugins: remotedata-0.2.1, openfiles-0.3.0, doctestplus-0.1.3, arraydiff-0.2
collected 1 item
tests\test_file.py F [100%]
================================== FAILURES ===================================
______________________________ test_script_func _______________________________
def test_script_func():
# a = 1
# b = 2
> args = script_with_args.parse_args()
tests\test_file.py:13:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
script_with_args.py:9: in parse_args
return parser.parse_args()
..\..\Anaconda3\lib\argparse.py:1733: in parse_args
self.error(msg % ' '.join(argv))
..\..\Anaconda3\lib\argparse.py:2389: in error
self.exit(2, _('%(prog)s: error: %(message)s\n') % args)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = ArgumentParser(prog='pytest.py', usage=None, description='description', f
ormatter_class=<class 'argparse.HelpFormatter'>, conflict_handler='error', add_h
elp=True)
status = 2, message = 'pytest.py: error: unrecognized arguments: tests\n'
def exit(self, status=0, message=None):
if message:
self._print_message(message, _sys.stderr)
> _sys.exit(status)
E SystemExit: 2
..\..\Anaconda3\lib\argparse.py:2376: SystemExit
---------------------------- Captured stderr call -----------------------------
usage: pytest.py [-h] [--a A] [--b B]
pytest.py: error: unrecognized arguments: tests
========================== 1 failed in 0.19 seconds ===========================
我的问题是,如何在不干扰 argparse 的命令行选项的情况下为 pytest 指定测试文件目录?
parse_args()
不带参数读取 sys.argv[1:]
列表。这将包括 'tests' 字符串。
pytests
也将 sys.argv[1:]
与自己的解析器一起使用。
使您的解析器可测试的一种方法是提供一个可选的 argv
:
def parse_args(argv=None):
parser = argparse.ArgumentParser(description="description")
parser.add_argument("--a", type=int, default=3)
parser.add_argument("--b", type=int, default=5)
return parser.parse_args(argv)
然后你可以测试它:
parse_args(['-a', '4'])
并与
一起真正使用它
parse_args()
改成sys.argv
也是个好办法。但是,如果您打算将解析器放入这样的函数中,您不妨给它增加灵活性。
要添加到 hpaulj 的答案中,您还可以使用像 unittest.mock 这样的库来临时屏蔽 sys.argv
的值。这样你的 parse args 命令将 运行 使用 "mocked" argv 但 actual sys.argv
保持不变。
当您的测试调用 parse_args()
时,他们可以这样做:
with unittest.mock.patch('sys.argv', ['--a', '1', '--b', 2]):
parse_args()
我 运行 在 VS Code 中遇到类似的测试发现问题。 VS Code 中的 运行 适配器传入我的程序不理解的参数。我的解决方案是让解析器接受未知参数。
变化:
return parser.parse_args()
收件人:
args, _ = parser.parse_known_args()
return args
- 我正在使用 pytest 为 Python 库编写单元测试
- 我需要为测试文件指定一个目录以避免自动发现测试文件,因为有一个很大的子目录结构,包括库中包含“_test”的许多文件" 或名称中的 "test_" 但不适用于 pytest
- 库中的某些文件使用 argparse 来指定命令行选项
- 问题是将 pytest 的目录指定为命令行参数似乎会干扰使用 argparse 的命令行选项
举个例子,我在根目录下有一个名为script_with_args.py
的文件如下:
import argparse
def parse_args():
parser = argparse.ArgumentParser(description="description")
parser.add_argument("--a", type=int, default=3)
parser.add_argument("--b", type=int, default=5)
return parser.parse_args()
我在根目录中还有一个名为 tests
的文件夹,其中包含一个名为 test_file.py
:
import script_with_args
def test_script_func():
args = script_with_args.parse_args()
assert args.a == 3
如果我从命令行调用 python -m pytest
,测试会顺利通过。如果我从命令行使用 python -m pytest tests
指定测试目录,则会返回以下错误:
============================= test session starts =============================
platform win32 -- Python 3.6.5, pytest-3.5.1, py-1.5.3, pluggy-0.6.0
rootdir: C:\Users\Jake\CBAS\pytest-tests, inifile:
plugins: remotedata-0.2.1, openfiles-0.3.0, doctestplus-0.1.3, arraydiff-0.2
collected 1 item
tests\test_file.py F [100%]
================================== FAILURES ===================================
______________________________ test_script_func _______________________________
def test_script_func():
# a = 1
# b = 2
> args = script_with_args.parse_args()
tests\test_file.py:13:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
script_with_args.py:9: in parse_args
return parser.parse_args()
..\..\Anaconda3\lib\argparse.py:1733: in parse_args
self.error(msg % ' '.join(argv))
..\..\Anaconda3\lib\argparse.py:2389: in error
self.exit(2, _('%(prog)s: error: %(message)s\n') % args)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = ArgumentParser(prog='pytest.py', usage=None, description='description', f
ormatter_class=<class 'argparse.HelpFormatter'>, conflict_handler='error', add_h
elp=True)
status = 2, message = 'pytest.py: error: unrecognized arguments: tests\n'
def exit(self, status=0, message=None):
if message:
self._print_message(message, _sys.stderr)
> _sys.exit(status)
E SystemExit: 2
..\..\Anaconda3\lib\argparse.py:2376: SystemExit
---------------------------- Captured stderr call -----------------------------
usage: pytest.py [-h] [--a A] [--b B]
pytest.py: error: unrecognized arguments: tests
========================== 1 failed in 0.19 seconds ===========================
我的问题是,如何在不干扰 argparse 的命令行选项的情况下为 pytest 指定测试文件目录?
parse_args()
不带参数读取 sys.argv[1:]
列表。这将包括 'tests' 字符串。
pytests
也将 sys.argv[1:]
与自己的解析器一起使用。
使您的解析器可测试的一种方法是提供一个可选的 argv
:
def parse_args(argv=None):
parser = argparse.ArgumentParser(description="description")
parser.add_argument("--a", type=int, default=3)
parser.add_argument("--b", type=int, default=5)
return parser.parse_args(argv)
然后你可以测试它:
parse_args(['-a', '4'])
并与
一起真正使用它parse_args()
改成sys.argv
也是个好办法。但是,如果您打算将解析器放入这样的函数中,您不妨给它增加灵活性。
要添加到 hpaulj 的答案中,您还可以使用像 unittest.mock 这样的库来临时屏蔽 sys.argv
的值。这样你的 parse args 命令将 运行 使用 "mocked" argv 但 actual sys.argv
保持不变。
当您的测试调用 parse_args()
时,他们可以这样做:
with unittest.mock.patch('sys.argv', ['--a', '1', '--b', 2]):
parse_args()
我 运行 在 VS Code 中遇到类似的测试发现问题。 VS Code 中的 运行 适配器传入我的程序不理解的参数。我的解决方案是让解析器接受未知参数。
变化:
return parser.parse_args()
收件人:
args, _ = parser.parse_known_args()
return args