使用 pytest 测试模块执行

Testing module execution with pytest

我有一个 python 模块作为 python -m my_package.my_module --arg1 a1 --arg2 a2 执行。这会在本地磁盘上创建一个工件并将该工件上传到云存储桶。

我的模块基本上是这样的

import argparse

def func():
    # parse args
    # create artifact
    # upload to bucket

func()

我想为此模块编写一个测试,我可以 运行 来自不同的脚本,比如 test_module.py。我想模拟云 api 所以不会上传任何内容,但也会向模块提供一组测试命令行参数。

到目前为止我可以做这样的事情

#test_module.py
from unittest import mock

def test_my_module():
    test_args = # [  test args ]
    with mock.patch.object(sys, 'argv', test_args):
        import my_package.my_module
        # test file is written to local dir

这里的问题是,如果不先导入 my_package.my_module,我就无法模拟云 api,运行 是模块中的代码并上传工件。如果我这样做 像这样

#test_module.py
from unittest import mock
import my_package.my_module

@mock.patch('my_package.my_module.cloud_client')
def test_my_module():
    # run test

然后代码将在第一个导入语句 import my_package.my_module 上执行。有没有解决方案,我可以在 导入它所在的模块之前 模拟一个对象?

对这个问题使用惯用的解决方案:

import argparse

def func():
    # parse args
    # create artifact
    # upload to bucket

# Ensure this function only runs when this module is being executed as main, not when imported.
if __name__ == '__main__':
    func()

您可以在此处找到更多详细信息:What does if __name__ == "__main__": do?

在测试中导入模块(但不是 运行)后,您可以设置模拟并执行测试。