implementing my own test runner

66 views
Skip to first unread message

Andrea Crotti

unread,
Jan 11, 2012, 11:50:08 AM1/11/12
to nose-...@googlegroups.com
I've spent already a lot of time on this and it should actually be easy, so
maybe you can give me an hand.

I want to do something simple, which is running tests from another python
program.

What is should do is quite the same as the normal nosetests, so collect
all the test modules and run them.
All the things I've tried until now didn't find/run any tests unfortunately,
and here is the last attempt:

class NoseTestRunner(object):
def egg_runner(self, eggpath):
conf = Config()
# it must be a tuple even if it's not really supported
conf.where = (eggpath, )
return TestProgram(config=conf)


Where I found out in the config module that where is the path where
the test modules should be looked for..
Any idea of what I'm missing?

Thanks,
Andrea

jason pellerin

unread,
Jan 11, 2012, 2:27:12 PM1/11/12
to nose-...@googlegroups.com
Does this help?

http://readthedocs.org/docs/nose/en/latest/api/core.html#nose.core.run

Or have you already tried nose.run()?

JP

> --
> You received this message because you are subscribed to the Google Groups
> "nose-users" group.
> To post to this group, send email to nose-...@googlegroups.com.
> To unsubscribe from this group, send email to
> nose-users+...@googlegroups.com.
> For more options, visit this group at
> http://groups.google.com/group/nose-users?hl=en.
>

Andrea Crotti

unread,
Jan 12, 2012, 5:28:46 AM1/12/12
to nose-...@googlegroups.com
On 01/11/2012 07:27 PM, jason pellerin wrote:
> Does this help?
>
> http://readthedocs.org/docs/nose/en/latest/api/core.html#nose.core.run
>
> Or have you already tried nose.run()?
>
> JP


It's actually the same as TestProgram, just exit is set to False, and
I get the same result, something like..

Ok

run 0 tests...


From the same directory running nosetest instead works perfectly, and
I thought I was doing the same thing.

Is there a way to get more debug output from the loader to see what
it's actually looking for and discarding eventually?
(Because it takes quite some time anyway to run the command).

Andrea Crotti

unread,
Jan 12, 2012, 5:41:23 AM1/12/12
to nose-...@googlegroups.com
On 01/12/2012 10:28 AM, Andrea Crotti wrote:
>
>
> It's actually the same as TestProgram, just exit is set to False, and
> I get the same result, something like..
>
> Ok
>
> run 0 tests...
>
>
> From the same directory running nosetest instead works perfectly, and
> I thought I was doing the same thing.
>
> Is there a way to get more debug output from the loader to see what
> it's actually looking for and discarding eventually?
> (Because it takes quite some time anyway to run the command).

I found the problem, even if not understood yet, and it's in the code
calling
that class, if made more stupid everything works.

Andrea Crotti

unread,
Jan 12, 2012, 5:46:37 AM1/12/12
to nose-...@googlegroups.com
On 01/12/2012 10:41 AM, Andrea Crotti wrote:
>
> I found the problem, even if not understood yet, and it's in the code
> calling
> that class, if made more stupid everything works.

I maybe understood, is nose using the sys.argv even as when called from
another python
program.

Because I had something like
run_tests.py -m simple <directory to test>

And I was passing myself <directory to test> as where, but removing
"-m simple" actually works, and more surprisingly also not handling myself
<directory to test> works, so it's clear that someone else is using
the sys.argv after me, how do I avoid that?
Thanks

Olivier Delalleau

unread,
Jan 12, 2012, 7:17:09 AM1/12/12
to nose-...@googlegroups.com
2012/1/12 Andrea Crotti <andrea....@gmail.com>

I think you should be using the argv argument to run:

argv: Command line arguments (default: None; sys.argv is read)

-=- Olivier

Andrea Crotti

unread,
Jan 13, 2012, 8:28:59 AM1/13/12
to nose-...@googlegroups.com, Olivier Delalleau
On 01/12/2012 12:17 PM, Olivier Delalleau wrote:
>
> I think you should be using the argv argument to run:
>
> argv: Command line arguments (default: None; sys.argv is read)

That worked fine actually thanks, now I have another problem though.
Running from nosetests everything work correctly, but with my own very
stupid
wrapper I get something like:

File
"h:\git_projs\Psi\psi.devsonly\psi\devsonly\test\test_wrapper.py", line
1, in <module>
import psi.devsonly.setup_wrapper as sw
AttributeError: 'module' object has no attribute 'setup_wrapper'


And the wrapper is simply this


class NoseTestRunner(object):
def egg_runner(self, eggpath):
conf = Config()

conf.verbosity = True
return TestProgram(argv=argv[:1], defaultTest=eggpath)


Which makes me think that the importer used is somehow different and
smarter when running nosetests... What can this be then?
Thanks..

Olivier Delalleau

unread,
Jan 13, 2012, 9:36:04 AM1/13/12
to nose-...@googlegroups.com
2012/1/13 Andrea Crotti <andrea....@gmail.com>

My first guess would be that your import order is such that devsonly.setup_wrapper has not been defined yet when you reach the line that tries to import it. It's hard to tell for sure what's going on without having access to the code though, but this looks like a circular import issue.

-=- Olivier

Andrea Crotti

unread,
Jan 13, 2012, 9:47:50 AM1/13/12
to nose-...@googlegroups.com, Olivier Delalleau
On 01/13/2012 02:36 PM, Olivier Delalleau wrote:
>
> My first guess would be that your import order is such that
> devsonly.setup_wrapper has not been defined yet when you reach the
> line that tries to import it. It's hard to tell for sure what's going
> on without having access to the code though, but this looks like a
> circular import issue.
>
> -=- Olivier
>

Mm no I don't think is the issue, but I found something really
interesting debugging
with PDB.

If I do from the pdb shell:
import psi.devsonly.setup_wrapper

it works
if I do
import psi.devsonly.setup_wrapper as sw
it doesn't with a "module object has no attribute setup_wrapper" , while
they both work perfectly from IPython.

And more strangely they actually work if just running nosetests.
So what can be different in the two cases?

Olivier Delalleau

unread,
Jan 13, 2012, 10:07:30 AM1/13/12
to nose-...@googlegroups.com
2012/1/13 Andrea Crotti <andrea....@gmail.com>

Ok, hmm... tbh the way Python imports stuff has often been confusing to me, and I remember seeing such oddifies and never really being able to figure out what was going on.
Try to add to psi/devsonly/__init__.py the following line, see if it helps:
from psi.devsonly import setup_wrapper

-=- Olivier

Andrea Crotti

unread,
Jan 13, 2012, 10:27:03 AM1/13/12
to nose-...@googlegroups.com, Olivier Delalleau
On 01/13/2012 03:07 PM, Olivier Delalleau wrote:
>
> Try to add to psi/devsonly/__init__.py the following line, see if it
> helps:
> from psi.devsonly import setup_wrapper
>
> -=- Olivier
> Ok, hmm... tbh the way Python imports stuff has often been confusing
> to me, and I remember seeing such oddifies and never really being able
> to figure out what was going on.
>
I actually have some experience with the import mechanisms actually, but
never seen such a thing before (probably it's easy to fix though).

I added a print statement just before it fails to see what it does
(it's this "mod = load_module(part_fqname, fh, filename, desc)"
from the importer.py module by the way).

And I get the following:

Running nosetests
--8<---------------cut here---------------start------------->8---
trying to import psi, None, H:\git_projs\Psi\psi.devsonly\psi, ('', '', 5)
trying to import psi.devsonly, None,
H:\git_projs\Psi\psi.devsonly\psi\devsonly,
('', '', 5)
--8<---------------cut here---------------end--------------->8---

And all the tests run and pass

Running my wrapper (which is simply):
--8<---------------cut here---------------start------------->8---


class NoseTestRunner(object):
def egg_runner(self, eggpath):
conf = Config()

conf.verbosity = 3
return TestProgram(argv=argv[:1], defaultTest=eggpath, config=conf)
--8<---------------cut here---------------end--------------->8---

I get instead:

--8<---------------cut here---------------start------------->8---
running mode simple
trying to import psi, None, H:\git_projs\Psi\psi.devsonly\psi, ('', '', 5)
trying to import psi.devsonly, None,
H:\git_projs\Psi\psi.devsonly\psi\devsonly,
('', '', 5)
trying to import psi.devsonly.bin, None,
H:\git_projs\Psi\psi.devsonly\psi\devso
nly\bin, ('', '', 5)

======================================================================
ERROR: Failure: AttributeError ('module' object has no attribute 'walk')
----------------------------------------------------------------------
Traceback (most recent call last):
File
"c:\python25\lib\site-packages\nose-0.10.3n1-py2.5-win32.egg\nose\loader.
py", line 364, in loadTestsFromName
addr.filename, addr.module)
File
"c:\python25\lib\site-packages\nose-0.10.3n1-py2.5-win32.egg\nose\importe
r.py", line 39, in importFromPath
return self.importFromDir(dir_path, fqname)
File
"c:\python25\lib\site-packages\nose-0.10.3n1-py2.5-win32.egg\nose\importe
r.py", line 85, in importFromDir
mod = load_module(part_fqname, fh, filename, desc)
File "h:\git_projs\Psi\psi.devsonly\psi\devsonly\test\test_walk.py",
line 3, i
n <module>
import psi.devsonly.walk as w
AttributeError: 'module' object has no attribute 'walk'
--8<---------------cut here---------------end--------------->8---

The only difference is that it tries also to load the bin directory, but
why does it behave in a different way in the first place then?

Andrea Crotti

unread,
Jan 13, 2012, 10:50:37 AM1/13/12
to nose-...@googlegroups.com, Olivier Delalleau
Even more strangely on Linux where I have a more recent version of nose
I get these paths attempted to import (which also seems more correct),
but the nosetests on windows also works, that's the strange thing..

('got ', 'psi.devsonly.test', None,
'/home/andrea/git_projs/Psi/psi.devsonly/psi/devsonly/test', ('', '', 5))
('got ', 'psi.devsonly.test.other_deps', None,
'/home/andrea/git_projs/Psi/psi.devsonly/psi/devsonly/test/other_deps',
('', '', 5))
('got ', 'psi.devsonly.test.other_deps.dep1', None,
'/home/andrea/git_projs/Psi/psi.devsonly/psi/devsonly/test/other_deps/dep1',
('', '', 5))
('got ', 'psi.devsonly.test.other_deps.dep2', None,
'/home/andrea/git_projs/Psi/psi.devsonly/psi/devsonly/test/other_deps/dep2',
('', '', 5))
('got ', 'psi.devsonly.test.test_analyze', <open file
'/home/andrea/git_projs/Psi/psi.devsonly/psi/devsonly/test/test_analyze.py',
mode 'U' at 0x12ddae0>,
'/home/andrea/git_projs/Psi/psi.devsonly/psi/devsonly/test/test_analyze.py',
('.py', 'U', 1))
('got ', 'psi.devsonly.test.test_checksums', <open file
'/home/andrea/git_projs/Psi/psi.devsonly/psi/devsonly/test/test_checksums.py',
mode 'U' at 0x12ddae0>,
'/home/andrea/git_projs/Psi/psi.devsonly/psi/devsonly/test/test_checksums.py',
('.py', 'U', 1))
('got ', 'psi.devsonly.test.test_dev_main', <open file
'/home/andrea/git_projs/Psi/psi.devsonly/psi/devsonly/test/test_dev_main.py',
mode 'U' at 0x12ddae0>,
'/home/andrea/git_projs/Psi/psi.devsonly/psi/devsonly/test/test_dev_main.py',
('.py', 'U', 1))
('got ', 'psi.devsonly.test.test_egg', <open file
'/home/andrea/git_projs/Psi/psi.devsonly/psi/devsonly/test/test_egg.py',
mode 'U' at 0x12ddae0>,
'/home/andrea/git_projs/Psi/psi.devsonly/psi/devsonly/test/test_egg.py',
('.py', 'U', 1))
('got ', 'psi.devsonly.test.test_environment', <open file
'/home/andrea/git_projs/Psi/psi.devsonly/psi/devsonly/test/test_environment.py',
mode 'U' at 0x12ddae0>,
'/home/andrea/git_projs/Psi/psi.devsonly/psi/devsonly/test/test_environment.py',
('.py', 'U', 1))
('got ', 'psi.devsonly.test.test_history', <open file
'/home/andrea/git_projs/Psi/psi.devsonly/psi/devsonly/test/test_history.py',
mode 'U' at 0x12ddae0>,
'/home/andrea/git_projs/Psi/psi.devsonly/psi/devsonly/test/test_history.py',
('.py', 'U', 1))
('got ', 'psi.devsonly.test.test_imports', <open file
'/home/andrea/git_projs/Psi/psi.devsonly/psi/devsonly/test/test_imports.py',
mode 'U' at 0x12ddae0>,
'/home/andrea/git_projs/Psi/psi.devsonly/psi/devsonly/test/test_imports.py',
('.py', 'U', 1))
('got ', 'psi.devsonly.test.test_pathfixer', <open file
'/home/andrea/git_projs/Psi/psi.devsonly/psi/devsonly/test/test_pathfixer.py',
mode 'U' at 0x12ddae0>,
'/home/andrea/git_projs/Psi/psi.devsonly/psi/devsonly/test/test_pathfixer.py',
('.py', 'U', 1))
('got ', 'psi.devsonly.test.test_problem', <open file
'/home/andrea/git_projs/Psi/psi.devsonly/psi/devsonly/test/test_problem.py',
mode 'U' at 0x12ddae0>,
'/home/andrea/git_projs/Psi/psi.devsonly/psi/devsonly/test/test_problem.py',
('.py', 'U', 1))
('got ', 'psi.devsonly.test.test_remove_eggs', <open file
'/home/andrea/git_projs/Psi/psi.devsonly/psi/devsonly/test/test_remove_eggs.py',
mode 'U' at 0x12ddae0>,
'/home/andrea/git_projs/Psi/psi.devsonly/psi/devsonly/test/test_remove_eggs.py',
('.py', 'U', 1))
('got ', 'psi.devsonly.test.test_utils', <open file
'/home/andrea/git_projs/Psi/psi.devsonly/psi/devsonly/test/test_utils.py',
mode 'U' at 0x12ddae0>,
'/home/andrea/git_projs/Psi/psi.devsonly/psi/devsonly/test/test_utils.py',
('.py', 'U', 1))
('got ', 'psi.devsonly.test.test_walk', <open file
'/home/andrea/git_projs/Psi/psi.devsonly/psi/devsonly/test/test_walk.py', mode
'U' at 0x12ddae0>,
'/home/andrea/git_projs/Psi/psi.devsonly/psi/devsonly/test/test_walk.py', ('.py',
'U', 1))
('got ', 'psi.devsonly.test.test_wrapper', <open file
'/home/andrea/git_projs/Psi/psi.devsonly/psi/devsonly/test/test_wrapper.py',
mode 'U' at 0x12ddae0>,
'/home/andrea/git_projs/Psi/psi.devsonly/psi/devsonly/test/test_wrapper.py',
('.py', 'U', 1))

Andrea Crotti

unread,
Jan 16, 2012, 6:23:15 AM1/16/12
to nose-...@googlegroups.com, Olivier Delalleau
I'm still not quite sure about what's going on unfortunately, to summarize,
nosetests and run_tests.py (my script) work perfectly on Linux with
python 2.7,
while run_tests.py doesn't work on Windows.

I checked all the values that are passed to the TestProgram class in
Unittest,
and they are all the same.

The only thing which I might think problematic is the different
implementation
of the TestProgram in the different versions of unittest.
These are the two different versions..
Any clue about what could cause the import problems??


# new version
class TestProgram(object):
failfast = catchbreak = buffer = progName = None

def __init__(self, module='__main__', defaultTest=None, argv=None,
testRunner=None, testLoader=loader.defaultTestLoader,
exit=True, verbosity=1, failfast=None, catchbreak=None,
buffer=None):
if isinstance(module, basestring):
self.module = __import__(module)
for part in module.split('.')[1:]:
self.module = getattr(self.module, part)
else:
self.module = module
if argv is None:
argv = sys.argv

self.exit = exit
self.failfast = failfast
self.catchbreak = catchbreak
self.verbosity = verbosity
self.buffer = buffer
self.defaultTest = defaultTest
self.testRunner = testRunner
self.testLoader = testLoader
self.progName = os.path.basename(argv[0])
self.parseArgs(argv)
self.runTests()

# old version
class TestProgram:
def __init__(self, module='__main__', defaultTest=None,
argv=None, testRunner=None, testLoader=defaultTestLoader):
if type(module) == type(''):
self.module = __import__(module)
for part in module.split('.')[1:]:
self.module = getattr(self.module, part)
else:
self.module = module
if argv is None:
argv = sys.argv
self.verbosity = 1
self.defaultTest = defaultTest
self.testRunner = testRunner
self.testLoader = testLoader
self.progName = os.path.basename(argv[0])
self.parseArgs(argv)
self.runTests()


Reply all
Reply to author
Forward
0 new messages