Python subprocess.call()中的Pytest mock全局变量

Python subprocess.call()中的Pytest mock全局变量,python,unit-testing,mocking,pytest,patch,Python,Unit Testing,Mocking,Pytest,Patch,全局变量可以很容易地模拟如下。伟大的但是,在使用Pytest进行测试时,如果试图模拟脚本中使用subprocess.call()调用的变量,则此操作不起作用 这是我在一个名为so\u script.py的文件中的简化脚本: import argparse INCREMENTOR = 4 if __name__ == '__main__': parser = argparse.ArgumentParser() parser.add_argument('input_nr', t

全局变量可以很容易地模拟如下。伟大的但是,在使用Pytest进行测试时,如果试图模拟脚本中使用
subprocess.call()
调用的变量,则此操作不起作用

这是我在一个名为
so\u script.py
的文件中的简化脚本:

import argparse

INCREMENTOR = 4


if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('input_nr', type=int, help='An int to increment')
    args = parser.parse_args()

    with open('test.txt', 'w+') as f:
        f.write(str(args.input_nr + INCREMENTOR))
现在,假设我想模拟测试中
INCREMENTOR
的值为
1
。如果我这样做:

from subprocess import call
from unittest import mock

def test_increments_with_1():
    with mock.patch('so_script.INCREMENTOR', 1):
        call(['python', 'so_script.py', '3'])
    with open('test.txt', 'r+') as f:
        assert f.read() == '4'
测试将失败,因为
INCREMENTOR
的值仍然为4,即使我尝试将其修补为1。所以写入文件的是7,而不是4


因此,我的问题是:如何模拟
So_script.py
文件中的
INCREMENTOR
全局变量,以便在对其调用
subprocess.call()
时保持模拟状态

因为
so_script.py
脚本和pytest在不同的进程中执行,所以在测试中将后者作为不同的进程调用时,不能在
so_script.py
中模拟对象

我找到的最佳解决方案是将
if\uuuu name\uuu=='\uuu main\uuu:
块的所有内容放入函数中,并使用Pytest测试该函数,模拟我需要模拟的任何内容。并且,为了获得100%的测试覆盖率(这是我最初将脚本作为子流程调用的意图),我应用了


因此,我在测试中放弃了使用
subprocess.call()
,并编写了一个
init()
函数检查
if\uuuu name\uuu=='\uu main\uuuu:
,然后在测试中模拟
\uu name\uuuuu
,就像文章建议的那样。这使我获得了100%的测试覆盖率和完整的模拟功能。

Mock与语言资源(对象)一起使用。在本例中,您使用的是操作系统资源。从so调用子进程时,根据定义,您使用的不是Python资源,而是so资源,并将结果(有时是stdout)分配给Python对象。这就是为什么你不能做你想做的事。