You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

遵循TDD小步迭代原则,如何开发API响应解析函数?

遵循TDD小步迭代优化API响应解析函数

问题背景

刚读完Kent Beck的《Test Driven Development: By Example》,正在项目里实践TDD。需求是从如下JSON格式的API响应中提取最近的事件:

[
 {"1789484079": "event1", "1531059415": "event2"},
 {},
 {},
 {"1234256612": "event3"}
]

数组里的每个对象可能包含多个时间戳键,也可能为空。规则是:给定一个时间戳,返回小于等于该时间戳的最近时间戳对应的事件,比如:

  • 给定1889484079,返回"event1"
  • 给定1689484079,返回"event2"

当前测试与实现困境

按照TDD步骤,我先写了测试和返回常量的简易实现:

def parse_response(response, timestamp):
    return "event1"


def test_api_response_parsing_returns_correct_events():
    response = [{1789484079: "event1", 1531059415: "event2"}]
    timestamp = 1889484079
    assert parse_response(response, timestamp) == "event1"

接着更新测试让它失败(添加第二个断言):

def test_api_response_parsing_returns_correct_events():
    response = [{1789484079: "event1", 1531059415: "event2"}]
    timestamp = 1889484079
    assert parse_response(response, timestamp) == "event1"
    timestamp = 1689484079
    assert parse_response(response, timestamp) == "event2"

然后写了硬编码的实现让测试通过,但存在明显重复:

def parse_response(response, timestamp):
    if timestamp == 1889484079:
        return "event1"
    else:
        return "event2"

我想改成遍历响应、按规则检查时间戳的实现,但担心步子跨太大不符合小步迭代原则,想知道遵循TDD该怎么推进。

小步迭代优化步骤

第一步:从硬编码转向依赖输入数据

先不直接做全量遍历,先把硬编码的时间戳和事件名替换成从测试传入的response中读取。修改实现,让它能从第一个非空对象里筛选符合条件的时间戳:

def parse_response(response, timestamp):
    # 先处理测试中的第一个非空对象
    event_dict = response[0]
    # 把字符串时间戳转成整数
    timestamps = [int(ts) for ts in event_dict.keys()]
    # 筛选出小于等于给定时间戳的所有值
    valid_timestamps = [ts for ts in timestamps if ts <= timestamp]
    # 取最近(最大)的时间戳
    closest_ts = max(valid_timestamps)
    return event_dict[str(closest_ts)]

这时候跑测试,两个断言都会通过,同时摆脱了硬编码的具体值,开始依赖输入数据。

第二步:添加空对象场景的测试并优化实现

现在测试里只有一个非空对象,接下来覆盖响应包含空对象的场景。新增测试:

def test_api_response_with_empty_objects():
    response = [{}, {1789484079: "event1"}, {}]
    timestamp = 1889484079
    assert parse_response(response, timestamp) == "event1"

这个测试会失败,因为当前实现只取response[0](是空对象)。此时修改实现,遍历所有响应对象,收集非空对象的时间戳:

def parse_response(response, timestamp):
    all_ts = []
    event_map = {}
    # 遍历所有响应对象,跳过空对象
    for obj in response:
        if not obj:
            continue
        # 合并所有时间戳和对应事件
        for ts_str, event in obj.items():
            ts = int(ts_str)
            all_ts.append(ts)
            event_map[ts] = event
    # 筛选有效时间戳并取最近的
    valid_ts = [ts for ts in all_ts if ts <= timestamp]
    closest_ts = max(valid_ts)
    return event_map[closest_ts]

现在这个新测试和原有测试都能通过,实现也覆盖了空对象场景。

第三步:添加边界场景测试并完善逻辑

比如测试给定时间戳早于所有事件的情况,先写测试(假设需求是返回最早的事件):

def test_timestamp_earlier_than_all_events():
    response = [{1789484079: "event1", 1531059415: "event2"}]
    timestamp = 1000000000
    assert parse_response(response, timestamp) == "event2"

如果当前实现逻辑正确,这个测试会直接通过;如果有问题,再针对性调整实现。

核心TDD原则落地

Kent Beck的小步迭代核心是红-绿-重构循环:

  1. 红:编写一个会失败的测试(覆盖新场景)
  2. 绿:写最少的代码让测试通过(哪怕是临时方案)
  3. 重构:在测试全过的前提下,优化代码消除重复、提升可读性

你之前的硬编码是绿阶段的合理选择,后续重构要拆成小步:先从依赖硬编码转向输入数据,再逐步覆盖空对象、边界值等场景,每一步都保证测试通过,就不会出现步子过大的问题。

内容的提问来源于stack exchange,提问作者hardhypochondria

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 14:30:00