10

I want to be able to get the result of a particular test method and output it inside the teardown method, while using the nose test runner. There is a very good example here.

But unfortunately, running nosetests example.py does not work, since nose doesn't seem to like the fact that the run method in the superclass is being overridden:

AttributeError: 'ResultProxy' object has no attribute 'wasSuccessful'
Community
  • 1
  • 1
Rafael
  • 186
  • 1
  • 6

2 Answers2

5

Caveat: the following doesn't actually access the test during the tearDown, but it does access each result.

You might want to write a nose plugin (see the API documentation here). The method that you are probably interested in is afterTest(), which is run... after the test. :) Though, depending on your exact application, handleError()/handleFailure() or finalize() might actually be more useful.

Here is an example plugin that accesses the result of a test immediately after it is executed.

from nose.plugins import Plugin
import logging
log = logging.getLogger('nose.plugins.testnamer')

class ReportResults(Plugin):
    def __init__(self, *args, **kwargs):
        super(ReportResults, self).__init__(*args, **kwargs)
        self.passes = 0
        self.failures = 0
    def afterTest(self, test):
        if test.passed:
            self.passes += 1
        else:
            self.failures += 1
    def finalize(self, result):
        print "%d successes, %d failures" % (self.passes, self.failures)

This trivial example merely reports the number of passes and failures (like the link you included, but I'm sure you can extend it to do something more interesting (here's another fun idea). To use this, make sure that it is installed in Nose (or load it into a custom runner), and then activate it with --with-reportresults.

Community
  • 1
  • 1
dbn
  • 13,144
  • 3
  • 60
  • 86
-1

If you are OK with adding some boilerplate code to the tests, something like the following might work.

In MyTest1, tearDown is called at the end of each test, and the value of self.result has been set to a tuple containing the method name and a dictionary (but you could set that to whatever you like). The inspect module is used to get the method name, so tearDown knows which test just ran.

In MyTest2, all the results are saved in a dictionary (results), which you can do with what you like in the tearDownClass method.

import inspect
import unittest


class MyTest1(unittest.TestCase):

    result = None

    def tearDown(self):
        print "tearDown:", self.result

    def test_aaa(self):
        frame = inspect.currentframe()
        name = inspect.getframeinfo(frame).function
        del frame
        self.result = (name, None)

        x = 1 + 1
        self.assertEqual(x, 2)

        self.result = (name, dict(x=x))

    def test_bbb(self):
        frame = inspect.currentframe()
        name = inspect.getframeinfo(frame).function
        del frame
        self.result = (name, None)

        # Intentional fail.
        x = -1
        self.assertEqual(x, 0)

        self.result = (name, dict(x=x))


class MyTest2(unittest.TestCase):

    results = {}

    @classmethod
    def tearDownClass(cls):
        print "tearDownClass:", cls.results

    def test_aaa(self):
        frame = inspect.currentframe()
        name = inspect.getframeinfo(frame).function
        del frame
        self.results[name] = None

        x = 1 + 1
        self.assertEqual(x, 2)

        self.results[name] = dict(x=x)

    def test_bbb(self):
        frame = inspect.currentframe()
        name = inspect.getframeinfo(frame).function
        del frame
        self.results[name] = None

        x = -1
        self.assertEqual(x, 0)

        self.results[name] = dict(x=x)


if __name__ == '__main__':
    unittest.main()
Warren Weckesser
  • 110,654
  • 19
  • 194
  • 214
  • 1
    As this is a bit hackish and possibly brittle (e.g. not tested in python 3), the downvote is probably deserved. I wouldn't use it in my own production code. On the other hand, it seems to work; practicality beats purity and all that. – Warren Weckesser Mar 27 '14 at 19:02