pytest在subprocess.call()中模拟全局变量

时间:2018-11-03 09:03:01

标签: python unit-testing mocking pytest patch

可以在these answers之后轻松模拟全局变量。大。但是,当在Pytest的测试中尝试用subprocess.call()调用的脚本中模拟变量时,此方法不起作用。

这是我的简化脚本,位于名为so_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。

所以我的问题是:我如何在INCREMENTOR文件中模拟so_script.py全局变量,以便在对其调用subprocess.call()时仍能对其进行模拟?

1 个答案:

答案 0 :(得分:0)

由于<b:widget id='Blog1' type='Blog'>脚本和pytest是在不同的进程中执行的,因此无法在so_script.py中模拟对象,而后者在测试中被称为不同的进程。

我发现的最佳解决方案是将so_script.py块中的所有内容放入函数中,并使用Pytest测试该函数,从而模拟我需要模拟的一切。并且,为了获得100%的测试覆盖率(这是我最初的意图,将脚本作为子流程进行调用),我应用了this solution

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