TDD:在实现另一个 (public) 方法之前无法测试一个方法的行为,反之亦然

TDD: Cant Test One Method's behaviour until another (public) method is implemented, and vice versa

我同意这样的观点,即在测试时,我们应该使用 public API 来确保我们的测试不脆弱。 IE。不要测试实现,测试行为。

想象一下我的 public 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.

如果我使用 public API,我无法测试 reserve_resource 的行为,直到 retrieve_reserved_resource 已实施。而且我无法测试 retrieve_reserved_resource 是否具有正确的行为,直到 reserve_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