是否可以实现一个具有如下文件结构的Python项目?:
myproj
├── a.py
├── b.py
├── c.py
└── test/
├── a.py
├── b.py
└── c.py
Note, in particular, that the test scripts under test/
have the same basenames as the module files they are testing 1. (In other words, test/a.py
contains the unit tests for a.py
; test/b.py
contains those for b.py
, etc.)
下的测试test/
全部进口unittest
并定义子类unittest.TestCase
.
我想知道如何运行测试test/
,无论是单独的还是一起的。
我尝试过很多变体python -m unittest ...
,但它们要么失败(下面的示例),要么最终运行零测试。
例如,
% python -m unittest test.a
Traceback (most recent call last):
File "/usr/lib/python2.7/runpy.py", line 174, in _run_module_as_main
"__main__", fname, loader, pkg_name)
File "/usr/lib/python2.7/runpy.py", line 72, in _run_code
exec code in run_globals
File "/usr/lib/python2.7/unittest/__main__.py", line 12, in <module>
main(module=None)
File "/usr/lib/python2.7/unittest/main.py", line 94, in __init__
self.parseArgs(argv)
File "/usr/lib/python2.7/unittest/main.py", line 149, in parseArgs
self.createTests()
File "/usr/lib/python2.7/unittest/main.py", line 158, in createTests
self.module)
File "/usr/lib/python2.7/unittest/loader.py", line 130, in loadTestsFromNames
suites = [self.loadTestsFromName(name, module) for name in names]
File "/usr/lib/python2.7/unittest/loader.py", line 100, in loadTestsFromName
parent, obj = obj, getattr(obj, part)
AttributeError: 'module' object has no attribute 'a'
如果我更改名称test/
目录到t/
,则错误变为:
% python -m unittest t.a
Traceback (most recent call last):
File "/usr/lib/python2.7/runpy.py", line 174, in _run_module_as_main
"__main__", fname, loader, pkg_name)
File "/usr/lib/python2.7/runpy.py", line 72, in _run_code
exec code in run_globals
File "/usr/lib/python2.7/unittest/__main__.py", line 12, in <module>
main(module=None)
File "/usr/lib/python2.7/unittest/main.py", line 94, in __init__
self.parseArgs(argv)
File "/usr/lib/python2.7/unittest/main.py", line 149, in parseArgs
self.createTests()
File "/usr/lib/python2.7/unittest/main.py", line 158, in createTests
self.module)
File "/usr/lib/python2.7/unittest/loader.py", line 130, in loadTestsFromNames
suites = [self.loadTestsFromName(name, module) for name in names]
File "/usr/lib/python2.7/unittest/loader.py", line 91, in loadTestsFromName
module = __import__('.'.join(parts_copy))
ImportError: No module named t
Or
% python -m unittest t/a.py
Traceback (most recent call last):
File "/usr/lib/python2.7/runpy.py", line 174, in _run_module_as_main
"__main__", fname, loader, pkg_name)
File "/usr/lib/python2.7/runpy.py", line 72, in _run_code
exec code in run_globals
File "/usr/lib/python2.7/unittest/__main__.py", line 12, in <module>
main(module=None)
File "/usr/lib/python2.7/unittest/main.py", line 94, in __init__
self.parseArgs(argv)
File "/usr/lib/python2.7/unittest/main.py", line 149, in parseArgs
self.createTests()
File "/usr/lib/python2.7/unittest/main.py", line 158, in createTests
self.module)
File "/usr/lib/python2.7/unittest/loader.py", line 130, in loadTestsFromNames
suites = [self.loadTestsFromName(name, module) for name in names]
File "/usr/lib/python2.7/unittest/loader.py", line 91, in loadTestsFromName
module = __import__('.'.join(parts_copy))
ImportError: Import by filename is not supported.
(我使用的是Python 2.7.9。)
UPDATE
由于我对这个问题给予了奖励,因此我将非常明确地说明什么是可接受的答案。
以下任何一项都是可以接受的:
作为基本案例,从以下最小案例开始,具有以下文件结构:
myproj
├── a.py
├── b.py
└── test/
├── a.py
└── b.py
...以及以下内容
# a.py
def hello():
print 'hello world'
# b.py
def bye():
print 'good-bye world'
# test/a.py
import unittest
import a
class TestA(unittest.TestCase):
def test_hello(self):
self.assertEqual(a.hello(), None)
# test/b.py
import unittest
import b
class TestB(unittest.TestCase):
def test_bye(self):
self.assertEqual(b.bye(), None)
展示一个人如何讲述unittest
运行测试test/a.py
,以及如何运行“所有测试test
”。(后者应该继续工作,即使新的测试脚本被添加到test
,或者删除一些当前的测试脚本。)
对迄今为止提出的建议进行的最低限度测试表明它们不起作用。例如:
% python -m unittest discover -s test -p '*.py'
EE
======================================================================
ERROR: test_hello (a.TestA)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/SHIVAMJINDAL/myproj/test/a.py", line 6, in test_hello
self.assertEqual(a.hello(), None)
AttributeError: 'module' object has no attribute 'hello'
======================================================================
ERROR: test_bye (b.TestB)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/SHIVAMJINDAL/myproj/test/b.py", line 6, in test_bye
self.assertEqual(b.bye, None)
AttributeError: 'module' object has no attribute 'bye'
----------------------------------------------------------------------
Ran 2 tests in 0.000s
FAILED (errors=2)
% tree .
.
├── a.py
├── b.py
├── __init__.py
└── test/
├── a.py
├── b.py
└── __init__.py
1 directory, 6 files
1 This constraint is very much intentional, and it is an integral part of the problem presented here. (IOW, a "solution" that entails relaxing this constraint is in fact not a solution.)