Подтвердить что ты не робот

Могу ли я "подделать" пакет (или хотя бы модуль) в python для тестирования?

Я хочу подделать пакет в python. Я хочу что-то определить, чтобы код мог выполнять

from somefakepackage.morefakestuff import somethingfake

И somefakepackage определяется в коде, и все под ним. Это возможно? Причина этого заключается в том, чтобы обмануть мой unittest, что я получил пакет (или, как я сказал в названии, модуль) в пути python, который на самом деле просто что-то издевается над этим unittest.

Спасибо!

4b9b3361

Ответ 1

Конечно. Определите класс, поместите нужный материал внутри него, присвойте классу sys.modules["classname"].

class fakemodule(object):

    @staticmethod
    def method(a, b):
        return a+b

import sys
sys.modules["package.module"] = fakemodule

Вы также можете использовать отдельный модуль (назовите его fakemodule.py):

import fakemodule, sys

sys.modules["package.module"] = fakemodule

Ответ 2

Да, вы можете создать поддельный модуль:

from types import ModuleType
m = ModuleType("fake_module")

import sys
sys.modules[m.__name__] = m

# some scripts may expect a file
# even though this file doesn't exist,
# it may be used by Python for in error messages or introspection.
m.__file__ = m.__name__ + ".py"

# Add a function
def my_function():
    return 10

m.my_function = my_function

Обратите внимание, что в этом примере используется фактический модуль (ModuleType), поскольку некоторые Код Python может ожидать модули, (а не фиктивный класс).

Это можно сделать в служебную функцию:

def new_module(name, doc=None):
    import sys
    from types import ModuleType
    m = ModuleType(name, doc)
    m.__file__ = name + '.py'
    sys.modules[name] = m
    return m

print(new_module("fake_module", doc="doc string"))

Теперь могут выполняться другие скрипты:

import fake_module

Ответ 3

Вы можете подделать его классом, который ведет себя как somethingfake:

try:
    from somefakepackage.morefakestuff import somethingfake
except ImportError:
    class somethingfake(object):
         # define what you'd expect of somethingfake, e.g.:
         @staticmethod
         def somefunc():
             ...
         somefield = ...

Ответ 4

Я взял некоторые идеи из других ответов и превратил их в декоратор Python @modulize, который преобразует функцию в модуль. Этот модуль можно импортировать, как обычно. Вот пример.

@modulize('my_module')
def my_dummy_function(__name__):  # the function takes one parameter __name__
    # put module code here
    def my_function(s): 
        print(s, 'bar')

    # the function must return locals()
    return locals()

# import the module as usual
from my_module import my_function
my_function('foo') # foo bar

Код декоратора выглядит следующим образом

import sys
from types import ModuleType

class MockModule(ModuleType):
    def __init__(self, module_name, module_doc=None):
        ModuleType.__init__(self, module_name, module_doc)
        if '.' in module_name:
            package, module = module_name.rsplit('.', 1)
            get_mock_module(package).__path__ = []
            setattr(get_mock_module(package), module, self)

    def _initialize_(self, module_code):
        self.__dict__.update(module_code(self.__name__))
        self.__doc__ = module_code.__doc__

def get_mock_module(module_name):
    if module_name not in sys.modules:
        sys.modules[module_name] = MockModule(module_name)
    return sys.modules[module_name]

def modulize(module_name, dependencies=[]):
    for d in dependencies: get_mock_module(d)
    return get_mock_module(module_name)._initialize_

Проект можно найти здесь, на GitHub. В частности, я создал это для соревнований по программированию, которые позволяют конкурсанту подавать только один файл .py. Это позволяет разработать проект с несколькими .py файлами, а затем объединить их в один файл .py в конце.