pythondoctest中的对象重用

pythondoctest中的对象重用,python,unit-testing,doctest,Python,Unit Testing,Doctest,我有一个像这样的医生测试样本 """ This is the "iniFileGenerator" module. >>> hintFile = "./tests/unit_test_files/hint.txt" >>> f = iniFileGenerator(hintFile) >>> print f.hintFilePath ./tests/unit_test_files/hint.txt """ class iniFileGener

我有一个像这样的医生测试样本

"""
This is the "iniFileGenerator" module.
>>> hintFile = "./tests/unit_test_files/hint.txt"
>>> f = iniFileGenerator(hintFile)
>>> print f.hintFilePath
./tests/unit_test_files/hint.txt
"""
class iniFileGenerator:
    def __init__(self, hintFilePath):
        self.hintFilePath = hintFilePath
    def hello(self):
        """
        >>> f.hello()
        hello
        """
        print "hello"
if __name__ == "__main__":
    import doctest
    doctest.testmod()
当我执行这段代码时,我得到了这个错误

Failed example:
    f.hello()
Exception raised:
    Traceback (most recent call last):
      File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/doctest.py", line 1254, in __run
        compileflags, 1) in test.globs
      File "<doctest __main__.iniFileGenerator.hello[0]>", line 1, in <module>
        f.hello()
    NameError: name 'f' is not defined
您可以使用
testmod(extraglobs={'f':initFileGenerator(“”)})
全局定义可重用对象

正如《圣经》所说

extraglobs提供了一个dict,该dict合并到用于执行示例的globals中。这与dict.update()类似

但我过去总是在所有方法之前测试类的
\uuuu doc\uu
中的所有方法

class MyClass(object):
    """MyClass
    >>> m = MyClass()
    >>> m.hello()
    hello
    >>> m.world()
    world
    """

    def hello(self):
        """method hello"""
        print 'hello'

    def world(self):
        """method world"""
        print 'world'

要获得所有测试都使用共享执行上下文(即可以共享和重用结果的单个测试)的可读模块,必须查看的相关部分如下:

。。。每次
doctest
找到要测试的文档字符串时,它都会使用
M
的全局文件的一个浅副本,这样运行测试不会改变模块的真实全局文件,并且
M
中的一个测试不会留下碎屑,意外地允许另一个测试工作

您可以通过将
globs=your_dict
传递到
testmod()
testfile()
来强制使用您自己的dict
作为执行上下文

鉴于此,在
doctest
模块中,除了使用copies(即
dict
copy()
方法)外,它还可以在每次测试后清除全局dict(使用
clear()

因此,您可以使用以下内容修补自己的globals字典:

class Context(dict):
    def clear(self):
        pass
    def copy(self):
        return self 
然后将其用作:

import doctest
from importlib import import_module

module = import_module('some.module')
doctest.testmod(module,
                # Make a copy of globals so tests in this
                # module don't affect the tests in another
                glob=Context(module.__dict__.copy()))

对于任何像我这样发现这个的人,这里有一个简单的破解方法来解决这个问题

在模块文档中,将“全局”值作为
内置模块的属性附加,例如

“”“
我的模块文档
>>>进口内置设备
>>>builtins.sample\u value=“这是一个长值”
>>>builtins.sample_func=lambda x:x.lower()
"""
内置
模块会自动导入到每个作用域中,因此其属性将在您的函数中可用,包括doctest函数

def first\u char\u func(s:str)->str:
"""
返回函数的第一个字符
>>>第一个字符函数(样本函数(样本值))
H
"""  
如果len(s)>0,则返回s[0],否则无

然而,可以说,一旦你达到了这个阶段,你最好只写一个单元测试。

就在我之前,是的,在extraglobs上。虽然我不喜欢extraglobs方法,但我不太喜欢这个答案——doctests的一些要点是记录方法,你在这里丢失了这些方法。@Thomas在我检查了一些流行的和有良好文档记录的项目的源代码后,我认为这没问题,很酷——我只是喜欢在DocString中看到它,这样我就可以调用help()在方法上查看它是如何工作的,而不是滚动类文档。
import doctest
from importlib import import_module

module = import_module('some.module')
doctest.testmod(module,
                # Make a copy of globals so tests in this
                # module don't affect the tests in another
                glob=Context(module.__dict__.copy()))