0

As a unit test, I would like to be able to test that the imports defined in a bunch of GUI screens make sense programatically. I don't want to have to execute anything, just

import main_screen

and see if anything falls over during the chain of imports. I've got as far as using the sys.modules trick:

import my_fake_module
sys.modules['module_i_want_to_fake'] = my_fake_module

Which works great, up until something does:

from module_i_want_to_fake import real_attribute

Then of course I get an ImportError unless I add a stubbed out method/class to my_fake_module, but there are way too many to make this practical.

Is there some way to hook imports from my_fake_module so that they always succeed? Again, they don't need to do anything. I bet there's a simple way but it's escaping me at the moment...

jambox
  • 584
  • 4
  • 15
  • 1
    I'm not sure what you mean by `anything falls over´ but does `mymod = __import__("module_name")` help? you can call `reload(mymod)` and you can run tests on the variable? You can also modify the `__import__` function/method with your own and have fallbacks and error handling, even create dummy functions/stubs on the fly. – Torxed May 20 '13 at 12:53
  • by "anything falls over" i just mean see if there are broken references, typos, etc, but I may expand it to find orphans and some other analysis. Yes, overriding `__import__` sounds good but I can't figure it out or google it up so far. Maybe I need to do the PEP302 thing by creating a new importer. – jambox May 20 '13 at 13:09

1 Answers1

1

One option is to create a custom FakeModule class which handles __getattr__ and hands out appropriately stubbed functions/values:

>>> class FakeModule:
...     def __getattr__(self, name):
...         print name
...         return name
...
>>> sys.modules['fakeModule'] = FakeModule()
>>> from fakeModule import something
__path__
something
something
>>> something
'something'

The actual code would need a little more thought than the quick proof of concept above, perhaps returning a lambda, so you can at least execute the imported value.

You might want to do something like this:

from functools import wraps

class FakeModule(object):
    def __init__(self):
        self.module = __import__("module_to_fake")

    @staticmethod
    def __testWrapper(fn):
        @wraps(fn)
        def wrapped(*args):
            print "%s called with args %s" % (fn.__name__, args)
            result = fn(*args)
            print "    Result was %s" % (result,)
            return result
        return wrapped

    def __getattr__(self, name):
        try:
            result = getattr(module, name)
        except AttributeError:
            print "tried to get %s, which does not exist" % name
            result = None

        if hasattr(result, "__call__"):
            result = self.__testWrapper(result)

        return result
RoadieRich
  • 6,330
  • 3
  • 35
  • 52
  • Yeah, kinda. I think the key to my understanding was that I needed to understand that I had to wrap the module in a class in order to override the magic methods. All I had to do was subvert a couple of sub-modules in that package by name, so they worked in a unit-test context, in the end. See also: http://stackoverflow.com/a/2447383/455916 – jambox May 22 '13 at 13:44