The Python unittest
module seems to assume a directory structure for a project in which there's a project root level directory with the source code and tests under that directory.
I would like, however, to write Python scripts in my ~/bin
directory and tests for it in another directory (say, ~/dev/tests
). Is there a way for me to run the unit tests using the command line interface without setting my PYTHONPATH
environment variable and creating __init__.py
files and whatnot?
Here's a simple example demonstrating what I want:
~/bin/candy
:
#!/usr/bin/env python
def candy():
return "candy"
if __name__ == '__main__':
print candy()
~/dev/tests/test_candy.py
:
#!/usr/bin/env python
import unittest
import candy
class CandyTestCase(unittest.TestCase):
def testCandy(self):
candyOutput = candy.candy()
assert candyOutput == "candy"
I notice that everything can be done conveniently if:
candy.py
and test_candy.py
)Can I run python with the unittest
module to do the following without setting anything in my environment explicitly:
~/candy
).test_candy
has py as an extension or not.candy
and test_candy.py
to not share a common root (other than my home directory).If that's not possible with a simple invocation of python -m unittest
, what is the most simple way to accomplish this?
Tests are put in files of the form test_*. py or *_test.py , and are usually placed in a directory called tests/ in a package's root.
You can invoke testing through the Python interpreter from the command line: python -m pytest [...] This is almost equivalent to invoking the command line script pytest [...] directly, except that calling via python will also add the current directory to sys.
This is candy executable (no change):
➜ cat ~/bin/candy
#!/usr/bin/env python
def candy():
return "candy"
if __name__ == '__main__':
print candy()
and this is ~/dev/tests/test_candy.py
(changed):
➜ cat ~/dev/tests/test_candy.py
#!/usr/bin/env python
import imp
import unittest
from os.path import expanduser, join
# use expanduser to locate its home dir and join bin and candy module paths
candy_module_path = join(expanduser("~"), "bin", "candy")
# load the module without .py extension
candy = imp.load_source("candy", candy_module_path)
class CandyTestCase(unittest.TestCase):
def testCandy(self):
candyOutput = candy.candy()
assert candyOutput == "candy"
What changed?
We added imp.load_source
to import ~/bin/candy
(a module without *.py
extension)
We added provision to locate home directory mention i.e. ~
using expanduser
We are using os.path.join
to join the paths for ~/bin/candy
Now you can run the tests with discover
option of unittest
module.
Check python -m unittest --help
for more details.
Excerpts below
-s directory Directory to start discovery ('.' default)
-p pattern Pattern to match test files ('test*.py' default)
➜ python -m unittest discover -s ~/bin/ -p 'test*' -v ~/dev/tests
testCandy (test_candy.CandyTestCase) ... ok
----------------------------------------------------------------------
Ran 1 test in 0.000s
OK
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With