[TIP] getting the result of a test in teardown_method?

holger krekel holger at merlinux.eu
Tue May 11 10:20:56 PDT 2010


Hi Mark, Hans, 

On Tue, May 11, 2010 at 11:33 -0400, Mark Roddy wrote:
> On Tue, May 11, 2010 at 10:44 AM, C. Titus Brown <ctb at msu.edu> wrote:
> > On Tue, May 11, 2010 at 11:30:10AM +0200, holger krekel wrote:
> >> > I hope this is where people do Q&A on py.test. Otherwise please direct me to
> >> > the right place.
> >>
> >> Yes, I think so.  Both nose and py.test (not sure about unittest2)
> >> also have their own mailing lists but policies are somewhat unclear.
> >> Often questions touch general testing issues and I find it interesting
> >> to see how a specific tools/other people see it.
> 
> It's hacky, but you could accomplish this w/unittest by sub-classing
> TestResult (or more likely _TextTestResult), overriding the
> startTest(test) method and setting an attribute on the test instance
> passed to the test result instance.  Then in your tearDown() you can
> grab the test result object and find the result of the test run
> (though this will take some mucking w/the internal structures of
> TestResult which are not geared for accessing results for a specific
> test.  Due to this you should probably add some convenience methods to
> the TestResult class to make it easier).
> 
> You'll also need to inject your new subclass to make sure your
> TestResult gets used instead of the underlying one.  Look at
> TestCase.defaultTestResult() and TextTestRunner._makeResult(),
> 
> I'm not advocating this approach, but it will get the job done.

However, this approach is not applicable to py.test (was the context of Hans'
question).  There you could put this in a conftest.py file: 

    def pytest_runtest_makereport(item, call):
        if call.when == "call":
            item.excinfo = call.excinfo # memorize outcome info 

    def pytest_runtest_teardown(item):
        if item.excinfo: 
            ### do something if an exception was raised during a test call
        else:
            ### do something else if no exception was raised during a test call

These hooks would be called for each test function execution in the directory 
of the conftest.py.  If the idea is to have a post-check function that gets run after each "successful" test function the above hook could be refined like this:

    def pytest_runtest_teardown(item):
        if not item.excinfo:
            instance = item.getparent(py.test.collect.Instance)
            meth = getattr(instance.obj, 'check_post', None)
            if meth:
                meth()

This would allow to write test files like this: 

    class TestPost:
        def setup_method(self):
            self.STATE = ... 
        def test_method1(self):
            ...
        def check_post(self):
            assert self.STATE .... 

where check_post() gets run for each non-exception throwing test method.

HTH,
holger



More information about the testing-in-python mailing list