Knitting in extra package directories

Python packages have __path__ variables that can be manipulated to add extra directories cntaining software used in the packages. The testrunner needs to be given extra information about this sort of situation.

Let’s look at an example. The testrunner-ex-knit-lib directory is a directory that we want to add to the Python path, but that we don’t want to search for tests. It has a sample4 package and a products subpackage. The products subpackage adds the testrunner-ex-knit-products to it’s __path__. We want to run tests from the testrunner-ex-knit-products directory. When we import these tests, we need to import them from the sample4.products package. We can’t use the –path option to name testrunner-ex-knit-products. It isn’t enough to add the containing directory to the test path because then we wouldn’t be able to determine the package name properly. We might be able to use the –package option to run the tests from the sample4/products package, but we want to run tests in testrunner-ex that aren’t in this package.

We can use the –package-path option in this case. The –package-path option is like the –test-path option in that it defines a path to be searched for tests without affecting the python path. It differs in that it supplied a package name that is added a profex when importing any modules found. The –package-path option takes two arguments, a package name and file path.

>>> import os.path, sys
>>> directory_with_tests = os.path.join(this_directory, 'testrunner-ex')
>>> sys.path.append(os.path.join(this_directory, 'testrunner-ex-pp-lib'))
>>> defaults = [
...     '--path', directory_with_tests,
...     '--tests-pattern', '^sampletestsf?$',
...     '--package-path',
...     os.path.join(this_directory, 'testrunner-ex-pp-products'),
...     'sample4.products',
...     ]
>>> from zope import testrunner
>>> old_argv = sys.argv
>>> sys.argv = 'test --layer Layer111 -vv'.split()
>>> _ = testrunner.run_internal(defaults)
Running tests at level 1
Running samplelayers.Layer111 tests:
  Set up samplelayers.Layerx in 0.000 seconds.
  Set up samplelayers.Layer1 in 0.000 seconds.
  Set up samplelayers.Layer11 in 0.000 seconds.
  Set up samplelayers.Layer111 in 0.000 seconds.
  Running:
    test_x1 (sample1.sampletests.test111.TestA)
    test_y0 (sample1.sampletests.test111.TestA)
    ...
    test_y0 (sampletests.test111)
    test_z1 (sampletests.test111)
    testrunner-ex/sampletests/../sampletestsl.rst
    test_extra_test_in_products (sample4.products.sampletests.Test)
    test_another_test_in_products (sample4.products.more.sampletests.Test)
  Ran 28 tests with 0 failures, 0 errors and 0 skipped in 0.008 seconds.
Tearing down left over layers:
  Tear down samplelayers.Layer111 in 0.000 seconds.
  Tear down samplelayers.Layerx in 0.000 seconds.
  Tear down samplelayers.Layer11 in 0.000 seconds.
  Tear down samplelayers.Layer1 in 0.000 seconds.

In the example, the last test, test_extra_test_in_products, came from the products directory. As usual, we can select the knit-in packages or individual packages within knit-in packages:

>>> sys.argv = 'test --package sample4.products -vv'.split()
>>> _ = testrunner.run_internal(defaults)
Running tests at level 1
Running samplelayers.Layer111 tests:
  Set up samplelayers.Layerx in 0.000 seconds.
  Set up samplelayers.Layer1 in 0.000 seconds.
  Set up samplelayers.Layer11 in 0.000 seconds.
  Set up samplelayers.Layer111 in 0.000 seconds.
  Running:
    test_extra_test_in_products (sample4.products.sampletests.Test)
    test_another_test_in_products (sample4.products.more.sampletests.Test)
  Ran 2 tests with 0 failures, 0 errors and 0 skipped in 0.000 seconds.
Tearing down left over layers:
  Tear down samplelayers.Layer111 in 0.000 seconds.
  Tear down samplelayers.Layerx in 0.000 seconds.
  Tear down samplelayers.Layer11 in 0.000 seconds.
  Tear down samplelayers.Layer1 in 0.000 seconds.
>>> sys.argv = 'test --package sample4.products.more -vv'.split()
>>> _ = testrunner.run_internal(defaults)
Running tests at level 1
Running samplelayers.Layer111 tests:
  Set up samplelayers.Layerx in 0.000 seconds.
  Set up samplelayers.Layer1 in 0.000 seconds.
  Set up samplelayers.Layer11 in 0.000 seconds.
  Set up samplelayers.Layer111 in 0.000 seconds.
  Running:
    test_another_test_in_products (sample4.products.more.sampletests.Test)
  Ran 1 tests with 0 failures, 0 errors and 0 skipped in 0.000 seconds.
Tearing down left over layers:
  Tear down samplelayers.Layer111 in 0.000 seconds.
  Tear down samplelayers.Layerx in 0.000 seconds.
  Tear down samplelayers.Layer11 in 0.000 seconds.
  Tear down samplelayers.Layer1 in 0.000 seconds.

Restore the arguments:

>>> sys.argv = old_argv