如何在 pytest 中使用 sys.argv 为函数创建多个测试

Posted

技术标签:

【中文标题】如何在 pytest 中使用 sys.argv 为函数创建多个测试【英文标题】:How to create multiple tests for a function using sys.argv in pytest 【发布时间】:2021-09-03 15:40:06 【问题描述】:

我有一个看起来像这样的函数:

import argparse
import sys


def execute():
    parser = argparse.ArgumentParser()
    if (total_args := len(sys.argv)) == 1:
        do_stuff()
    if total_args == 2:
        first = sys.argv[1]
        do_stuff2()
    if total_args == 3:
        first, second = sys.argv[1:3]
        do_stuff3()
    if total_args > 3:
        first, second = sys.argv[1:3]
        del sys.argv[1:3]
        add_args(parser)
        parser.parse_args()
        do_stuff4()

哪个应该有一个测试函数test_execute,它将尝试不同的给定参数,问题是:有没有一种干净的方法可以不用手动修改sys.argv,使用sys.argv.extend(some_test_args)并稍后删除参数?

注意:我不能通过在parser.add_argument() 中设置nargs=? 来使用argparse 可选位置参数,因为前2 个参数是可选的,并且每种情况(1、2、3、> 3 个参数)执行不同的功能。要进一步了解,请查看以下示例...

parser = argparse.ArgumentParser()
parser.add_argument('arg1', nargs='?')
parser.add_argument('arg2', nargs='?')
args = parser.parse_known_args()
print(args)

如果像下面这样调用,将导致错误的变量保存在第二个位置:

>>> python my_script.py --unknown-arg 999 

将打印:

(Namespace(arg1='999', arg2=None), ['--unknown-arg'])

这完全不是我需要的。我期待arg1 有一个None 值。有时会出现未知参数的原因是argparse 不支持通过指定组来解析参数。假设我有参数组A 和参数组B,我只需要解析组A,我不能做parser.parse_group('A') 我将不得不创建parser_a = argparse.ArgumentParser() 并添加组A 参数和解析它们并重复parser_b

因此,到目前为止,我最好的解决方案是使用sys.argv,尽管这对于测试不方便。在不分组的情况下添加所有选项也会产生另一个问题,因为组 B 参数取决于从组 A 解析的值。

一种解决方法是指定使用--unknown-arg=999,但这会在文档和脚本的使用中造成不一致,这也不是我需要的。

【问题讨论】:

args =parser.parse_args(sys.argv[3:])。更一般地调用parse_args(argv),并根据需要创建或操作列表argv 我不确定我是否完全理解您的问题,但您是否考虑过使用sub-parser?子解析器允许您创建带有单独参数的“命令”,与 git init --bare 相当,其中 --bare 仅与 init 相关。 【参考方案1】:

您能否将sys.argv 传递给execute()

类似这样的:

import argparse
import sys

def execute(argv):
    parser = argparse.ArgumentParser()
    if (total_args := len(argv)) == 1:
        do_stuff()
    if total_args == 2:
        first = argv[1]
        do_stuff2()
    if total_args == 3:
        first, second = argv[1:3]
        do_stuff3()
    if total_args > 3:
        first, second = argv[1:3]
        del argv[1:3]
        add_args(parser)
        parser.parse_args(argv)
        do_stuff4()

if __name__ == "__main__":
    execute(sys.argv)

在您的测试中,您可以执行以下操作:

def test_execute():
    test_argv = ["some", "args", "list"]

    execute(test_argv)
    # assert something

【讨论】:

是的,反正我就是这么做的,谢谢。

以上是关于如何在 pytest 中使用 sys.argv 为函数创建多个测试的主要内容,如果未能解决你的问题,请参考以下文章

下载github单独文件夹的一个自用脚本

如何在 sys.argv 存在的情况下使用 argparse

python中sys.argv[]的使用

sys.argv[]用法-转载

python标准库之sys模块 学习

python - 如何将python argparse与sys.argv以外的args一起使用?