Python、Unittest、sys.Argv用于在脚本中定义全局变量.如何正确测试?



我想测试一个脚本,看起来像这样:
my_script.py

import argparse, sys
def my_parser(args=sys.argv[1:]):
parser = argparse.ArgumentParser(description="my parser")
parser.add_argument("--my-arg", dest="my_arg", required=True)
args, _ = parser.parse_known_args(args=args)
return args
args = my_parser()
def do_something():
res = 5+1
return res
def main():
use_args = args
res = do_something()
# whatevere here

当我尝试为函数do_something()运行单元测试时,我总是得到解析器需要输入参数的错误。我的测试是这样的:
my_test.py

from unittest import TestCase
from my_script import sys, do_something
class MyTest(TestCase):
def test_do_something(self):
test_sys_argv = ["dummy", "--my-arg", "dummy_arg"]
with patch.object(sys, "argv", test_sys_argv):
out = do_something()
self.assertEqual(out, 6)

我做补丁的方式不工作。我理解,通过这种方式,我在函数do_something()中修补对sys.argv的任何引用,而当调用测试时,sys.argv为脚本空。
是否有可能在不重构函数内的变量args的情况下解决这个问题?我想有args变量my_script.py作为脚本的全局变量。谢谢你的帮助。

如果您想测试my_parser,只需在测试中手动传递一个输入。如果您想测试do_something,则根本不需要sys.argv,因为fn从不使用args。

这里的问题在于

这一行
args = my_parser()

在导入脚本时运行,即在测试之前。*将其移动到main或if __name__ == "__main__"块中。如果你真的想要,没有什么可以阻止args成为全局变量:

args = None
if __name__ == "__main__":
args = my_parser()

我强烈怀疑你只会计算一次参数——在运行时,在这种情况下,我不太确定为什么你不像往常一样使用argparse而不使用sys.argv.

你试图修补系统。Argv不起作用,因为它发生在导入之后,而函数已经有了一个空的sys。当它第一次被定义时。(可变的默认参数是在定义函数时绑定的,尽管在这种情况下它甚至不重要,因为在进行测试之前,函数被调用。)您可以考虑这样定义它:

def my_parser(args = None):
args = args or sys.argv[1:]
...

sys以来。Argv现在在函数内部被调用,它将在运行时被评估,如果需要,你可以修补它。除了测试之外,我看不出有任何理由这样做,因为您通常不会修改sys。

*你可以通过在test函数内部导入来解决这个问题…但重点是,目前模块中的"全局变量"是而不是导入安全的。我不太确定这里的执行流程是什么。

注:如果你想测试一个命令行应用程序,你可能想看看其中一个测试框架来模拟不同参数的调用。

相关内容

  • 没有找到相关文章

最新更新