如何在pytest中导入函数

时间:2018-03-22 16:00:10

标签: python python-2.7 pytest

我的项目结构如下:

package
    -- tests
    -- bin 
    -- subpackage
        -- ...py

我需要测试一个名为master_disaster()的函数,它存在于bin/let-me-out内(是-)。 let-me-out是一个可执行的.py文件,我的文件夹中没有setup.py个文件或类似文件。

如何在测试中导入此功能?我的测试将是一个简单的工具,用以下方式检查时间:

@pytest.fixture
def now():
    return timezone.now()

然后使用now()函数创建一个let-me-out将在特定时间后删除的新文件。所有这些都是Python 2.7。

1 个答案:

答案 0 :(得分:2)

首先,破折号将let-me-out单词变为Python中的无效标识符。要解决它,你必须调用imp(Python 2.7)  或importlib(Python 3.5+)机制。

Python 3.5 +

以下是导入具有限定名称let_me_out但使用bin/let-me-out作为源文件的新模块的示例:

import importlib


def test_master_disaster():
    loader = importlib.machinery.SourceFileLoader('let_me_out', 'bin/let-me-out')
    spec = importlib.util.spec_from_loader(loader.name, loader)
    let_me_out = importlib.util.module_from_spec(spec)
    loader.exec_module(let_me_out)
    # this is only a stub, to show an example of calling the master_disaster function
    assert let_me_out.master_disaster() == 'spam'

您可以将此代码提取到灯具中以使其可重复使用:

import importlib
import pytest


@pytest.fixture(scope='session')
def let_me_out():
    loader = importlib.machinery.SourceFileLoader('let_me_out', 'bin/let-me-out')
    spec = importlib.util.spec_from_loader(loader.name, loader)
    let_me_out = importlib.util.module_from_spec(spec)
    loader.exec_module(let_me_out)
    return let_me_out


def test_master_disaster(let_me_out):
    assert let_me_out.master_disaster() == 'spam'

Python 2.7

使用Python 2.7,事情变得更加容易:

import imp
import pytest


@pytest.fixture(scope='session')
def let_me_out():
    return imp.load_source('let_me_out', 'bin/let-me-out')


def test_master_disaster(let_me_out):
    assert let_me_out.master_disaster() == 'spam'