Dependency Testing with Python

2019-06-19 01:16发布

问题:

I would like to write unit tests to test whether a dependency exists between two python packages. E.g.:

a/
    __init__.py
    models.py
    views.py
    ...
b/
    __init__.py
    models.py
    views.py
    ...

a unit test to check that modules in package b don't import anything from modules in package a. The only solution I have so far is to scan the files and check that there isn't a "from a" or "import a" in the source code. Are there other ways of doing this? One of the requirements is that a/ and b/ must be in the same directory level.

I would like to have this unit test because I want to be sure that I can use package b in other projects without package a, and also not have other developers write code that will make b dependent on a.

回答1:

Python is too dynamic to do this 100% correctly. Consider that you can import modules by calling __import__, which takes a string argument so the name of the module to import can be constructed at runtime. Also, __import__ is a function, so it could be bound to other names, so you can't even be sure of detecting all the cases when something is being imported.

And it's technically possible for a module to call a function from another module, which imports a module and returns it. So you definitely can't do this by analysing just package b.

And then there's exec to execute arbitrary python code constructed at runtime...

The closest you could get is probably to try and make your unit test exercise b when a is on the PYTHONPATH, and also when a isn't on the PYTHONPATH. Still not foolproof, as that only tells you that b completed all the tests without a on the PYTHONPATH, not that it doesn't ever need a for anything. And if you're really unlucky, b does something really stupid and fiddles with sys.path in flight and manages to import a anyway somehow.

If, however, this is all your your own code and you know you don't do this kind of wacky crap, then a simple script that scans the files for import statements is probably your best bet. It would probably work very very often on random other people's code too. It's just not possible to do the job perfectly with full generality.



回答2:

import sys
sys.modules['a'] = None

import b
# run unit tests for b to try and catch local import statements in b's functions