Search code examples
pythontestingnose

Nose: test all modules in a given package


I have a package with several sub-packages, one of them for tests (named tests). Since the sub-package name makes it clear that contained modules are test modules, I prefer not to pollute module names with the test-name pattern nose expects to include them for testing. That's the setup I'm thinking of:

- foo
  - __init__.py
  ...
  - bar
    - __init__.py
    ...
  - baz
    - __init__.py
    ...
  - tests
    - __init__.py
    - something.py

Now, by default nose does not run tests found in foo.tests.something. I know nose accepts the -i option to define regular expressions for additional stuff to search tests in. So nose -i something does the job here. However, I have a bunch of modules in the tests package and do not want to name them explicitely. nose -i tests\..* does not work, it looks like nose only matches against module base-names. As a last resort I could run nose --all-modules, but this also inspects foo.bar and foo.baz -- I'd like to avoid this.

So, how could I instruct nose to look for tests in all modules within a given package (tests in my case)? I could write a nose plugin for this task, but I'm looking for a standard solution.


Solution

  • You should be able to import the files into your __init__.py and have them picked up. I had this setup:

    - app:
      - __init__.py
      - models.py
      - views.py
      - tests:
        - __init__.py
        - models.py # contain tests
        - views.py # contain tests
    

    In the tests/__init__.py file I had the following:

    from app.tests.models import *
    from app.tests.views import *
    

    Which defeats one of the benefits of using a regex to find tests (a goal of nose) but worked.

    You can also use the decorator @istest to flag an individual def as a test if you want to avoid the naming of methods to match the regex. I've not tried to do this for modules (py files) that don't also match the regex but I doubt it would work without the above import.

    Note, I've moved away from the import in __init__.py and just prefix my test methods and filenames with test_ and postfix my classes with Test. I find this makes the code more self-describing as even in a Test class there may be setup methods and helper methods (e.g. generators).