2017-04-01 54 views
2

我正在编写一个pytest插件,它应该测试设计用于在一组特定环境中工作的软件。在pytest中嘲弄模块导入

我正在编写的软件运行在一个更大的框架内,这使得某些Python模块只有在框架内运行我的Python软件时才可用。

为了测试我的软件,我需要“模拟”或伪造整个模块(实际上,不少)。我需要以某种类似外观的方式实现它的功能,但是我的问题是如何使用py.test插件将这个假Python模块提供给我的软件代码?

例如,假设我有下面的代码在我的源文件中的一个:

import fwlib 

def fw_sum(a, b): 
    return fwlib.sum(a, b) 

然而,fwlib模块仅通过我运行从我的软件框架可用,而我无法测试在里面。

我如何确保从pytest插件中确定名为fwlib的模块已在sys.modules中定义?当然,我需要自己实施fwlib.sum。我正在寻找如何做到这一点的建议。

回答

1

pytest为此用例提供了一个工具:monkeypatch.syspath_prepend

您可以预先输入一个到导入位置列表的路径sys.path。写一个假的fwlib.py并将其包含在您的测试中,根据需要添加目录。像其他测试模块一样,它不需要包含在发行版中。

在玩完这个之后,我实际上并没有弄清楚如何从库代码中正确地模拟模块级导入(如果有人阅读,请找到正确的目录结构以使其正常工作,请发表一个答案!)。

但是,我可以提供一个不同的解决方案:您可以从conftest.py,which gets imported first注入名称。随后的导入语句将只重新使用sys.modules中已有的对象。

封装结构:

$ tree . 
. 
├── conftest.py 
├── lib 
│   └── my_lib.py 
└── tests 
    └── test_my_lib.py 

2 directories, 3 files 

内容的conftest.py

import sys 

def fwlib_sum(a, b): 
    return a + b 

module = type(sys)('fwlib') 
module.sum = fwlib_sum 
sys.modules['fwlib'] = module 

库模块:

import fwlib 

def fw_sum(a, b): 
    return fwlib.sum(a, b) 

测试模块:

import my_lib 

def test_sum(): 
    assert my_lib.fw_sum(1, 2) == 3 
+0

这很好,谢谢!你能否澄清最后一个声明,关于这个声明中是否需要包含它? – NirIzr

+0

假设你有一个'。/ tests /'子目录,在创建一个发行版时,它不会被'setup.py'文件打包。您可以创建例如可以在测试运行期间导入的'。/ tests/mocks/fwlib.py',但它不会与您的库一起分发。 – wim

+0

啊,我明白了。我会稍微等待其他答案来(不太可能),并尽快接受你的答案。再次感谢! – NirIzr