2017-09-15 128 views
1

我有一个Python脚本,可以执行多个os.system调用。将其作为一系列字符串进行声明将会很容易(并且相对优雅)。什么是模拟os.system单元测试(PyTest)

不容易的是拦截(并阻止)实际的呼叫。在有问题的剧本,我可能会在SUT(*),像这样抽象的使用os.system:

os_system = None 

def main(): 
    return do_the_thing(os.system) 

def do_the_thing(os_sys): 
    global os_system 
    os_system = os_sys 

    # all other function should use os_system instead of os.system 

我的测试调用my_script.do_the_thing(),而不是当然的my_script.main()(留下的未经测试的代码一个很小的量)。

备用选项:我可以离开SUT不变,并在SUT调用main()前的测试方法取代os.system全球。

这给我留下了新的问题,因为这是一个全球性的持久变化。很好,所以我会在相同的测试方法中使用try/finally,并在离开测试方法之前替换原件。无论测试方法通过还是失败,这都会起作用。

是否有这样做的PyTest的安全和优雅安装/拆卸中心的方式有关系吗?

其他并发症:我想为stdout和stderr做同样的事情。是的,它确实是我正在测试的main()脚本。

  • SUT ==被测系统

回答

2

Python的3(> = 3.3)标准库具有正式文件在great tutorial about Mock。对于Python 2,您可以在PyPi上使用backported库:Mock

以下是一个示例用法。假设你希望将电话嘲笑到os.system在这个函数:

import os 


def my_function(src_dir): 
    os.system('ls ' + src_dir) 

要做到这一点,你可以使用unittest.mock.patch装饰,就像这样:

import unittest.mock 


@unittest.mock.patch('os.system') 
def test_my_function(os_system): 
    # type: (unittest.mock.Mock) -> None 
    my_function("/path/to/dir") 
    os_system.assert_called_once_with('ls /path/to/dir') 

过程中,该测试功能将修补os.system通话它的执行。在最后恢复os.system

然后,有几个“断言”方法来检查调用,参数和结果。您还可以检查某些情况下是否发生异常。

+0

太好了。对于PyTest和Python2,它只是@ mock.patch('os.system'),我可以很好地确认作品。 –