有没有办法可以使用mock()(或类似的)来模拟日期&脚本的时间我*从单元测试中调用*?

时间:2014-12-18 14:40:41

标签: python datetime mocking unit-testing

我在Python中使用unittest编写了一些单元测试。但是,它们不是简单地以传统方式测试对象 - 而是通过使用Popen调用它来调用另一个Python脚本。这是设计 - 它是一个命令行实用程序,所以我想以用户的身份进行测试,其中包括命令行选项等内容。需要说明的是,单元测试和要测试的脚本都是用Python编写的(准确地说是v3)。

我正在测试的脚本大量使用datetime.now(),理想情况下我想以某种方式模拟该值,以便我可以保持它不变。不过我所看到的所有这些例子(例如this one使用mock)都假设某种形式的白盒测试。

我有办法做到这一点吗?

1 个答案:

答案 0 :(得分:1)

在没有使用Popen的情况下,没有什么可以阻止您测试CLI。您只需要构建代码以使其成为可能:

而不是这个:

if __name__ == "__main__":
    import argparse
    parser = argparse.ArgumentParser()
    # ... Add args
    ns = parser.parse_args()

这样做:

import argparse

def main(argv):
    parser = argparse.ArgumentParser()
    # ... Add args
    parser.parse_args(argv[1:])  # This is the default for argparse
    ns = parser.parse_args()

if __name__ == "__main__":
    import sys
    main(sys.argv)

然后,您可以单独测试main函数(只需使用您指定的一组args调用main([...]))。请注意,对于其他CLI框架,这也应该起作用(对其进行一些调整)。


另请注意,如果您确实使用argparse,则需要修补ArgumentParser(),以便在解析失败时不会调用sys.exit

一种简单的方法是声明ParsingError例外,并使用以下代码修补ArgumentParser.error(self, message)

def error(self, message):
    raise ParsingError(message) 

然后,您可以在测试中使用assertRaises