带有命令行参数的单元测试

Posted

技术标签:

【中文标题】带有命令行参数的单元测试【英文标题】:Unittest with command-line arguments 【发布时间】:2015-12-10 17:12:37 【问题描述】:

根据我从另一篇 SO 帖子中了解到的情况,要对通过 argparse 获取命令行参数的脚本进行单元测试,我应该执行类似于以下代码的操作,将 sys.argv[0] 作为 arg。

import unittest
import match_loc

class test_method_main(unittest.TestCase):

    loc = match_loc.main()
    self.assertEqual(loc, [4])


if __name__ == '__main__':
    sys.argv[1] = 'aaaac'
    sys.argv[2] = 'ac'
    unittest.main(sys.argv[0])

这会返回错误:

usage: test_match_loc.py [-h] text patterns [patterns ...]
test_match_loc.py: error: the following arguments are required: text, patterns

我想更深入地了解这里发生了什么。我明白了

if __name__ == '__main__': main()

说如果这是由'main'执行,***别,默认解释器,只是自动运行'main'方法。我假设

if __name__ == '__main__': unittest.main()

恰好是您在运行单元测试脚本时所说的方式。

我知道当任何脚本运行时,它都会自动有一个argv 对象,一个收集命令行上所有项目的向量。

但我不明白unittest.main(sys.arg[0]) 会做什么。 'unittest.main' 对参数有什么作用?如何预先设置 sys.argv 的值 - 每次运行脚本时它不会自动重置吗?此外,如果在任何脚本之外,这个对象 'sys.argv' 存在于哪里?最后,实现命令行参数测试的正确方法是什么?

如果我的问题含糊不清和误导,我很抱歉。我想了解这里所有相关的组件,这样我才能真正了解我在做什么。

非常感谢。

【问题讨论】:

如果不知道您在test_match_loc.py 中如何使用argparse,很难为您提供帮助。您可能需要在该模块中设置sys.argv,或者使用自定义字符串列表调用parse_args,如许多argparse 文档示例中所示。另请查看argparse 自己的单元测试文件。 【参考方案1】:

只是玩弄了一对简单的文件,我发现在调用者模块的主体中​​修改sys.argv会影响导入模块看到的sys.argv

import sys
sys.argv[1] = 'aaaac'
sys.argv[2] = 'ac'
class test_method_main(unittest.TestCase):
   ...

但是像你一样在main 块中修改sys.argv,不会出现在导入的块中。我们可以深入研究文档(和代码)以了解确切原因,但我认为仅确定有效的方法就足够了。

这是我从您之前关于导入模块的问题中重建的内容 - 带有一些诊断打印

import argparse
import sys
def main():
    print(sys.argv)
    parser = argparse.ArgumentParser(
            description='Takes a series of patterns as fasta files'
            ' or strings and a text as fasta file or string and'
            ' returns the match locations by constructing a trie.')
    parser.add_argument('text')
    parser.add_argument('patterns', nargs='+')
    args = parser.parse_args()
    print(args)
    return 1

您还可以使用自己的字符串列表测试解析器,如果 parse_args 的参数缺失或无,则使用 sys.argv[1:]

def main(argv=None):
    print(argv)
    ...
    args = parser.parse_args(argv)
    print(args)
    return 1

loc = match_loc.main(['abc','ab'])  # and in the caller

即使我能够构建一个有效的测试用例,您确实应该提供足够的信息,我无需猜测或挖掘。

【讨论】:

嗨,我想使用相同的功能。但是在 sys args 中添加参数时出现 IndexError: list assignment index out of range 错误。 @Vish,在尝试添加项目之前检查sys.argv 的大小。 是的..如果有人想添加额外的参数,可以像 sys.argv.append("ert") 一样添加。

以上是关于带有命令行参数的单元测试的主要内容,如果未能解决你的问题,请参考以下文章

Visual Studio单元测试和命令行参数,以避免源代码管理中的密码

pytest--命令行常用参数

如何在命令行上将运行时参数传递给 dotnet test?

带有命令行参数的 Autohotkey 脚本运行程序

用于查找可安装单元的p2 director命令行参数不返回信息

将命令行参数传递给调用带有装饰器参数的装饰函数的函数