与this question类似,我希望让Nose运行测试(或所有测试)n
次 - 但不是并行。
我在一个项目中有几百个测试;一些是一些简单的单元测试。其他是具有某种程度并发性的集成测试。经常在调试测试时,我想更“努力”地测试一下;一个bash循环工作,但会产生很多杂乱的输出 - 没有更好的单一“。”每次通过测试。有能力击败一些试验的选定测试似乎是让Nose做的自然事情,但我没有在文档中找到它。
让Nose做到这一点最简单的方法是什么(除了bash循环)?
答案 0 :(得分:14)
你可以write a nose test as a generator,然后鼻子将运行每个功能 得到:
def check_something(arg):
# some test ...
def test_something():
for arg in some_sequence:
yield (check_something, arg)
使用nose-testconfig,可以使测试运行次数成为命令行参数:
from testconfig import config
# ...
def test_something():
for n in range(int(config.get("runs", 1))):
yield (check_something, arg)
您可以从命令行调用例如
$ nosetests --tc=runs:5
......不止一次。
或者(但也使用nose-testconfig),你可以写一个装饰器:
from functools import wraps
from testconfig import config
def multi(fn):
@wraps(fn)
def wrapper():
for n in range(int(config.get("runs", 1))):
fn()
return wrapper
@multi
def test_something():
# some test ...
然后,如果您想将测试划分为不同的组,每个组都有自己的命令行参数来表示运行次数:
from functools import wraps
from testconfig import config
def multi(cmd_line_arg):
def wrap(fn):
@wraps(fn)
def wrapper():
for n in range(int(config.get(cmd_line_arg, 1))):
fn()
return wrapper
return wrap
@multi("foo")
def test_something():
# some test ...
@multi("bar")
def test_something_else():
# some test ...
你可以这样打电话:
$ nosetests --tc=foo:3 --tc=bar:7
答案 1 :(得分:2)
测试本身就是一种方式:
改变这个:
class MyTest(unittest.TestCase):
def test_once(self):
...
对此:
class MyTest(unittest.TestCase):
def assert_once(self):
...
def test_many(self):
for _ in range(5):
self.assert_once()
答案 2 :(得分:2)
您必须编写一个脚本来执行此操作,但您可以在命令行上重复测试名称X次。
nosetests testname testname testname testname testname testname testname
等。
答案 3 :(得分:1)
我最终使用的解决方法是创建sh脚本run_test.sh:
var=0
while $1; do
((var++))
echo "*** RETRY $var"
done
用法:
./run_test.sh "nosetests TestName"
它无限运行测试但在第一次错误时停止。
答案 4 :(得分:0)
永远不应该有理由不止一次地运行测试。重要的是你的测试是确定性的(即,给定相同的代码库状态,它们总是产生相同的结果。)如果不是这种情况,那么你应该重新设计测试和/或重新设计测试,而不是多次运行测试。代码,以便它们。
例如,间歇性测试失败的一个原因是测试和被测代码(CUT)之间的竞争条件。在这种情况下,一个天真的反应是在测试中添加一个大的“伏都教睡眠”,以“确保”在测试开始断言之前完成CUT。
这很容易出错,因为如果您的CUT由于任何原因(动力不足的硬件,加载的盒子,繁忙的数据库等)而变慢,那么它会偶尔失败。在这种情况下,更好的解决方案是让您的测试等待事件,而不是睡觉。
活动可能是您选择的任何事情。有时,您可以使用的事件已经生成(例如Javascript DOM事件,Selenium测试可以使用的'pageRendered'事件。)其他时候,您可能适合向CUT添加代码,这会引发一个事件完成后(也许你的架构涉及对此类事件感兴趣的其他组件。)
通常,你需要重新编写测试,以便它试图检测你的CUT是否已经完成执行(例如输出文件是否存在?),如果没有,则睡眠50ms然后再次尝试。最终它会超时并失败,但只能在很长一段时间后完成(例如,你的CUT预期执行时间的100倍)
另一种方法是使用'洋葱/六角形/端口''适配器原理设计您的CUT,这些原则坚持您的业务逻辑应该没有任何外部依赖性。这意味着您的业务逻辑可以使用普通的亚毫秒单元测试进行测试,这些测试从不接触网络或文件系统。完成此操作后,您需要的端到端系统测试要少得多,因为它们现在只用作集成测试,而不需要尝试通过UI操作业务逻辑的每个细节和边缘情况。 。这种方法在其他领域也会带来很大的好处,例如改进的CUT设计(减少组件之间的依赖关系),测试更容易编写,并且运行整个测试套件所需的时间大大减少。
使用上述方法可以完全消除不可靠测试的问题,我建议这样做,不仅要改进测试,还要改进代码库和设计能力。