如何使 python 的覆盖率库包含 doctests

How to make python's coverage library include doctests

从谷歌搜索和实验来看,python 的 coverage 库似乎在其计算中不包括 doctests。有什么办法让它这样做吗?

我搜索了文档 (https://coverage.readthedocs.io/en/coverage-4.4.1/) 并没有发现任何关于 doctests 的提及,但看起来很奇怪,它没有 some 包含它们的方式我觉得我一定是错过了什么。

如果我是对的并且覆盖率不包括它们,我如何才能测量我的测试覆盖率而不用 unittest 将我的所有 doctests 更改为单元测试(我不想做)?

模块的 doctests 可以转换为 unittest 的测试套件

import mymodule
suite = doctest.DocTestSuite(mymodule)

想到了两种方法,要么让模块导入自身,要么从另一个模块加载模块。

让模块自行导入

在文件 a.py 中:

def linear(a, b):
    ''' Solve ax + b = 0

        >>> linear(3, 5)
        -1.6666666666666667

    '''
    if a == 0 and b != 0:
        raise ValueError('No solutions')
    return -b  / a

if __name__ == '__main__':
    import doctest
    import a

    print(doctest.testmod(a))

在命令行:

$ coverage run a.py
$ coverage annotate
$ cat a.py,cover

这会产生:

> def linear(a, b):
>     ''' Solve ax + b = 0

>         >>> linear(3, 5)
>         -1.6666666666666667

>     '''
>     if a == 0 and b != 0:
!         raise ValueError('No solutions')
>     return -b  / a

> if __name__ == '__main__':
>     import doctest
>     import a

>     print(doctest.testmod(a))

运行 来自单独模块的测试

或者,您可以将导入和 testmod() 移出 a.py 并将它们放在单独的模块中。

在文件中 b.py

import doctest
import a

print(doctest.testmod(a))

在命令行:

$ coverage run b.py
$ coverage annotate
$ cat a.py,cover

这会产生:

> def linear(a, b):
>     ''' Solve ax + b = 0

>         >>> linear(3, 5)
>         -1.6666666666666667

>     '''
>     if a == 0 and b != 0:
!         raise ValueError('No solutions')
>     return -b  / a