我正在编写pytest插件,该插件应测试旨在在一组特定环境中运行的软件。
我正在编写的软件在一个更大的框架中运行,这使某些Python模块仅在框架中运行我的Python软件时可用。
为了测试我的软件,我需要“模拟”或伪造整个模块(实际上是很多模块)。我需要以某种类似的方式实现其功能,但是我的问题是,如何使用py.test插件将该虚假的Python模块提供给我的软件代码?
例如,假设我的一个源文件中包含以下代码:
import fwlib
def fw_sum(a, b):
return fwlib.sum(a, b)
Run Code Online (Sandbox Code Playgroud)
但是,该fwlib模块仅由运行软件的框架提供,并且无法在其中进行测试。
我如何从pytest插件中确保fwlib已在中定义名为的模块sys.modules?当然,我需要实现fwlib.sum自己。我正在寻找有关如何做到这一点的建议。
wim*_*wim 27
pytest 为这个用例提供了一个装置:monkeypatch.syspath_prepend.
您可以sys.path在导入位置列表之前添加路径。编写一个假fwlib.py并将其包含在您的测试中,并根据需要附加目录。与其他测试模块一样,它不需要包含在发行版中。
在自己玩这个之后,我实际上无法弄清楚如何让夹具从库代码中正确地模拟模块级导入。到测试运行时,库代码已经导入,现在修补已经太晚了。
不过,我可以提供不同的解决方案,它的工作原理:您可以从内注入的名字conftest.py,其中最先被引进。被测代码中的后续导入语句将仅重用sys.modules.
封装结构:
$ tree .
.
??? conftest.py
??? lib
? ??? my_lib.py
??? tests
??? test_my_lib.py
2 directories, 3 files
Run Code Online (Sandbox Code Playgroud)
文件内容:
# conftest.py
import sys
def fwlib_sum(a, b):
return a + b
module = type(sys)('fwlib')
module.sum = fwlib_sum
sys.modules['fwlib'] = module
Run Code Online (Sandbox Code Playgroud)
库文件:
# lib/my_lib.py
import fwlib
def fw_sum(a, b):
return fwlib.sum(a, b)
Run Code Online (Sandbox Code Playgroud)
测试文件:
# lib/test_my_lib.py
import my_lib
def test_sum():
assert my_lib.fw_sum(1, 2) == 3
Run Code Online (Sandbox Code Playgroud)
只是为了向 @wim 的好答案提供更多细节,您也可以将它与子模块一起使用,如下所示:
import sys
module = type(sys)("my_module_name")
module.submodule = type(sys)("my_submodule_name")
module.submodule.something = sommething
sys.modules["my_module_name"] = module
sys.modules["my_module_name.my_submodule_name"] = module.submodule
Run Code Online (Sandbox Code Playgroud)