怎么给老代码补单元测试
老函数依赖全局配置和当前时间,根本没法单独跑,想补单测却无从下手,改一点就怕连累别处。
有人这样说「这破函数依赖全局配置和当前时间,想测它比登天还难,改一点就怕炸锅。」
能替你选的都选好了。不想动,直接点下面「交给 AI 办」,点一下就开始做;想改,就点一下要的那个。
已替你选好想改就点一下
只有你知道的不填就先空着,成品里留【待填】
还能补充
还想怎么改可以不选
高级选项一般不用动 · 这件事通常 1 分钟左右做好
示例成品全文按上面这组示例选项真跑出来的
先别改原函数。用 pytest 的 monkeypatch 把“全局配置”和“当前时间”临时换掉,就能测,不用动生产代码,零改动风险。
假设代码在 user_status.py:
from datetime import datetime
def get_user_status():
config = get_global_config()
now = datetime.now()
if now.hour < 9:
return 'off'
return config.get('status', 'on')测试文件 test_user_status.py:
from types import SimpleNamespace
import user_status # 换成你实际文件名
def _冻结时间(monkeypatch, hour):
# 造一个假的 datetime,让 datetime.now() 返回指定的 hour
fake_now = SimpleNamespace(hour=hour)
fake_datetime = SimpleNamespace(now=lambda: fake_now)
monkeypatch.setattr(user_status, "datetime", fake_datetime)
def test_9点前直接off(monkeypatch):
monkeypatch.setattr(user_status, "get_global_config", lambda: {"status": "on"})
_冻结时间(monkeypatch, 8)
assert user_status.get_user_status() == "off"
def test_9点整走配置且有值(monkeypatch):
monkeypatch.setattr(user_status, "get_global_config", lambda: {"status": "busy"})
_冻结时间(monkeypatch, 9)
assert user_status.get_user_status() == "busy"
def test_9点后配置没有status用默认on(monkeypatch):
monkeypatch.setattr(user_status, "get_global_config", lambda: {})
_冻结时间(monkeypatch, 10)
assert user_status.get_user_status() == "on"运行:
pip install pytest
pytest test_user_status.py -v这 3 个测试先保核心路径:
- 9 点前:不管配置,直接
off - 9 点整及以后:配置里有
status就用配置的值 - 9 点后:配置里没有
status,用默认on
注意我故意测了 9 点整,因为 hour < 9 不包含 9,这个边界要固定下来。
如果你以后想少写这种 mock,可以再做一个向后兼容的小改动:
def get_user_status(config=None, now=None):
if config is None:
config = get_global_config()
if now is None:
now = datetime.now()
if now.hour < 9:
return 'off'
return config.get('status', 'on')这个改动对老调用 get_user_status() 完全没影响,只是给测试留了口子。测试可以直接传参:
def test_9点前直接off():
assert get_user_status(
config={"status": "on"},
now=SimpleNamespace(hour=8)
) == "off"但如果你现在最怕改炸锅,就先用上面那套 monkeypatch 测试,不用改原函数。