Making errors eclipse-friendly

52 views
Skip to first unread message

Andrea Crotti

unread,
Jan 16, 2012, 10:31:26 AM1/16/12
to nose-...@googlegroups.com
I have to integrate nose output with Eclipse.
It would be maybe nicer to find a way to integrate PyDev but since it
looks way more complicated
and not everyone is using PyDev here, I think I have to stick with a
more hand-made thing.

What I need is very simple, output for every error something that
Eclipse is able to parse in the form
for example filename:line.

I didn't find any doc about how to do these kind of things, so I started
to do something like this:

class MyRunner(object):
def egg_runner(self, eggpath):
conf = Config()
conf.verbosity = 3
eclipse_runner = EclipseFriendlyRunner(stream=conf.stream,

verbosity=conf.verbosity, # why should I pass the config too in theory??
config=conf
)
# and with this the verbosity should be set correctly
TestProgram(argv=argv[:1], config=conf, defaultTest=eggpath,
testRunner=eclipse_runner)


class EclipseFriendlyRunner(TextTestRunner):

def _makeResult(self):
return EclipseFriendlyResult(self.stream,
self.descriptions,
self.verbosity,
self.config)


class EclipseFriendlyResult(TextTestResult):

def addError(self, test, err):
print("this is from my eclipse friendly runner")
super(EclipseFriendlyResult, self).addError(test, err)


But my print statement is never called even in case of errors.
Anyway in general does it make sense what I'm doing?
Seems that overriding _makeResult should not be a good thing to do,
but I didn't see anything better..

And another question, has the API been stable enough through versions
(past and future) or I am going to run into troubles?

Andrea Crotti

unread,
Jan 16, 2012, 10:47:31 AM1/16/12
to nose-...@googlegroups.com
On 01/16/2012 03:31 PM, Andrea Crotti wrote:
> I have to integrate nose output with Eclipse.
> It would be maybe nicer to find a way to integrate PyDev but since it
> looks way more complicated
> and not everyone is using PyDev here, I think I have to stick with a
> more hand-made thing.
>
> What I need is very simple, output for every error something that
> Eclipse is able to parse in the form
> for example filename:line.
> ...

From some analysis looks like it's not a great idea, I probably should
write a plugin and enable it,
is that right?

Andrea Crotti

unread,
Jan 16, 2012, 11:51:15 AM1/16/12
to nose-...@googlegroups.com
On 01/16/2012 03:47 PM, Andrea Crotti wrote:
>
> From some analysis looks like it's not a great idea, I probably should
> write a plugin and enable it,
> is that right?

I'm trying to write my own plugin and looking here and there I get the
following (at the moment).
The thing is that I'm not quite sure how to enable it, and how to get
the output of the plugin to
substitute the normal output.

For example xunit only allows to write on a separate file and the output
remains untouched,
so how do I just susbtitute the default formatter in general?

class EclipseFriendlyPlugin(Plugin):
"""Nose plugin to output errors in a format that is easily parsable
by Eclipse
"""

name = 'eclipse_friendly'
encoding = 'UTF-8'

def __init__(self):
self.errorlist = []
super(EclipseFriendlyPlugin, self).__init__()

def _format_error(self, level, test, err):
fname, lineno = _location_from_traceback(err)
return "%s %s: (%s:%d)" % (level, test.id(), fname, lineno)

def options(self, parser, env=os.environ):
super(EclipseFriendlyPlugin, self).options(parser, env=env)

def configure(self, options, config):
"""Configures the xunit plugin."""
Plugin.configure(self, options, config)
self.config = config
if self.enabled:
self.stats = {
'errors': 0,
'failures': 0,
'passes': 0,
'skipped': 0
}

def addError(self, test, err, capt=None):
if issubclass(err[0], SkipTest):
err_type = 'skipped'
self.stats['skipped'] += 1
else:
err_type = 'error'
self.stats['errors'] += 1

self.errorlist.append(self._format_error("error", test, err))

def addFailure(self, test, err):
self.stats['failures'] += 1
msg = self._format_error("failure", test, err)
self.errorlist.append(msg)

Andrea Crotti

unread,
Jan 17, 2012, 10:40:04 AM1/17/12
to nose-...@googlegroups.com
I cleaned up the code a little bit, and here it's what it looks like.
I don't actually want to add options to the option parser or any other
fancy thing,
I just want to make sure that this plugin is enabled and the default output
is substituted with the one given by this plugin.

I can't find, however, a single helpful example or a hint about how to do it
(and I would be pleased to share my code in the nose website when it's
working).

Any suggestions?

class NoseTestRunner(object):
def egg_runner(self, eggpath):
"""Run all the tests in the given egg


"""
conf = Config()
conf.verbosity = 3

ep = EclipseFriendlyPlugin()
# how do I make sure the plugin is actually loaded and doing
something?
ep.enabled = True
# how do I actually enable it?
plugins = [ep]


# and with this the verbosity should be set correctly

# should use addplugins instead if they are not "default" plugins


TestProgram(argv=argv[:1], config=conf, defaultTest=eggpath,

plugins=plugins)


class EclipseFriendlyPlugin(Plugin):
"""Nose plugin to output errors in a format that is easily parsable
by Eclipse
"""

name = 'eclipse_friendly'
encoding = 'UTF-8'

def __init__(self):
self.errorlist = []
self.successlist = []
super(EclipseFriendlyPlugin, self).__init__()

def _format_error(self, level, test, err):
fname, lineno = _location_from_traceback(err)
return "%s %s: (%s:%d)" % (level, test.id(), fname, lineno)

def options(self, parser, env=os.environ):
super(EclipseFriendlyPlugin, self).options(parser, env=env)

def configure(self, options, config):
"""Configures the xunit plugin."""
Plugin.configure(self, options, config)

def addError(self, test, err, capt=None):
# if returning something other plugins will not see the error
raised


self.errorlist.append(self._format_error("error", test, err))

def addFailure(self, test, err):
self.errorlist.append(self._format_error("failure", test, err))

def addSuccess(self, test):
self.successlist.append(test.id())

def report(self, stream):
# should I force the unicode here too maybe or not care about it?
for error in self.errorlist:
stream.writeln(error)

Andrea Crotti

unread,
Jan 18, 2012, 11:06:17 AM1/18/12
to nose-...@googlegroups.com
Simplifying the question a bit..
Given a plugin I think that the right thing to do to enable it would be
to use addplugins

ep = EclipseFriendlyPlugin()
# how do I make sure the plugin is actually loaded and doing
something?

plugins = [ep]
# and with this the verbosity should be set correctly
# should use addplugins instead if they are not "default" plugins
TestProgram(argv=argv[:1], config=conf, defaultTest=eggpath,

addplugins=plugins)


but it doesn't work, I get a :
File "/home/andrea/.local/bin/run_tests", line 9, in <module>
load_entry_point('psi.devsonly==0.1', 'console_scripts', 'run_tests')()
File
"/home/andrea/git_projs/Psi/psi.devsonly/psi/devsonly/bin/run_tests.py",
line 62, in main
modes[ns.mode]()
File
"/home/andrea/git_projs/Psi/psi.devsonly/psi/devsonly/bin/run_tests.py",
line 42, in simple
print(NoseTestRunner().egg_runner(ns.project_path))
File
"/home/andrea/git_projs/Psi/psi.devsonly/psi/devsonly/testwrapper.py",
line 60, in egg_runner
addplugins=plugins)
File "/usr/lib/python2.7/site-packages/nose/core.py", line 107, in
__init__
config.plugins.addPlugins(addplugins)
File "/usr/lib/python2.7/site-packages/nose/plugins/manager.py", line
208, in addPlugins
raise NotImplementedError()
NotImplementedError


I guess that with another PluginManager it might work, but I have no way
apparently to the way
the pluginmanager is actually chosen, am I wrong??

If instead I pass
"plugins=plugins", everything seems fine but the plugin seems to have no
effect whatsoever...

Any hint how to just make a plugin working by default and writing output
on the console??

jason pellerin

unread,
Jan 23, 2012, 3:22:15 PM1/23/12
to nose-...@googlegroups.com
addplugins is the right way to do this -- the error you're seeing
there is because somehow you've got the "NoPlugins" plugin manager
enabled. You should see good results from using the default plugin
manager and addplugins.

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 24, 2012, 5:51:00 AM1/24/12
to nose-...@googlegroups.com, jason pellerin
On 01/23/2012 08:22 PM, jason pellerin wrote:
> addplugins is the right way to do this -- the error you're seeing
> there is because somehow you've got the "NoPlugins" plugin manager
> enabled. You should see good results from using the default plugin
> manager and addplugins.
>
> JP

Good thanks I think I solved this by the way, I was passing
a configuration to increase the verbosity as
conf= Config()
conf.verbosity = 3

So the question is, how do I create a configuration which doesn't
interfere with the addplugins?

(because in Config actually plugins is set to NoPluginManager, which
explains everything).

Andrea Crotti

unread,
Jan 24, 2012, 8:02:53 AM1/24/12
to nose-...@googlegroups.com, jason pellerin
On 01/24/2012 10:51 AM, Andrea Crotti wrote:
>
> Good thanks I think I solved this by the way, I was passing
> a configuration to increase the verbosity as
> conf= Config()
> conf.verbosity = 3
>
> So the question is, how do I create a configuration which doesn't
> interfere with the addplugins?
>
> (because in Config actually plugins is set to NoPluginManager, which
> explains everything).
>


And another thing, which was the older way of doing the same?
Because actually addplugins is not present in the version I have on
windows (0.10)..

Reply all
Reply to author
Forward
0 new messages