fir*_*ush 8 python unit-testing python-unittest
Python unittest模块似乎假设一个项目的目录结构,其中有一个项目根级目录,其中包含源代码和该目录下的测试.
但是,我想在我的~/bin目录中编写Python脚本并在另一个目录中测试它(比方说~/dev/tests).有没有办法让我使用命令行界面运行单元测试,而无需设置我的PYTHONPATH环境变量和创建__init__.py文件等等?
这是一个展示我想要的简单例子:
~/bin/candy:
#!/usr/bin/env python
def candy():
return "candy"
if __name__ == '__main__':
print candy()
Run Code Online (Sandbox Code Playgroud)
~/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"
Run Code Online (Sandbox Code Playgroud)
我注意到如果出现以下情况,可以很方便
candy.py和test_candy.py)我可以使用unittest模块运行python 来执行以下操作,而无需在我的环境中明确设置任何内容:
~/candy).test_candy有py作为扩展名.candy和test_candy.py不共享一个共同的根(我的主目录除外).如果通过简单的调用python -m unittest无法做到这一点,那么实现这一目标的最简单方法是什么?
这是candy可执行文件(不变):
? cat ~/bin/candy
#!/usr/bin/env python
def candy():
return "candy"
if __name__ == '__main__':
print candy()
Run Code Online (Sandbox Code Playgroud)
这是~/dev/tests/test_candy.py(已更改):
? 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"
Run Code Online (Sandbox Code Playgroud)
发生了什么变化?
我们添加imp.load_source了导入~/bin/candy(没有*.py扩展名的模块)
我们增加了查找主目录提及的规定,即~使用expanduser
我们正在使用os.path.join加入的路径~/bin/candy
现在,您可以使用模块discover选项运行测试unittest。
检查python -m unittest --help更多细节。
摘录如下
-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
Run Code Online (Sandbox Code Playgroud)
自 Python 3.3 起,该imp包已被弃用,并由该importlib包取代。该答案提供了如何导入单个文件的详细信息。
对于您的单元测试,这将是:
from importlib.machinery import ModuleSpec, SourceFileLoader
from importlib.util import spec_from_loader, module_from_spec
import os.path
import types
import unittest
def import_from_source( name : str, file_path : str ) -> types.ModuleType:
loader : SourceFileLoader = SourceFileLoader(name, file_path)
spec : ModuleSpec = spec_from_loader(loader.name, loader)
module : types.ModuleType = module_from_spec(spec)
loader.exec_module(module)
return module
script_path : str = os.path.abspath(
os.path.join(
os.path.dirname(os.path.abspath(__file__)), "..", "..", "bin", "candy",
)
)
candy : types.ModuleType = import_from_source("candy", script_path)
class CandyTestCase(unittest.TestCase):
def testCandy(self : "CandyTestCase" ) -> None:
self.assertEqual( candy.candy(), "candy" )
if __name__ == '__main__':
unittest.main()
Run Code Online (Sandbox Code Playgroud)
假设文件结构为:
base_directory/bin/candy
base_directory/dev/tests/test_candy.py
Run Code Online (Sandbox Code Playgroud)
(注意:此单元测试假定测试的固定相对路径而不是固定的绝对路径,以便您可以将包移动到另一个目录,并且只要包内的文件不更改相对位置,测试就不会中断。 )
我还没有尝试过使用unittest,但是我对此类问题的快速解决方法是使用os模块更改脚本内的工作目录。但这应该对你有用。
#!/usr/bin/env python
import unittest
import os
os.chdir("/usr/bin/candy")
import candy
class CandyTestCase(unittest.TestCase):
def testCandy(self):
candyOutput = candy.candy()
assert candyOutput == "candy"
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1767 次 |
| 最近记录: |