TDD:无法测试一种方法的行为,直到实现另一种公共方法为止,反之亦然

问题描述

我同意这样的观点,即在进行测试时,我们应该使用公共API来确保我们的测试不易碎。即。不要测试实现,请测试行为。

想象一下我的公共API具有两个方法功能的情况。一种是用于更新内部私有状态的命令方法。另一个查询方法,它从此私有状态检索信息。我不想公开私有字段只是为了测试。

挑战在于,当遵循TDD方法时,如何在确认一个行为要求另一个行为时开始编写测试。

让我们想象一个这样的场景:

class Manager:

    def Manager():
        _reserved_resources = []

    def reserve_resource(id):
    # Creates a new resource and reserves if none exist in the pool,or reserves an existing one. Does not return anything.

    def retrieve_reserved_resource(id):
    # Returns a reserved resource,or returns None if not prevIoUsly reserved.

如果我使用公共API,则在实施 retrieve_reserved_resource 之前,我无法测试 reserve_resource 的行为。在实施 reserve_resource 之前,我无法测试 retrieve_reserved_resource 的行为是否正确。

如果我的第一个测试是:

def test_reserve_resource_when_no_resources_exists_creates_a_new_resource()

当尚未实现 retrieve_reserved_resource 时,如何确认此行为。

我是否只是像执行了 retrieve_reserved_resource 一样编写测试,这样,当测试变为绿色时,我将对这两种方法都有基本的实现?

这是TDD特有的。也可以理解这是一个人为的示例,但希望它能阐明问题。从根本上讲,这是鸡和蛋的情况,其中命令方法查询方法都需要彼此确认其行为。那么从哪里开始呢?

解决方法

我的启发是“先读后写”-如果您无法衡量被测代码的行为,则不能“驱动”任何设计或就此而论的任何实现。

因此,第一个测试都是“我在最简单的情况下应该测量什么”的变体?

m = Manager()
assert m.retrieve_reserved_resource(12345) is None

然后,当我们对这些测试感到满意时,我们继续测量在稍微复杂一些的情况下会发生什么。

m = Manager()
m.reserve_resource(12345)
assert m.retrieve_reserved_resource(12345) is not None