第十六章:开发工具-doctest:通过文档完成测试-处理不可预测的输出

16.2.2 处理不可预测的输出
还有一些情况可能无法预测准确的输出,不过仍可以测试。例如,每次运行测试时本地日期和时间值以及对象ID会改变,浮点值表示中使用的默认精度取决于编译器选项,另外容器对象(如字典)的串表示可能是不确定的。尽管这些条件可能无法控制,但是确实有一些技术可以处理。
例如,在CPython中,对象标识符是基于保存这个对象的数据结构的内存地址。

class MyClass:
    pass

def unpredictable(obj):
    """Returns a new list containing obj.

    >>> unpredictable(MyClass())
    [<doctest_unpredictable.MyClass object at 0x10055a2d0>]
    """

    return [obj]

每次程序运行时,这些ID值都会改变,因为这些值会被加载到内存的不同部分。
在这里插入图片描述
测试的值可能会以不可预测的方式改变时,如果具体值对于测试结果并不重要,则可以使用ELLIPSIS选项告诉doctest忽略验证值的某些部分。

class MyClass:
    pass



def unpredictable(obj):
    """Return a new list containing obj.
    >>> unpredictable(MyClass()) #doctest: +ELLIPSIS
    [<doctest_ellopsis.MyClass object at 0x...>]
    """

    return [obj]

unpredictable()调用后面的#doctest: +ELLIPSIS注释告诉doctest打开这个测试的ELLIPSIS选项。…将替换对象ID中的内存地址,这样就会忽略期望值中的这一部分。时间输出将成功匹配,并且通过测试。
在这里插入图片描述
有些情况下,不能忽略不可预测的值,因为这会让测试不完备或不准确。例如,处理一些数据类型时,如果其数据的串表示不一致,那么简单的测试很快会变得越来越复杂。举例来说,字典的串形式可能会根据增加键的顺序不同而改变。

keys = ['a','aa','aaa']

print('dict:',{k:len(k) for k in keys})
print('set :',set(keys))

由于散列随机化和键冲突,每次运行这个脚本时,字典的内部键列表的顺序都会有所不同。集合(set)会使用相同的散列算法,并提供相同的行为。
在这里插入图片描述
要处理这些潜在的差异,最好的方法是创建测试来生成不太可能改变的值。对于字典和集合,这可能意味着需要分布查找特定的键,并生成数据结构内容的一个有序列表,或者与一个字面值比较相等性而不依赖于串表示。

import collections


def group_by_length(words):
    """Returns a dictionary grouping words into sets by length.

    >>> grouped = group_by_length(['python','module','of',
    ... 'the','week'])
    >>> grouped == {2:set(['of']),
    ...             3:set(['the']),
    ...             4:set(['week']),
    ...             6:set(['python','module']),
    ...             }
    True

    """
    d = collections.defaultdict(set)
    for word in words:
        d[len(word)].add(word)
    return d

以上代码中的这个例子实际上会被解释为两个单独的测试,第一个没有任何控制台输出,第二个则会得到比较操作的布尔结果。
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值