8

Nose has a bug - test names created by generators are not cached, so the error looks like it happened in the last test, not the actual test where it failed. I got around it following the solution in the bug report discussion, but it only works for names shown on stdout, not in the XML report (--with-xunit)

from functools import partial, update_wrapper
def testGenerator():
    for i in range(10):
        func = partial(test)
        # make decorator with_setup() work again
        update_wrapper(func, test)
        func.description = "nice test name %s" % i
        yield func

def test():
    pass

The output of nose is as expected, something like

nice test name 0 ... ok
nice test name 1 ... ok
nice test name 2 ... ok
...

But the test names in XML are just 'testGenerator'.

...<testcase classname="example" name="testGenerator" time="0.000" />...

How can I change this so that the personalized test names are shown on both stdout and XML output?

I'm using nosetests version 1.1.2 and Python 2.6.6

M.K.
  • 346
  • 3
  • 14
  • Changing 'func.__name__' or 'func.__doc__' doesn't work either. – M.K. Jun 25 '12 at 16:59
  • How about creating a test suite instead? – Apalala Jun 26 '12 at 08:44
  • 1
    @Apalala thanks, that seems like it could solve it. Though I can't find any information about how to use this in nose and how does it mix with with noses' test discovery. Could you give an example please? – M.K. Jun 26 '12 at 13:00
  • Last time I tried, nose would not discover tests created at runtime. – Apalala Nov 12 '12 at 04:11

4 Answers4

5

You can change the way that Nose names tests by adding a plugin that implements describeTest

from nose.plugins import Plugin
class CustomName(Plugin):
    "Change the printed description/name of the test."
    def describeTest(self, test):
         return "%s:%s" % (test.test.__module__, test.test.description)

You will then have to install this plugin, and enable it in the Nose invocation.

dbn
  • 13,144
  • 3
  • 60
  • 86
2

You can add the following line.

testGenerator.__name__ = "nice test name %s" % i

Example:

from functools import partial, update_wrapper
def testGenerator():
    for i in range(10):
        func = partial(test)
        # make decorator with_setup() work again
        update_wrapper(func, test)
        func.description = "nice test name %s" % i
        testGenerator.__name__ = "nice test name %s" % i
        yield func

def test():
    pass

This will result in the names you want.

<testsuite name="nosetests" tests="11" errors="0" failures="0" skip="0"><testcase classname="sample" name="nice test name 0" time="0.000" />
ford
  • 10,687
  • 3
  • 47
  • 54
  • This nearly works except all tests get the same name for me (nose 1.2.1, python 2.7.3) – Rog May 17 '13 at 07:05
1

As Ananth mentions, you can use this.

testGenerator.__name__

You can also use this instead

testGenerator.compat_func_name

If your test class has arguments, I'd recommend currying them, as well as currying with_setup. Using lambda saves on the import, and I think it's a little cleaner. For example,

from nose.tools import with_setup

def testGenerator():
    for i in range(10):
        func = with_setup(set_up, tear_down)(lambda: test(i))

        func.description = "nice test name %s" % i
        testGenerator.compat_func_name = func.description

        yield func

def test(i):
    pass

def set_up():
    pass

def tear_down():
    pass
Dane White
  • 3,443
  • 18
  • 16
0

If using nose and Eclipe's PyUnit:

import nose

class Test(object):
    CURRENT_TEST_NAME = None

    def test_generator(self):
        def the_test(*args,**kwargs):
            pass

        for i in range(10):
            # Set test name
            Test.CURRENT_TEST_NAME = "TestGenerated_%i"%i
            the_test.description = Test.CURRENT_TEST_NAME

            # Yield generated test
            yield the_test,i

    # Set the name of each test generated
    test_generator.address = lambda arg=None:(__file__, Test, Test.CURRENT_TEST_NAME)

which will cause the name to show up nicely in PyUnit as well.

Generated test names

frmdstryr
  • 20,142
  • 3
  • 38
  • 32