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

Python行数统计程序运行正常但PyTest测试失败,如何排查?

问题原因及解决方法:PyTest测试is_input_valid函数始终触发参数数量错误

问题根源

你的is_input_valid函数设计时预期接收列表类型的参数(对应命令行启动时的sys.argv,格式为[脚本名, 目标文件名]),但测试用例中传入的是字符串(比如"filename foo.bar")。

当传入字符串时,len(cl_arg)计算的是字符串的字符长度,而非命令行参数的个数。例如"filename foo.bar"的长度远大于2,所以函数直接进入最后的else分支,触发"Too few or many command-line arguments"的异常。

另外,单个with pytest.raises块里放多个函数调用的写法有问题:第一个调用触发异常后,后续代码不会执行,导致后面的断言实际没跑。

解决方法

1. 修改测试用例,传入正确格式的列表参数

把测试中传给is_input_valid的字符串改成列表,模拟sys.argv的结构(第一个元素是脚本名,第二个是目标文件名),同时拆分多个断言到独立的测试块或使用参数化:

from lines import is_input_valid, count_loc
import pytest

@pytest.mark.parametrize("args", [
    ["filename", "foo.bar", "lang.py"],  # 超过2个参数
    ["filename"]  # 不足2个参数
])
def test_input(args):
    with pytest.raises(SystemExit, match="Too few or many command-line arguments"):
        is_input_valid(args)

@pytest.mark.parametrize("args", [
    ["filename", "foo.bar"],
    ["filename", "file.txt"]
])
def test_file_name(args):
    with pytest.raises(SystemExit, match="File is not a python(.py) file"):
        is_input_valid(args)

def test_file_exists():
    with pytest.raises(SystemExit) as e:
        is_input_valid(["filename", "abdcgr.py"])
    assert str(e.value) == "File does not exist"

def test_count_loc():
    assert count_loc("fuel.py") == 20

2. (可选)优化原函数的参数校验逻辑

可以给is_input_valid函数加一层参数类型校验,避免非列表参数传入时出现混淆:

def is_input_valid(cl_arg)->str:
    # 新增:校验参数类型是否为列表
    if not isinstance(cl_arg, list):
        sys.exit("Invalid argument format")
    
    if len(cl_arg) == 2:
        if cl_arg[1].endswith('.py'):  # 用endswith比切片更健壮,支持.py结尾的长文件名
            if os.path.isfile(cl_arg[1]):
                filename = cl_arg[1]
            else:
                sys.exit("File does not exist")
        else:
            sys.exit("File is not a python(.py) file")
    else:
        sys.exit("Too few or many command-line arguments")
    return filename

另外,原count_loc函数中row[0].lstrip()可能会引发索引错误(当行是空字符串时row[0]会报错),可以优化判断逻辑:

def count_loc(filename:str)->int:
    counter = 0
    with open(filename) as file:
        for row in file:
            stripped_row = row.strip()
            # 跳过空行和注释行
            if stripped_row and not stripped_row.startswith('#'):
                counter += 1
    return counter

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 09:00:40