Python, unit-testing and mocking imports
I am in a project where we are starting refactoring some massive code base. One problem that immediately sprang up is that each file imports a lot of other files. How do I in an elegant way mock this in my unit test without having to alter the actual code so I can start to write unit-tests?
As an example: The file with the functions I want to test, imports ten other files which is part of our software and not python core libs.
I want to be able to run the unit tests as separately as possible and for now I am only going to test functions that does not depend on things from the files that are being imported.
Thanks for all the answers.
I didn't really know what I wanted to do from the start but now I think I know.
Problem was that some imports was only possible when the whole application was running because of some third-party auto-magic. So I had to make some stubs for these modules in a directory which I pointed out with sys.path
Now I can import the file which contains the functions I want to write tests for in my unit-test file without complaints about missing modules.
Asked by: Roman479 | Posted: 28-01-2022
Answer 1
If you want to import a module while at the same time ensuring that it doesn't import anything, you can replace the __import__
builtin function.
For example, use this class:
class ImportWrapper(object):
def __init__(self, real_import):
self.real_import = real_import
def wrapper(self, wantedModules):
def inner(moduleName, *args, **kwargs):
if moduleName in wantedModules:
print "IMPORTING MODULE", moduleName
self.real_import(*args, **kwargs)
else:
print "NOT IMPORTING MODULE", moduleName
return inner
def mock_import(self, moduleName, wantedModules):
__builtins__.__import__ = self.wrapper(wantedModules)
try:
__import__(moduleName, globals(), locals(), [], -1)
finally:
__builtins__.__import__ = self.real_import
And in your test code, instead of writing import myModule
, write:
wrapper = ImportWrapper(__import__)
wrapper.mock_import('myModule', [])
The second argument to mock_import
is a list of module names you do want to import in inner module.
This example can be modified further to e.g. import other module than desired instead of just not importing it, or even mocking the module object with some custom object of your own.
Answered by: Grace741 | Posted: 01-03-2022Answer 2
If you really want to muck around with the python import mechanism, take a look at the ihooks
module. It provides tools for changing the behavior of the __import__
built-in. But it's not clear from your question why you need to do this.
Answer 3
"imports a lot of other files"? Imports a lot of other files that are part of your customized code base? Or imports a lot of other files that are part of the Python distribution? Or imports a lot of other open source project files?
If your imports don't work, you have a "simple" PYTHONPATH
problem. Get all of your various project directories onto a PYTHONPATH
that you can use for testing. We have a rather complex path, in Windows we manage it like this
@set Part1=c:\blah\blah\blah
@set Part2=c:\some\other\path
@set that=g:\shared\stuff
set PYTHONPATH=%part1%;%part2%;%that%
We keep each piece of the path separate so that we (a) know where things come from and (b) can manage change when we move things around.
Since the PYTHONPATH
is searched in order, we can control what gets used by adjusting the order on the path.
Once you have "everything", it becomes a question of trust.
Either
- you trust something (i.e., the Python code base) and just import it.
Or
You don't trust something (i.e., your own code) and you
- test it separately and
- mock it for stand-alone testing.
Would you test the Python libraries? If so, you've got a lot of work. If not, then, you should perhaps only mock out the things you're actually going to test.
Answered by: Audrey934 | Posted: 01-03-2022Answer 4
No difficult manipulation is necessary if you want a quick-and-dirty fix before your unit-tests.
If the unit tests are in the same file as the code you wish to test, simply delete unwanted module from the globals()
dictionary.
Here is a rather lengthy example: suppose you have a module impp.py
with contents:
value = 5
Now, in your test file you can write:
>>> import impp
>>> print globals().keys()
>>> def printVal():
>>> print impp.value
['printVal', '__builtins__', '__file__', 'impp', '__name__', '__doc__']
Note that impp
is among the globals, because it was imported. Calling the function printVal
that uses impp
module still works:
>>> printVal()
5
But now, if you remove impp
key from globals()
...
>>> del globals()['impp']
>>> print globals().keys()
['printVal', '__builtins__', '__file__', '__name__', '__doc__']
...and try to call printVal()
, you'll get:
>>> printVal()
Traceback (most recent call last):
File "test_imp.py", line 13, in <module>
printVal()
File "test_imp.py", line 5, in printVal
print impp.value
NameError: global name 'impp' is not defined
...which is probably exactly what you're trying to achieve.
To use it in your unit-tests, you can delete the globals just before running the test suite, e.g. in __main__
:
if __name__ == '__main__':
del globals()['impp']
unittest.main()
Answered by: Thomas306 | Posted: 01-03-2022
Answer 5
In your comment above, you say you want to convince python that certain modules have already been imported. This still seems like a strange goal, but if that's really what you want to do, in principle you can sneak around behind the import mechanism's back, and change sys.modules
. Not sure how this'd work for package imports, but should be fine for absolute imports.
Similar questions
Python unit-testing with nose: Making sequential tests
I am just learning how to do unit-testing. I'm on Python / nose / Wing IDE.
(The project that I'm writing tests for is a simulations framework, and among other things it lets you run simulations both synchronously and asynchronously, and the results of the simulation should be the same in both.)
The thing is, I want some of my tests to use simulat...
python - Unit-testing extensions for an 'external' program with pyunit
I'm struggling to know where to start with unittest, having read the dive-into-python tutorial and looked at http://pyunit.sourceforge.net/.
I've got a piece of analysis software (call it 'prog.exe') which uses python for its input decks. I've started writing a python module which I'm going to import from that input deck to provide some useful functionali...
python - Tunnel interface unit-testing
I've made a Tun class that wraps pytun.TunTapDevice :
from pytun import TunTapDevice
class Tun(object):
def __init__(self,name='tun',addr=None,dstaddr=None,netmask=None,mtu=None):
tun = TunTapDevice(name=name)
if addr : tun.addr = addr
if dstaddr : tun.dstaddr = dstaddr
if netmask : ...
python - Flask blueprint unit-testing
Is there a good practice to unit-test a flask blueprint?
http://flask.pocoo.org/docs/testing/
I didn't found something that helped me or that is simple enough.
// Edit
Here are my code:
# -*- coding: utf-8 -*-
import sys
import os
import unittest
import flask
sys.path = [os.path.abspath('')] + sys.path
from ap...
python - Django unit-testing client.login not working
I am using django 1.6 and I have the following test code:
def tes_stuff(self):
new_user=EndUser.objects.create(username="test", firstname="test", email="t@t.com", password="test")
self.assertTrue(self.client.login(username="test", password="test"))
When I run it I get an arror that says:
AssertionError: False is not true
I am unsure why it is not l...
Is there a preferred BDD style unit-testing framework for Python?
I was wondering if there are any BDD-style 'describe-it' unit-testing frameworks for Python that are maintained and production ready. I have found describe, but it doesn't seem to be maintained and has no documentation. I've also found sure which reached 1.0, but it seems to just add syntactic sugar i...
Python Unit-Testing All Test Cases
I am running unit tests on pycharm but some how am discovering something weird. When I started testing a class, more specifically its methods, I simply wrote test cases like the following:
# hey.py
class hey:
def hello(self):
return True
def bye(self):
return 'Bye'
# test_hey.py
from unittest import TestCase
class TestHey(TestCase):
def test_hello(self):
self.fail()
...
python - Unit-Testing Flask application views & dialogs
I am new to Flask and have recently started working on a project. After I've fixed some issues related to dialogs and views the client asked to write unittests to verify the resolutions. I've gone through some already written tests but they mostly just check the status code of http response, like this:
def test_home_page(self):
rv = self.client.get('/home')
self.assertEqual(rv._status_code, 200, rv....
What's the right way of unit-testing a python class?
I'm not sure what's the best way to build independent unit tests on methods of a python class. Here is a trivial example:
class MyClass(object):
def __init__(self, data):
self.data = data
def myMethod(self):
#do something
return True
I'm building unit tests like this:
class TestMyClass(unittest.TestCase):
def test_init(self):
mydata = mock.Mock()
...
django - Unit-testing Python: Mocking function calls inside function
I have a django view like this
# Django view
from some_module import f2
def f1(request, version):
# some code
f2(**kargs)
# more code
return HTTPResponse(response)
The function f2 is in another module
# some_module
def f2(**kargs):
# some code
The Django view is part of an API so, the request and response are in json
How do I...
Still can't find your answer? Check out these communities...
PySlackers | Full Stack Python | NHS Python | Pythonist Cafe | Hacker Earth | Discord Python