如何验证 python IOBase 的实现?

Jor*_*ips 6 python testing io

是否有现有的测试套件可供我用来测试其实现IOBase?如果可能的话,我想详尽地测试一个新的实现,但是有很多测试需要手动编写。

例如,假设我有一个不可查找、不可写的流。我想验证我的实现read是否合规,并且所有其他方法都会引发正确类型的错误。这样的类可能如下所示:

import io


class NonSeekableReader(io.RawIOBase):
    def __init__(self, b=b''):
        super(NonSeekableReader, self).__init__()
        self._data = io.BytesIO(b)

    def seekable(self):
        return False

    def writable(self):
        return False

    def readable(self):
        return True

    def read(self, n=-1):
        return self._data.read(n)
Run Code Online (Sandbox Code Playgroud)

也许 read 的工作正如我最初预期的那样,但也许在更复杂的实现中我会错过一些边缘情况。实验表明,这些文档至少对于预期的行为是令人困惑的。

根据python 文档,我可以看到通过定义writeablereturn Falsewrite应该引发 an OSError(在 Python 3.5 中)。这实际上是不正确的,NotImplementedError当继承RawIOBaseAttributeError继承时它会引发IOBase。此行为不会在 中重复seekable,即调用.tell()会引发正确的错误。为了解决这个问题,我定义write如下:

def write(self, b):
    raise io.UnsupportedOperation("write")
Run Code Online (Sandbox Code Playgroud)

值得注意的是,打开的文件'r'会产生预期的错误类别。

由于除了链接的文档页面之外,没有关于实现这些接口(我发现的)的一般指导,因此我什至不一定会考虑检查该问题。预先存在的测试套件可以解决这个问题。否则,对必要测试或边缘情况的描述将指导我解决这些问题。

我还没有找到这样的指导吗?

iva*_*eev 2

  • Python 文档是唯一包含有关库存实现行为的承诺/保证的官方权威来源 - 没有其他正式发布的内容。如果某件事没有记录在案,那么它就不存在,不应依赖。

    • 源存储库中有io模块的单元测试test_io.py(您也可以选择使用解释器安装测试套件)。请注意具体实施的细节,具体取决于您在下一段中的答案。
  • 有些行为是特定于实现的,并且确实在 Python 实现之间有所不同(例如,在 IronPython 中,sys.maxsize它大得离谱,因为 .NET 中没有这样的机制,并且所有字符串都是 Unicode,即使它实现了 Python 2)。

    • 这里的问题是:您的目标是否符合规范具体实施?答案取决于您希望兼容多少代码(以及编写得有多好(或者更确切地说,写得不好,即不可移植))。
      • 由于我们在这里讨论抽象类,因此除了相关实体中的少量默认/非抽象代码之外,实际上没有“具体实现”。所以差别还是比较小的。
  • 现在,确实存在规范省略或含糊某些关键细节的情况(我个人在 中遇到过至少两种情况ctypes)。这是因为它是作为用户指南而不是实施者指南编写的。

    • 除了遵守规范并在遇到问题时进行修复之外,您在这里无能为力。在模糊的情况下,您可以检查实现,但一定要找出基本原理概念上的目的),以确定什么适合您的情况。毕竟,如果您要替换内部模块,您如何知道其他内部模块依赖了多少未记录的行为?
      • 值得赞扬的是,Python 开发人员认为后一种情况应该极其罕见,因为它们确实遵循松散耦合原则,并努力在模块间交互中遵守规范(有规范的地方)。