my_project ./foo ./__init__.py ./bar.py ./tests ./test_foo.py ./test_bar.py
but i used to get confused on how to organize the import(s) and when to use PYTHONPATH for my tests.
my requirements are:
- i want to be able to run my tests both from my_project folder and from the tests folder
- i don’t want to set the PYTHONPATH manually (and i don’t want to add my development path to PYTHONPATH.
- i want to import the lib modules on the test on the same way i would import after the lib is deployed.
(yes i am lazy)
bar.py:
def dumb_true(): return True
1st try
the code for test_bar.py should like something like this:
import unittest from foo import bar class TestBar(unittest.TestCase): def test_bar_true(self): self.assertTrue(bar.dumb_true()) if __name__ == '__main__': unittest.main()
the problem here is that you need to set the PYTHONPATH manually.
2nd try
the first thing that comes in my mind is to add ‘foo’ folder to PYTHONPATH on the test module
... import sys,os sys.path.insert(0,os.path.abspath(__file__+"/../..")) from foo import bar ...
not bad. but you need to add this to every single test module. and hope that your folder structure wont change.
3rd try
i guess we need a smarter test runner (like nose).
get your code back to just:
... from foo import bar ...
you can just run “nosetests” from the project folder (‘my_project’ in the example above) and it will just work.
the same doesn’t happen if run “nosetests” from the tests folder.
- from nose homepage:
- When nose imports a module, it adds that module’s directory to sys.path; when the module is inside of a package, like package.module, it will be loaded as package.module and the directory of package will be added to sys.path.
so the trick here is to make the tests folder a package (adding __init__.py to it). so in the tests folder you will find:
./tests ./__init__.py ./test_foo.py ./test_bar.py
now from the tests folder you can:
- execute all tests doing “nosetests”
- execute just one file “nosetests test_bar.py”
- check nose docs for more options
and you don’t have to worry about PYTHONPATH at all :)
Great post! Just what I’m looking for.
Great post, man! I was tired of finding crappy responses on StackOverflow!
Holy smokes I’ve been trying to understand imports for days, if not weeks/months now… I finally understand it with your demonstration of how you solved your problem! thank you so much!
[…] get the same error when I run from inside the tests/ directory. According to the documentation and an example I found, nose is supposed to add all parent packages to the path as well as the directory from […]
[…] get the same error when I run from inside the tests/ directory. According to the documentation and an example I found, nose is supposed to add all parent packages to the path as well as the directory from […]
[…] get the same error when I run from inside the tests/ directory. According to the documentation and an example I found, nose is supposed to add all parent packages to the path as well as the directory from […]
[…] new python testing , want set construction similar 1 can have when testing ruby rspec. followed this blog, it’s not working me. current construction […]
[…] 当我从tests /目录里面运行时,我得到相同的错误。根据文档和an example,我发现,鼻子应该将所有父包添加到路径以及调用它的目录,但是在我的情况下似乎不会发生。 我使用Python 2.6.2运行Ubuntu 8.04。我已经手动构建并安装了鼻子(而不是setup_tools)。 […]
[…] документации и пример, который я нашел, […]
[…] /目录中运行时,我得到了同样的错误。 根据我发现的文档和示例 […]
[…] 当我从tests /目录中运行时,出现相同的错误。根据文档和我发现的示例,nose应该将所有父包都添加到路径以及调用它的目录中,但是在我看来,这似乎没有发生。 […]
[…] 내부에서 실행할 때 동일한 오류가 발생합니다. 내가 찾은 문서와 예제 에 따르면 nose는 모든 부모 패키지를 경로와 호출되는 디렉토리에 […]
[…] get the same error when I run from inside the tests/ directory. According to the documentation and an example I found, nose is supposed to add all parent packages to the path as well as the directory from […]
[…] get the same error when I run from inside the tests/ directory. According to the documentation and an example I found, nose is supposed to add all parent packages to the path as well as the directory from […]
[…] get the same error when I run from inside the tests/ directory. According to the documentation and an example I found, nose is supposed to add all parent packages to the path as well as the directory from […]