====================
 Setuptools Support
====================


The ``ftest`` Setup Command
===========================

The `.ftest` class is a proper `distutils` command and
`zope.testrunner` exposes it as such via an entry point.

  >>> import pkg_resources
  >>> ws = pkg_resources.WorkingSet()
  >>> eps = dict([(ep.name, ep)
  ...             for ep in ws.iter_entry_points('distutils.commands')])
  >>> 'ftest' in eps
  True
  >>> eps['ftest']
  EntryPoint.parse('ftest = zope.testrunner.eggsupport:ftest')

Let's now run this command:

  >>> import zope.testrunner
  >>> org_run = zope.testrunner.run

  >>> def run(args):
  ...     print(' '.join(args))
  >>> zope.testrunner.run = run

  >>> import os, tempfile, shutil
  >>> tmpdir = tempfile.mkdtemp()
  >>> srcdir = os.path.join(tmpdir, 'src')
  >>> os.mkdir(srcdir)

  >>> import setuptools.dist
  >>> dist = setuptools.dist.Distribution(
  ...     {'package_dir': {'': srcdir},
  ...      'script_name': __file__})

  >>> from zope.testrunner.eggsupport import ftest
  >>> ftest(dist).run()
  IGNORE_ME --test-path .../src

Cleanup:

  >>> zope.testrunner.run = org_run
  >>> shutil.rmtree(tmpdir)


Skipping Tests with Layers
==========================

The `.SkipLayers` scanning test loader can replace the standard test loader,
so that any tests that require layers are skipped. This is necessary, since
the standard setuptools testing facility does not handle layers. It can be
used as follows::

      setup(
          ...
          setup_requires=[
              'eggtestinfo' # captures testing metadata in EGG-INFO
          ],
          tests_require=[
              'zope.testrunner',
          ],
          ...
          test_loader='zope.testrunner.eggsupport:SkipLayers',
          ...
      )

Let's now create some test suites to make sure that all tests with layers are
properly skipped.

  >>> import doctest
  >>> import unittest

  >>> all = unittest.TestSuite()
  >>> class T1(unittest.TestCase):
  ...     def test_t1(self):
  ...         pass
  >>> class T2(unittest.TestCase):
  ...     layer = 'layer'
  ...     def test_t2(self):
  ...         pass
  >>> T3 = doctest.DocTestSuite('zope.testrunner.find')
  >>> T4 = doctest.DocTestSuite('zope.testrunner.options')
  >>> T4.layer = 'layer'
  >>> T5 = doctest.DocFileSuite('testrunner.rst', package='zope.testrunner.tests')
  >>> T6 = doctest.DocFileSuite('testrunner-gc.rst', package='zope.testrunner.tests')
  >>> T6.layer = 'layer'

  >>> all = unittest.TestSuite((
  ...     unittest.defaultTestLoader.loadTestsFromTestCase(T1),
  ...     unittest.defaultTestLoader.loadTestsFromTestCase(T2),
  ...     T3, T4, T5, T6,
  ...     ))

Let's return those tests from the scan:

  >>> from setuptools.command.test import ScanningLoader
  >>> orig_loadTestsFromModule = ScanningLoader.loadTestsFromModule
  >>> ScanningLoader.loadTestsFromModule = lambda *args: all

Now we can retrieve the modules from the layer skipping loader:

  >>> from zope.testrunner.eggsupport import SkipLayers
  >>> filtered = SkipLayers().loadTestsFromModule('zope.testrunner')

  >>> len(filtered._tests)
  3
  >>> from pprint import pprint
  >>> pprint(filtered._tests)
  [<...T1 testMethod=test_t1>,
   StartUpFailure (zope.testrunner.find),
   .../zope/testrunner/tests/testrunner.rst]

Cleanup:

  >>> ScanningLoader.loadTestsFromModule = orig_loadTestsFromModule

When the distribution specified a ``test_suite``, another method is used to
load the tests.

  >>> orig_loadTestsFromNames = ScanningLoader.loadTestsFromNames
  >>> ScanningLoader.loadTestsFromNames = lambda *args: all

Now we can retrieve the modules from the layer skipping loader:

  >>> from zope.testrunner.eggsupport import SkipLayers
  >>> filtered = SkipLayers().loadTestsFromNames(
  ...     'zope.testrunner.tests.test_suite', 'zope.testrunner')

  >>> len(filtered._tests)
  3
  >>> from pprint import pprint
  >>> pprint(filtered._tests)
  [<...T1 testMethod=test_t1>,
   StartUpFailure (zope.testrunner.find),
   .../zope/testrunner/tests/testrunner.rst]

Cleanup:

  >>> ScanningLoader.loadTestsFromNames = orig_loadTestsFromNames
