简体   繁体   中英

how to import function in pytest

I am trying to create a pytest for a Python 2.x script executable with dashes included in its name. I tried to import it the usual way but I can't figure out how to make it work with the dashes.

My project structure is as follows:

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

Specifically, I need to test a function called master_disaster() which exists inside bin/let-me-out (yes with - ). let-me-out is an executable .py file and my folder has no setup.py file or anything similar.

How can I import this function inside my test? My test is going to be a simple fixture that checks the time with:

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

It then uses the now() function to create a new file which let-me-out will delete after a specific amount of time.

First of all, dashes make let-me-out word to an invalid identifier in Python. To work around it, you have to invoke the imp (Python 2.7) or importlib (Python 3.5+) machinery.

Python 3.5+

Here is an example of importing a new module having a qualified name let_me_out , but using bin/let-me-out as source file:

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'

You can extract this code into a fixture to make it reusable:

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

Things are even easier with 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'

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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