Nose: 测试指定包中的所有模块
我有一个包含多个子包的包,其中一个子包是用来测试的,叫做 tests
。因为这个子包的名字已经很清楚地表明里面的模块是测试模块,所以我不想让模块的名字被测试相关的命名规则搞得乱七八糟,这些规则是 nose 需要用来找测试的。我想要的设置是这样的:
- foo
- __init__.py
...
- bar
- __init__.py
...
- baz
- __init__.py
...
- tests
- __init__.py
- something.py
现在,默认情况下,nose 不会运行在 foo.tests.something
中找到的测试。我知道 nose 可以用 -i
选项来定义正则表达式,以便在其他地方搜索测试。所以 nose -i something
可以解决这个问题。不过,我在 tests
包里有很多模块,不想一个个地明确命名。 nose -i tests\..*
也不行,因为看起来 nose 只匹配模块的基本名称。作为最后的办法,我可以运行 nose --all-modules
,但这样也会检查 foo.bar
和 foo.baz
,我想避免这种情况。
那么,我该如何指示 nose 在指定包(在我这里是 tests
)中的所有模块里寻找测试呢?我可以为这个任务写一个 nose 插件,但我在寻找一个标准的解决方案。
3 个回答
使用Nose:
nosetests --all-modules
如果你用的是py.test,可以在setup.cfg(配置文件)里加上这个:
[pytest]
python_files=*.py
查看这个文档:pytest文档。
如果你在测试文件的名字前加上一个 test_
的前缀(比如把 something.py
改成 test_something.py
),那么运行 nose 时,它会默认识别这些文件。
你说“我不想让模块名字被测试名称的模式弄得乱七八糟”,但是“something”这个名字并不能清楚地说明这个文件的内容,因为这个文件是用来测试某个东西的。那为什么不使用这种简单明了、标准的命名方式来命名你的测试呢?
你应该可以把文件导入到你的 __init__.py
文件中,这样它们就能被识别了。我之前是这样设置的:
- app:
- __init__.py
- models.py
- views.py
- tests:
- __init__.py
- models.py # contain tests
- views.py # contain tests
在 tests/__init__.py
文件里,我有以下内容:
from app.tests.models import *
from app.tests.views import *
这样做虽然有点违背了使用正则表达式查找测试的一个好处(这是nose的一个目标),但还是能正常工作。
如果你想避免方法名称和正则表达式匹配,可以使用 @istest
这个装饰器来标记某个函数为测试。我没有尝试过对那些不符合正则表达式的模块(py文件)使用这个装饰器,但我怀疑如果没有上面的导入,它是行不通的。
另外,我现在不再在 __init__.py
中做导入了,而是把我的测试方法和文件名都加上前缀 test_,把类名加上后缀 Test。我发现这样做让代码更容易理解,因为即使在一个测试类里,可能还有一些设置方法和辅助方法(比如生成器)。