用鼻子重复单次或多次测试

时间:2012-11-28 18:08:39

标签: python nose

this question类似,我希望让Nose运行测试(或所有测试)n次 - 但不是并行。

我在一个项目中有几百个测试;一些是一些简单的单元测试。其他是具有某种程度并发性的集成测试。经常在调试测试时,我想更“努力”地测试一下;一个bash循环工作,但会产生很多杂乱的输出 - 没有更好的单一“。”每次通过测试。有能力击败一些试验的选定测试似乎是让Nose做的自然事情,但我没有在文档中找到它。

让Nose做到这一点最简单的方法是什么(除了bash循环)?

5 个答案:

答案 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设计(减少组件之间的依赖关系),测试更容易编写,并且运行整个测试套件所需的时间大大减少。

使用上述方法可以完全消除不可靠测试的问题,我建议这样做,不仅要改进测试,还要改进代码库和设计能力。