myproj ├── a.py ├── b.py ├── c.py └── test/ ├── a.py ├── b.py └── c.py
特别要注意,测试中的测试脚本与他们测试的模块文件具有相同的基本名称.(换句话说,test / a.py包含a.py的单元测试; test / b.py包含对于b.py等的那些)
测试中的测试/所有导入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'
% python -m unittest t.a Traceback (most recent call last): File "/usr/lib/python2.7/runpy.py",line 91,in loadTestsFromName module = __import__('.'.join(parts_copy)) ImportError: No module named t
要么
% python -m unittest t/a.py Traceback (most recent call last): File "/usr/lib/python2.7/runpy.py",in loadTestsFromName module = __import__('.'.join(parts_copy)) ImportError: Import by filename is not supported.
(我使用的是Python 2.7.9.)
UPDATE
由于我对这个问题给予了赏识,我将非常明确地说明什么是可接受的答案.
以下任一项都是可以接受的:
>如何从命令行调用unittest来运行单个测试或test /目录下的所有测试;解决方案可以接受对测试脚本中的代码进行小的更改(例如对import语句的修改).
>如果出于某种原因无法使用上面显示的文件结构,则详细说明将是可接受的解决方案.
作为基本案例,从以下最小案例开始,使用以下文件结构:
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,以及如何运行“所有测试中的测试”. (后者应该继续工作,即使添加了新的测试脚本进行测试,或者删除了一些当前的测试脚本.)
迄今为止提供的建议的最小测试表明它们不起作用.例如:
% 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",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这种约束是非常有意的,它是这里提出的问题的一个组成部分. (IOW,需要放松这种约束的“解决方案”实际上不是解决方案.)
解决方法
>应该使用父目录上下文运行测试
>主文件夹和测试文件夹都应该有__init__.py
>测试中的导入应该是相对导入而不是直接导入
所以下面是我的树形结构
root@5db7ad85dafd:/project# tree . __init__.py a.py test __init__.py a.py 1 directory,4 files root@5db7ad85dafd:/project# python --version Python 2.7.9
项目/ a.py
hello = 'tarun'
项目/测试/ a.py
import unittest from .. import a class TestStringMethods(unittest.TestCase): def test_abc(self): assert a.hello == "tarun"
注意from .. import a导入为此工作
接下来,我们将测试放在项目的根文件夹中,如下所示
root@5db7ad85dafd:/project# python -m unittest discover -t .. -s test -p "*.py" . ---------------------------------------------------------------------- Ran 1 test in 0.000s OK
-t这里设置顶级导入目录,因此我们的相对导入可以工作
-s告诉我们测试的目录
-p告诉应该发现测试的模式
当您想要进行单独的测试时,您将执行以下操作
python -m unittest discover -t .. -s test -p "a.py"
要么
python -m unittest discover -t .. -s test -p "*.py" a
编辑-1
在看到Peter的回答之后想要更新我的回答.我没有提到从固定命名包导入的原因是,这意味着您需要知道克隆代码的文件夹的名称,并强制保持相同.但是如果你仍然想要采用这种方法,那么一种方法是将实际移动到子文件夹中
所以它将是repo / project / test / a.py,然后在您的测试中使用
from project import a
然后从repo文件夹中运行它,如下所示
root@5db7ad85dafd:/repo# python -m unittest discover -v -t project -s project.test -p "*.py" test_abc (test.a.TestStringMethods) ... ok ---------------------------------------------------------------------- Ran 1 test in 0.000s OK
或者像下面的测试文件夹一样
root@5db7ad85dafd:/repo/project# python -m unittest discover -v -t .. -s test -p "*.py" test_abc (project.test.a.TestStringMethods) ... ok ---------------------------------------------------------------------- Ran 1 test in 0.001s OK