输入校验写了assert,为什么换个启动参数就失效了?

举报
霍格沃兹测试开发 发表于 2026/09/20 16:50:47 2026/09/20
【摘要】 有一段Python代码,用来检查购买数量必须在1到99之间。# bad_quantity.py:故意保留问题的教学版本import sysquantity = int(sys.argv[1])assert 1 <= quantity <= 99, "数量超出范围"print(f"接受数量:{quantity}")运行python bad_quantity.py -1,程序报错。看起来,负数已...

有一段Python代码,用来检查购买数量必须在1到99之间。

# bad_quantity.py:故意保留问题的教学版本
import sys

quantity = int(sys.argv[1])
assert 1 <= quantity <= 99, "数量超出范围"
print(f"接受数量:{quantity}")

运行python bad_quantity.py -1,程序报错。看起来,负数已经被拦住了。

再试一次:python -O bad_quantity.py -1。

它会走到打印语句,输出“接受数量:-1”。没有修改业务代码,只换了Python启动方式,校验就消失了。

这道题很适合准备测试开发面试的同学。它考察的不只是assert语法,还包括:你是否知道测试断言、调试断言和业务输入校验分别承担什么责任。



assert为什么会被跳过

Python的assert与调试模式相关。请求优化运行时,编译器会省略相应的断言代码。

因此,一条“无论部署方式如何都必须生效”的业务规则,不适合只靠assert守住。数量范围、权限条件、价格合法性等规则,应使用明确的运行时检查和异常处理。

还有一个更隐蔽的写法:把必须发生的业务动作放进assert表达式。断言被省略以后,表达式本身也不会执行。测试不能只检查条件真假,还要看代码是否把副作用藏进了断言。

用明确校验,把规则从启动参数里拿回来

下面把数量检查写成一个独立函数。为了让输入规则更清楚,约定只接受严格整数,不接受布尔值和数字字符串:

def validate_quantity(value):
    if type(value) is not int:
        raise ValueError("数量必须是整数")
    if not 1 <= value <= 99:
        raise ValueError("数量必须在1到99之间")
    return value

如果接口允许用户输入字符串,可以在独立的解析层按明确规则转换,再交给校验函数。不要靠某一次自动转换,把“1.0”“1e2”“True”都含糊地塞进业务层。

修复后的程序也应分别在普通启动和优化启动下运行。输入合法时结果一致,输入非法时都按约定拒绝。

测试别只写一个-1,再补几个刚好会混淆的样本

import pytest

@pytest.mark.parametrize("value", [1, 50, 99])
def test_valid_quantity(value):
    assert validate_quantity(value) == value

@pytest.mark.parametrize("value", [0, -1, 100, True, "1", None])
def test_invalid_quantity(value):
    with pytest.raises(ValueError):
        validate_quantity(value)

把函数与测试放在同一个文件中,安装pytest后即可运行。还应单独保留前面两种解释器启动方式的实验,它验证的是部署方式对原始程序的影响。

这里用pytest的assert写测试预期,并不意味着业务函数也应该用assert做输入门禁。pytest会对符合条件的测试模块进行断言重写,这与普通业务模块的assert处理不同。不要把前面的演示推广成“pytest在-O下一定完全不验证”,两者要分别检查。



面试官继续追问,错误应该怎样回到用户面前

抛出ValueError,只解决了函数层面的拒绝。真实接口还要将它映射成约定的客户端错误,返回可理解的信息,并保证没有在校验失败之前创建订单或扣减库存。

这就能再增加一条更有价值的断言:非法输入被拒绝以后,数据库和相关业务状态没有发生不该发生的变化。只看错误码,仍然可能漏掉“先操作、后发现不合法”的顺序问题。

如果AI生成了一段看起来很简洁的校验代码,可以让它同时列出规则执行位置、类型约定、异常映射和副作用边界。随后自己构造一个启动方式变化、一个边界值和一个类型混淆样本。

这比要求模型“再多生成十条测试”更容易得到可核验的结果。

面试中可以这样解释自己的选择:

“业务输入校验要在运行时明确执行,我会用条件判断和异常表达拒绝。测试里用断言描述预期结果,同时验证错误输入没有产生副作用。涉及Python启动参数时,我会检查实际部署方式,不把一次本地通过当成所有环境都成立。”

基础语法题也能回答出工程意识。关键是继续往下问一步:这行代码换到真实运行环境里,它守住的规则还在不在?

关于我们

本文部分内容参考了霍格沃兹测试开发学社整理的相关技术资料,主要涉及软件测试、自动化测试、测试开发及 AI 测试等内容,侧重测试实践、工具应用与工程经验整理。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。