Search code examples
pythonpython-sphinxnosedoctest

Disable nose running setup()


The nose package is often used to run doctests as well as tests in dedicated test files. It appears that even in doctest files, it attempts to run the setup and teardown fixtures.

When the module for doctesting happens to require a function named setup for some other purpose -- it may be a Sphinx extension, for example -- nosetests will call setup and fail.

To be clear, here is an example:

def my_tricky_function(arg):
    """Do something testable

    >>> my_tricky_function(1)
    2
    """
    return arg + arg


def my_extension(app):
    ...


def setup(app):
    """Establish sphinx hooks"""
    app.connect('build-finished', my_extension)

Running nosestests results in:

File ".../site-packages/nose/suite.py", line 291, in setUp
    self.setupContext(ancestor)
  File ".../site-packages/nose/suite.py", line 314, in setupContext
    try_run(context, names)
  File ".../site-packages/nose/util.py", line 468, in try_run
    return func(obj)
  File "sphinx_ext.py", line 14, in setup
    app.connect('build-finished', my_extension)
AttributeError: 'module' object has no attribute 'connect'

(Note: when setup accepts an argument, nosetest passes the scope in which setup is a name, in this case the module.)

Note that the following do not (seem to) apply:

  • adding an attribute __test__ = False (or using this decorator) to setup doesn't stop it being called.
  • there is no command-line option equivalent to --ignore-files
  • setting my_tricky_function.setup = None does not stop the module-level setup (h/t @alecxe)

Solution

  • I have found the following somewhat hacky solution: add another function setup_module which will hide setup from nose.

    ...
    
    def setup(app):
        """Establish sphinx hooks"""
        app.connect('build-finished', my_extension)
    
    def setup_module():
        pass