使用doctest测试异常链接和回溯输出

时间:2018-11-23 15:30:22

标签: python doctest

如何使用doctest测试“多重回溯”? 看来使用多个ELLIPSIS<BLANKLINE>并不能解决问题:

def myfunc():
    """

    >>> myfunc()
    Traceback (most recent call last):
     ...
    ValueError: this is
    <BLANKLINE>
    The above exception was the direct cause of the following exception:
    <BLANKLINE>
    Traceback (most recent call last):
     ...
    TypeError: it

    """
    try:
        raise ValueError('this is')
    except ValueError as err:
        raise TypeError('it') from err


import doctest
doctest.testmod(optionflags=doctest.REPORT_NDIFF|doctest.ELLIPSIS)

结果:

"test.py" 23L, 490C written
**********************************************************************
File "test.py", line 4, in __main__.myfunc
Failed example:
    myfunc()
Differences (ndiff with -expected +actual):
      Traceback (most recent call last):
    -  ...
    +   File "test.py", line 17, in myfunc
    +     raise ValueError('this is')
      ValueError: this is
      <BLANKLINE>
      The above exception was the direct cause of the following exception:
      <BLANKLINE>
      Traceback (most recent call last):
    -  ...
    +   File "/usr/lib/python3.7/doctest.py", line 1329, in __run
    +     compileflags, 1), test.globs)
    +   File "<doctest __main__.myfunc[0]>", line 1, in <module>
    +     myfunc()
    +   File "test.py", line 19, in myfunc
    +     raise TypeError('it') from err
      TypeError: it
**********************************************************************
1 items had failures:
   1 of   1 in __main__.myfunc
***Test Failed*** 1 failures.

但是如果我全部压扁,它将通过:

>>> myfunc()
Traceback (most recent call last):
 ...
TypeError: it

1 个答案:

答案 0 :(得分:0)

恐怕无法以这种方式检查“多重回溯”。

问题在于doctest会忽略除异常类及其消息以外的所有内容。

在您的示例中,它将是:

TypeError: it

如果您对它的工作方式感兴趣,请检查doctest.py并搜索

exc_msg = traceback.format_exception_only(*exception[:2])[-1]

“ exc_msg”将仅包含引发的异常的详细信息:

TypeError: it

替代品

如果可能,您可以更改测试以不引发任何异常,而是打印所需的消息。

另一种可能性是使用另一个{doc}引擎,例如byexample。它的工作方式与doctest相同,但更加灵活(quick overview here)。

如果您进行了大量测试,则可以尝试使用its compatibility mode with doctest来避免重写所有内容。

以您的示例为例,

"""                                                                                                                            
>>> from your_module import myfunc                                                                                             
"""                                                                                                                            

def myfunc():                                                                                                                  
    """                                                                                                                        

    >>> myfunc()                                                                                                               
    Traceback (most recent call last):                                                                                         
     ...                                                                                                                       
    ValueError: this is                                                                                                        
    <BLANKLINE>                                                                                                                
    The above exception was the direct cause of the following exception:                                                       
    <BLANKLINE>                                                                                                                
    Traceback (most recent call last):                                                                                         
     ...                                                                                                                       
    TypeError: it                                                                                                              

    """                                                                                                                        
    try:                                                                                                                       
        raise ValueError('this is')                                                                                            
    except ValueError as err:                                                                                                  
        raise TypeError('it') from err

要运行它,您可以在shell中执行

byexample -l python -o '+py-doctest -py-pretty-print +ELLIPSIS' your_module.py

免责声明:我是byexample的作者。我是doctest的忠实粉丝,但我知道它有其局限性,而检查异常就是其中之一(特别是如果您在双重Python 2.x / 3.x项目中工作)。

基于这个原因,我创建了byexample:这对我真的很有用,我也希望对其他人也有用。

在这里或github中问我任何问题