如何让导入与 python 包和测试包一起使用
How to get imports to work with python package and testing package
我正在努力让导入为我的 python 项目工作。我创建了一个测试项目来说明我的问题。这是 Python 3.
我的目录结构如下:
project/
test.sh
packageA/
__init__.py
moduleA.py
test/
__init__.py
test_moduleA.py
test.sh的内容是python3 packageA/test/test_moduleA.py
两个__init__py
都是空的。
这是moduleA.py
:
class A:
def doSomething(self):
print("Did something")
这是“test_moduleA.py”:
import unittest
from packageA.moduleA import A
class TestModuleA(unittest.TestCase):
def testSomething(self):
a = A()
self.assertTrue(a.doSomething() == "Did Something")
if __name__ == '__main__':
unittest.main()
当我 运行 test.sh
这是我得到的错误:
[project] $ ./test.sh
Traceback (most recent call last):
File "packageA/test/test_moduleA.py", line 2, in <module>
from packageA.moduleA import A
ModuleNotFoundError: No module named 'packageA'
[project] $
我试过在“test_moduleA.py”中使用相对导入,如下所示:
from ..moduleA import A
在这种情况下,我得到的错误如下所示:
[project] $ ./test.sh
Traceback (most recent call last):
File "packageA/test/test_moduleA.py", line 2, in <module>
from ..moduleA import A
ValueError: attempted relative import beyond top-level package
[project] $
如何让它正常工作? Pythonic 方法是什么?
将 shell 脚本用于 test/deploy python 并不是一个好主意,因此我建议您将 test.sh 替换为 test.py
,其内容为:
import unittest
testmodules = [
'packageA.test.test_moduleA',
]
suite = unittest.TestSuite()
for t in testmodules:
try:
mod = __import__(t, globals(), locals(), ['suite'])
suitefn = getattr(mod, 'suite')
suite.addTest(suitefn())
except (ImportError, AttributeError):
suite.addTest(unittest.defaultTestLoader.loadTestsFromName(t))
unittest.TextTestRunner().run(suite)
向其中添加新测试非常容易,您只需要修改测试模块列表即可。
这是我基于 this answer (see also here) and this article 建议的解决方案。
首先,将测试目录移动到项目的根目录中:
project/
test.sh
packageA/
__init__.py
moduleA.py
test/
__init__.py
test_moduleA.py
然后,将 test_moduleA.py
更改如下(注意导入):
import unittest
from packageA.moduleA import A
class TestModuleA(unittest.TestCase):
def testSomething(self):
a = A()
self.assertTrue(a.do_something() == "Something was done")
test.sh
是这个:
#!/bin/bash
TEST_PACKAGE="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
cd ${TEST_PACKAGE}
python3 -m unittest test.test_moduleA
为了通过测试,我也更改了 class:
class A:
def do_something(self):
print("do_somwthing was called")
return "Something was done"
现在,运行 test.sh
它应该按预期工作:
$ ./test.sh
do_somwthing was called
.
----------------------------------------------------------------------
Ran 1 test in 0.000s
OK
我正在努力让导入为我的 python 项目工作。我创建了一个测试项目来说明我的问题。这是 Python 3.
我的目录结构如下:
project/
test.sh
packageA/
__init__.py
moduleA.py
test/
__init__.py
test_moduleA.py
test.sh的内容是python3 packageA/test/test_moduleA.py
两个__init__py
都是空的。
这是moduleA.py
:
class A:
def doSomething(self):
print("Did something")
这是“test_moduleA.py”:
import unittest
from packageA.moduleA import A
class TestModuleA(unittest.TestCase):
def testSomething(self):
a = A()
self.assertTrue(a.doSomething() == "Did Something")
if __name__ == '__main__':
unittest.main()
当我 运行 test.sh
这是我得到的错误:
[project] $ ./test.sh
Traceback (most recent call last):
File "packageA/test/test_moduleA.py", line 2, in <module>
from packageA.moduleA import A
ModuleNotFoundError: No module named 'packageA'
[project] $
我试过在“test_moduleA.py”中使用相对导入,如下所示:
from ..moduleA import A
在这种情况下,我得到的错误如下所示:
[project] $ ./test.sh
Traceback (most recent call last):
File "packageA/test/test_moduleA.py", line 2, in <module>
from ..moduleA import A
ValueError: attempted relative import beyond top-level package
[project] $
如何让它正常工作? Pythonic 方法是什么?
将 shell 脚本用于 test/deploy python 并不是一个好主意,因此我建议您将 test.sh 替换为 test.py
,其内容为:
import unittest
testmodules = [
'packageA.test.test_moduleA',
]
suite = unittest.TestSuite()
for t in testmodules:
try:
mod = __import__(t, globals(), locals(), ['suite'])
suitefn = getattr(mod, 'suite')
suite.addTest(suitefn())
except (ImportError, AttributeError):
suite.addTest(unittest.defaultTestLoader.loadTestsFromName(t))
unittest.TextTestRunner().run(suite)
向其中添加新测试非常容易,您只需要修改测试模块列表即可。
这是我基于 this answer (see also here) and this article 建议的解决方案。
首先,将测试目录移动到项目的根目录中:
project/
test.sh
packageA/
__init__.py
moduleA.py
test/
__init__.py
test_moduleA.py
然后,将 test_moduleA.py
更改如下(注意导入):
import unittest
from packageA.moduleA import A
class TestModuleA(unittest.TestCase):
def testSomething(self):
a = A()
self.assertTrue(a.do_something() == "Something was done")
test.sh
是这个:
#!/bin/bash
TEST_PACKAGE="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
cd ${TEST_PACKAGE}
python3 -m unittest test.test_moduleA
为了通过测试,我也更改了 class:
class A:
def do_something(self):
print("do_somwthing was called")
return "Something was done"
现在,运行 test.sh
它应该按预期工作:
$ ./test.sh
do_somwthing was called
.
----------------------------------------------------------------------
Ran 1 test in 0.000s
OK