pytest 和 argparse:由于命令行参数导致测试失败

问题描述 投票:0回答:1

我有

client.py
模块,它使用
argparse
用于 CLI:

class Client:
    #some logic
    ...

def main(arguments=None):
    parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
    parser.add_argument("n", nargs='?', type=int, default=10, help="number of threads")
    parser.add_argument("f", nargs='?', default="urls.txt", help="file with URLs")
    args = parser.parse_args(arguments)

    #some logic unrelated to argparse
    ...

if __name__ == "__main__":
    main()

还有

tests.py
模块进行测试:

import sys
from unittest.mock import patch
import client

    def test(self):
        with patch.object(sys, 'argv', ['n', 10, 'f', "urls.txt"]):
            client.main()

client.py
模块在 CLI 和脚本中运行良好。但是当它调用 pytest 测试时 - 出现错误:

    def test(self):
        with patch.object(sys, 'argv', ['n', 10, 'f', "urls.txt"]):    
>           client.main()

test_client_server.py:60: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
client.py:55: in main
    args = parser.parse_args(arguments)
..\..\..\AppData\Local\Programs\Python\Python311\Lib\argparse.py:1862: in parse_args
    args, argv = self.parse_known_args(args, namespace)
..\..\..\AppData\Local\Programs\Python\Python311\Lib\argparse.py:1895: in parse_known_args
    namespace, args = self._parse_known_args(args, namespace)
..\..\..\AppData\Local\Programs\Python\Python311\Lib\argparse.py:1938: in _parse_known_args
    option_tuple = self._parse_optional(arg_string)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = ArgumentParser(prog='n', usage=None, description=None, formatter_class=<class 'argparse.ArgumentDefaultsHelpFormatter'>, conflict_handler='error', add_help=True)
arg_string = 10

    def _parse_optional(self, arg_string):
        # if it's an empty string, it was meant to be a positional
        if not arg_string:
            return None
    
        # if it doesn't start with a prefix, it was meant to be positional
>       if not arg_string[0] in self.prefix_chars:
E       TypeError: 'int' object is not subscriptable

..\..\..\AppData\Local\Programs\Python\Python311\Lib\argparse.py:2228: TypeError

我尝试过模拟

sys.argv
- 它可以很好地模拟
['n', 10, 'f', 'urls.txt']
,但测试还是失败并出现错误。
为什么
arg_string = 10
会出错?没看懂。

python mocking pytest argparse
1个回答
0
投票

你的解析器,没有所有的 pytest 包袱(在

ipython
会话中):

In [10]: def main(arguments=None):
    ...:     parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
    ...:     parser.add_argument("n", nargs='?', type=int, default=10, help="number of threads")
    ...:     parser.add_argument("f", nargs='?', default="urls.txt", help="file with URLs")
    ...:     args = parser.parse_args(arguments)
    ...:     return args

帮助:

In [11]: main(['-h'])
usage: ipykernel_launcher.py [-h] [n] [f]

positional arguments:
  n           number of threads (default: 10)
  f           file with URLs (default: urls.txt)

options:
  -h, --help  show this help message and exit

有效的 argv 列表 - 两个字符串,用于两个位置参数:

In [12]: main(['10','text.file'])
Out[12]: Namespace(n=10, f='text.file')

尝试你的

argv
,但使用“10”字符串:

In [13]: main(['n', '10', 'f', "urls.txt"])
usage: ipykernel_launcher.py [-h] [n] [f]
ipykernel_launcher.py: error: argument n: invalid int value: 'n'

它试图将 'n' 字符串解析为

int
。您定义了位置,而不是标记的参数,因此 'n' 和 'f' 字符串不属于。

您的错误 - 使用数字

10
而不是字符串:

In [14]: main(['n', 10, 'f', "urls.txt"])
TypeError: 'int' object is not subscriptable
© www.soinside.com 2019 - 2024. All rights reserved.