使用doctests,coverage和parallelism进行Python测试发现

时间:2013-06-07 11:00:44

标签: python unit-testing discovery python-coverage

......还有一匹小马!不,真的。我正在寻找一种方法来组织“正常工作”的测试。大多数事情都有效,但并非所有部分都适合。所以这就是我想要的:

  • 自动发现测试。这包括doctests。请注意,doctests的总和不得显示为单个测试。 (即不是什么py.test --doctest-modules)
  • 能够并行运行测试。 (像xdist中的py.test -n之类的东西)
  • 生成覆盖率报告。
  • python setup.py test正常工作。

我目前的方法涉及tests目录和load_tests protocol。包含的所有文件都命名为test_*.py。如果我使用以下内容创建文件python -m unittest discover,这会使test_doctests.py正常工作。

import doctest
import mymodule1, mymodule2
def load_tests(loader, tests, ignore):
    tests.addTests(doctest.DocTestSuite(mymodule1))
    tests.addTests(doctest.DocTestSuite(mymodule2))
    return tests

这种方法还有一个好处,就是可以使用setuptools并提供setup(test_suite="unittest2.collector")

然而,这种方法存在一些问题。

  • coverage.py期望运行一个脚本。所以我不能在这里使用unittest2发现。
  • py.test不运行load_tests函数,因此它找不到doctests而--doctest-modules选项是废话。
  • nosetests运行load_tests函数,但不提供任何参数。这看起来完全打破了鼻子。

如何让事情比这更好或解决上面的一些问题?

2 个答案:

答案 0 :(得分:1)

我使用鼻子,当我遇到同样的问题时找到了你的问题。

我最终得到的并不漂亮,但确实运行了测试。

import doctest
import mymodule1, mymodule2

def test_mymodule1():
    assert doctest.testmod(mymodule1, raise_on_error=True)

def test_mymodule2():
    assert doctest.testmod(mymodule2, raise_on_error=True)

不幸的是,它将模块中的所有doctests作为单个测试运行。但如果出现问题,至少我知道从哪里开始寻找。失败会导致DocTestFailure,并提供有用的消息:

DocTestFailure: <DocTest mymodule1.myfunc from /path/to/mymodule1.py:63 (4 examples)>

答案 1 :(得分:1)

这是一个老问题,但问题仍然存在于我们中的一些人身上!我刚刚完成它并找到了类似于kaapstorm的解决方案,但输出效果更好。我使用py.test来运行它,但我认为它应该与测试运行者兼容:

import doctest
from mypackage import mymodule

def test_doctest():
    results = doctest.testmod(mymodule)
    if results.failed:
        raise Exception(results)

我在失败案例中最终得到的是您手动运行doctest时可以获得的打印标准输出,另外一个例外情况如下:

Exception: TestResults(failed=1, attempted=21)

正如kaapstrom所提到的那样,它并没有正确计算测试(除非有失败),但我发现如果覆盖率数字很高,那么它并不值得一试:)