在 doctest 字符串中嵌入测试代码或数据

发布于 2024-09-11 05:09:57 字数 1346 浏览 5 评论 0原文

我希望文件中的几个文档测试共享测试数据和/或函数。有没有办法做到这一点,而无需将它们定位在外部文件或正在测试的文件的代码中?

更新

"""This is the docstring for the module ``fish``.

I've discovered that I can access the module under test
  from within the doctest, and make changes to it, eg


>>> import fish
>>> fish.data = {1: 'red', 2: 'blue'}
"""

def jef():
    """
    Modifications made to the module will persist across subsequent tests:

    >>> import fish
    >>> fish.data[1]
    'red'
    """
    pass

def seuss():
    """
    Although the doctest documentation claims that
      "each time doctest finds a docstring to test,
       it uses a shallow copy of M‘s globals",
      modifications made to the module by a doctest
      are not imported into the context of subsequent docstrings:

    >>> data
    Traceback (most recent call last):
      ...
    NameError: name 'data' is not defined
    """
    pass

所以我猜 doctest 复制模块一次,然后复制每个文档字符串的副本?

无论如何,将模块导入到每个文档字符串中似乎是有用的,尽管有些尴尬。

我更愿意为此使用单独的命名空间,以避免意外践踏实际模块数据,这些数据将或不会以可能未记录的方式导入到后续测试中。

我发现(理论上)可以动态创建一个模块来包含这个名称空间。然而,到目前为止,我还没有从我提出的问题中得到关于如何做到这一点的任何指示不久前。任何信息都非常受欢迎! (作为对适当问题的回答)

无论如何,我希望将更改直接传播到后续文档字符串的名称空间中。所以我原来的问题仍然存在,并将其作为限定词。

I'd like to have several of the doctests in a file share test data and/or functions. Is there a way to do this without locating them in an external file or within the code of the file being tested?

update

"""This is the docstring for the module ``fish``.

I've discovered that I can access the module under test
  from within the doctest, and make changes to it, eg


>>> import fish
>>> fish.data = {1: 'red', 2: 'blue'}
"""

def jef():
    """
    Modifications made to the module will persist across subsequent tests:

    >>> import fish
    >>> fish.data[1]
    'red'
    """
    pass

def seuss():
    """
    Although the doctest documentation claims that
      "each time doctest finds a docstring to test,
       it uses a shallow copy of M‘s globals",
      modifications made to the module by a doctest
      are not imported into the context of subsequent docstrings:

    >>> data
    Traceback (most recent call last):
      ...
    NameError: name 'data' is not defined
    """
    pass

So I guess that doctest copies the module once, and then copies the copy for each docstring?

In any case, importing the module into each docstring seems usable, if awkward.

I'd prefer to use a separate namespace for this, to avoid accidentally trampling on actual module data that will or will not be imported into subsequent tests in an possibly undocumented manner.

It's occurred to me that it's (theoretically) possible to dynamically create a module in order to contain this namespace. However as yet I've not gotten any direction on how to do that from the question I asked about that a while back. Any information is quite welcome! (as a response to the appropriate question)

In any case I'd prefer to have the changes be propagated directly into the namespace of subsequent docstrings. So my original question still stands, with that as a qualifier.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

饮湿 2024-09-18 05:09:57

这就是导致人们放弃文档测试的原因:随着测试变得越来越复杂,您需要真正的编程工具来设计测试,就像设计产品代码一样。

我认为除了在产品代码中定义它们然后在文档测试中使用它们之外,没有其他方法可以在文档测试中包含共享数据或函数。

您将需要使用真实的代码来定义一些测试基础设施。如果您喜欢文档测试,您可以使用文档测试中的基础设施。

This is the sort of thing that causes people to turn away from doctests: as your tests grow in complexity, you need real programming tools to be able to engineer your tests just as you would engineer your product code.

I don't think there's a way to include shared data or functions in doctests other than defining them in your product code and then using them in the doctests.

You are going to need to use real code to define some of your test infrastructure. If you like doctests, you can use that infrastructure from your doctests.

天冷不及心凉 2024-09-18 05:09:57

这是可能的,尽管可能没有那么大声地宣传。

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

...每次 doctest 找到要测试的文档字符串时,它都会使用 M 副本的全局变量,以便运行测试不会更改模块的实际全局变量,并且 M 中的一个测试不会留下意外允许另一测试工作的碎片。

...

您可以通过将 globs=your_dict 传递给 testmod() 来强制使用您自己的字典作为执行上下文code> 或 testfile() 代替。


鉴于此,我设法从 doctest 模块进行逆向工程除了使用副本(即 dictcopy() 方法)之外,它还会在每次调用后清除全局字典(使用 clear())测试。

因此,人们可以用以下内容修补自己的全局字典:

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()))

This is possible, albeit perhaps not advertised as loudly.

To obtain literate modules with tests that all use a shared execution context (i.e. individual tests can share and re-use their results), one has to look at the relevant part of documentation which says:

... each time doctest finds a docstring to test, it uses a shallow copy of M‘s globals, so that running tests doesn’t change the module’s real globals, and so that one test in M can’t leave behind crumbs that accidentally allow another test to work.

...

You can force use of your own dict as the execution context by passing globs=your_dict to testmod() or testfile() instead.

Given this, I managed to reverse-engineer from doctest module that besides using copies (i.e. the dict's copy() method), it also clears the globals dict (using clear()) after each test.

Thus, one can patch their own globals dictionary with something like:

class Context(dict):
    def clear(self):
        pass
    def copy(self):
        return self 

and then use it as:

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()))
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文