I found it surprisingly hard to determine in tearDown() whether or not the test that currently ran succeeded or not. I am writing some tests for gnome-settings-daemon and want to show the log output of the daemon if a test failed.
I now cobbled together the following hack, but I wonder if there’s a more elegant way? The interwebs don’t seem to have a good solution for this either.
def tearDown(self):
[...]
# collect log, run() shows it on failures
with open(self.daemon_log.name) as f:
self.log_output = f.read()
def run(self, result=None):
'''Show log output on failed tests'''
if result:
orig_err_fail = result.errors + result.failures
super().run(result)
if result and result.errors + result.failures > orig_err_fail:
print('\n----- daemon log -----\n%s\n------\n' % self.log_output)
#1 by Jonathan Lange on 2012/10/11 - 12:19
Zitieren
Oh man, we’ve got this _so_ covered, but you need to use some other dependencies.
testtools has an API called addDetails, which lets you attach arbitrary content to a test’s result. These results are then shown in the output.
http://testtools.readthedocs.org/en/latest/for-test-authors.html#details
That solves the core problem.
However, if you want to get even fancier, you can use fixtures: . They also support the same “details” API. What you’d do is make a Fixture subclass for your daemon and have that class add the log. Then, in your test::
self.useFixture(GnomeSettingsDaemon())
And it will take care of showing the log and shutting down the daemon.
This has the added advantage of making the daemon set up and tear down re-usable without subclassing.
#2 by Marcel Stimberg on 2012/10/12 - 01:14
Zitieren
If you’d be using the nose testing framework (and why would you use anything else
?), you’d have this behaviour by default:
https://nose.readthedocs.org/en/latest/plugins/logcapture.htm
#3 by Marcel Stimberg on 2012/10/12 - 01:16
Zitieren
Ups, that link was missing an l in the end…:
https://nose.readthedocs.org/en/latest/plugins/logcapture.html
#4 by pitti on 2012/10/12 - 06:12
Zitieren
Marcel,
indeed I do use nose for some of my Python projects; these are tests for gnome-settings-daemon which uses autotools (and is otherwise a C project). But doesn’t this only capture things you already print to stdout/err? What I want is to only show the daemon log for a test that fails.
#5 by Ulrich Eckhardt on 2012/10/15 - 07:04
Zitieren
You can print() things unconditionally and tell unittest.runt() to buffer that output. In case of success, the output is discarded, otherwise it is displayed along with the fault.
Uli
#6 by pitti on 2012/10/15 - 07:08
Zitieren
Ah, do you have an example how to do that?
#7 by Ulrich Eckhardt on 2012/10/16 - 21:47
Zitieren
Sorry, should have been main(), not runt(), which was a typo anyway.
From http://docs.python.org/library/unittest.html, it’s just “unittest.main(buffer=True)” and you won’t see any of the output of setUp, test and tearDown unless the thing fails. Alternatively, you can pass -b or –buffer on the commandline.
Should be enabled by default, if you ask me.
Uli
#8 by pitti on 2012/10/17 - 08:38
Zitieren
Ah, thanks Ulrich!
#9 by Marcel on 2012/10/17 - 23:28
Zitieren
Sorry for not following up on my comment. The logcapture extension does capture log messages emitted using Python’s logging system. I assumed that was how you generated the log file but I only now realized that it is about a different log file. You could still always “log the log” (i.e. do something like logger.debug(log_output) but then Ulrich’s solution is probably easier.
#10 by edin on 2013/04/11 - 15:36
Zitieren
Hi,
Do yuo know how to repeat only failed tests? Some call in tearDown…
#11 by pitti on 2013/04/12 - 04:19
Zitieren
You can run the test suite with explicit test names (tests/run MyClass.test_foo) if you want to debug a particular test and only run that one.