I am trying to write tests with nose that get set up with something
calculated using multiprocessing.
I have this directory structure:
code/tests/tests.py
tests.py looks like this:
import multiprocessing as mpdef f(i):return i ** 2pool = mp.Pool()
out = pool.map(f, range(10))def test_pool():"""Really simple test that relies on the output of pool.map.The actual tests are much more complicated, but this is allthat is needed to produce the problem."""ref_out = map(f, range(10))assert out == ref_outif __name__ == '__main__':test_pool()
Running from the code
directory, python tests/tests.py
passes.
nosetests tests/tests.py
fails to complete. It starts up, but never gets through the call to pool.map
and just hangs.
Why is this and what is the simplest solution?
The problem is related to the fact that pool.map
is called at the "global level". Normally you want to avoid that, because these statements will be executed even if your file is simply imported.
Nose has to import your module to be able to find your tests and later execute them, therefore I believe the problem happens while the import mechanism kicks in (I haven't spent time trying to find out the exact reason for this behaviour)
You should move your initialization code to a test fixture instead; Nose supports fixtures with the with_setup
decorator. Here is one possibility (probably the simplest change while keeping pool
and out
as globals):
import multiprocessing as mp
from nose import with_setuppool = None
out = Nonedef f(i):return i ** 2def setup_func():global poolglobal outpool = mp.Pool()out = pool.map(f, range(10))@with_setup(setup_func)
def test_pool():"""Really simple test that relies on the output of pool.map.The actual tests are much more complicated, but this is allthat is needed to produce the problem."""global outref_out = map(f, range(10))assert out == ref_outif __name__ == '__main__':test_pool()
Executing:
$ nosetests tests/tests.py
.
----------------------------------------------------------------------
Ran 1 test in 0.011sOK