【问题标题】:How to unittest with command line arguments如何使用命令行参数进行单元测试
【发布时间】:2022-01-18 14:46:36
【问题描述】:

我正在使用 python unittest 模块来测试一个带有命令行参数的文件。参数是一个文件名,然后传递给这样的函数:

file_name = str(sys.argv[1])
file = open(file_name)
result = main_loop(file)
print(result)

我的测试是这样设置的:

class testMainFile(unittest.TestCase):

    def test_main_loop(self):
        file = open('file_name.json')
        result = main_file.main_loop(file)
        self.assertEqual(result, 'Expected Result')
                
if __name__ == 'main':
    unittest.main()

当我运行测试时,我得到一个“IndexError: list index out of range”。

我尝试在运行测试时传递参数,但无济于事。如何正确运行测试?

【问题讨论】:

  • 您可以直接分配给sys.argv,但不清楚您是如何导入脚本进行测试的。您的脚本和测试代码之间有很多明显的重复,并且没有提及 main_file 的定义位置。
  • 您能否进一步解释如何做到这一点?

标签: python unit-testing


【解决方案1】:

我认为您在这里有几个选择。首先去文档和结帐patch 因为我认为你可以侥幸逃脱

from unittest.mock import patch

@patch('sys.argv', ['mock.py', 'test-value'])
def test_main_loop(self):

有趣的选项:

一个将简单地覆盖您的电话旁边的sys.argv

def test_main_loop(self):
    file = open('file_name.json')
+   orginal_argv = sys.argv
+   sys.argv = ['mock argv', 'my-test-value'] 
    result = main_file.main_loop(file)
+   sys.argv = orginal_argv 
    self.assertEqual(result, 'Expected Result')

第二个是为你的函数创建一个简单的包装器

def set_sys_argv(func: Callable):
    sys.argv = ['mock.py', 'my_test_value']
    def wrapper(*args, **kwargs):
        func()
    return wrapper

并将其与测试功能一起使用

@set_sys_argv
def test_main_loop(self):

我们可以稍微改进一下,让它更通用,制作一个接受要模拟的值的装饰器

def set_sys_argv(*argv):
    sys.argv = argv

    def _decorator(func: Callable):
        def wrapper(*args, **kwargs):
            func()
        return wrapper
    return _decorator

并类似地使用它来修补

@set_sys_argv('mock.py', 'test-value')
def test_main_loop(self):

第三个是创建一个上下文管理器,同样:

class ReplaceSysArgv(list):
    def __enter__(self):
        self._argv = sys.argv
        sys.argv = ['mock', 'my-test-value']
        return self
    def __exit__(self, *args):
        sys.argv = self._argv

并将其与您的代码一起使用

    def test_main_loop(self):
        file = open('file_name.json')
        with ReplaceSysArgv():
            result = main_file.main_loop(file)
        self.assertEqual(result, 'Expected Result')

【讨论】:

    【解决方案2】:

    在检索参数之前,您必须将参数推送到 sys.argv(如果您的代码是从命令行参数中提取的 - 我不清楚您在测试中的哪个位置使用命令行参数,但我离题了)

    所以首先要做的事情

    import sys
    
    sys.argv = ['mock_filename.py', 'json_file.json']
    #... continue with rest of program / test.
    

    【讨论】:

    • 抱歉,在定义 sys.argv 列表后,我有点不清楚如何处理它。
    猜你喜欢
    • 2011-08-22
    • 2016-02-25
    • 2016-09-08
    • 1970-01-01
    • 2016-11-07
    • 1970-01-01
    • 2019-03-22
    • 1970-01-01
    • 2015-12-10
    相关资源
    最近更新 更多