简体   繁体   English

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

[英]Pytest mock global variable in subprocess.call()

A global variable can be easily mocked following these answers . 遵循这些答案可以很容易地嘲笑全局变量。 Great. 大。 However, this does not work when trying to mock a variable in a script that you call with subprocess.call() in a test with Pytest. 但是,在使用Pytest进行的测试中尝试用subprocess.call subprocess.call()调用的脚本中模拟变量时,此方法不起作用。

Here is my simplified script in a file called so_script.py : 这是名为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))

Now, say I want to mock the value of INCREMENTOR in my tests to be 1 . 现在,假设我想在测试中将INCREMENTOR的值模拟为1 If I do this: 如果我这样做:

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'

The test will fail, because the value of INCREMENTOR remains 4, even though I tried to patch it to 1. So what gets written to the file is 7 instead of 4. 测试将失败,因为即使我尝试将其修补为1, INCREMENTOR的值仍为4,所以写入文件的是7而不是4。

So my question is: how do I mock the INCREMENTOR global variable in my so_script.py file so that, when calling subprocess.call() on it, it remains mocked? 所以我的问题是:如何在so_script.py文件中模拟INCREMENTOR全局变量,以便在对其调用so_script.py subprocess.call()时仍保持模拟状态?

Because the so_script.py script and pytest are executed in different processes, one cannot mock objects in so_script.py while the latter is being called as a different process in tests. 由于so_script.py脚本和pytest在不同的进程中执行,因此无法在so_script.py模拟对象,而后者在测试中被称为不同的进程。

The best solution I found was to put everything from the if __name__ == '__main__: block in a function and test that function with Pytest, mocking whatever I needed to mock. 我发现最好的解决方案是将if __name__ == '__main__:块中的所有内容放入函数中,并使用Pytest测试该函数,模拟我需要模拟的一切。 And, to have 100% test coverage (which was my initial intent with calling the script as a subprocess), I applied this solution . 而且,为了获得100%的测试覆盖率(这是我最初的意图,将脚本作为子流程进行调用),我应用了此解决方案

So I dropped using subprocess.call() in my tests and wrote an init() function checking if __name__ == '__main__: , and then mocked __name__ in the tests to test the function, just as the article advises to do. 所以我放弃了使用subprocess.call()在我的测试,并写了init()函数检查if __name__ == '__main__:然后嘲笑__name__的测试,以测试功能,就像文章建议做。 This got me 100% test coverage and full mocking capabilities. 这给了我100%的测试覆盖率和完整的模拟功能。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM