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

如何让pytest在shell命令调用失败时正确触发测试失败

问题原因

os.system() 执行shell命令时仅返回命令的退出状态码,不会在命令执行失败(退出码非0)时主动抛出异常。pytest默认只有检测到断言失败、未捕获异常时才会将测试用例标记为失败,当前代码没有处理失败命令的非0退出码,pytest感知不到命令执行出错,因此会误判用例通过。

解决方案

方案1:兼容原有os.system()写法

POSIX系统(Linux/macOS等)下,os.system()返回的是16位整数值:高8位是进程的真实退出码,低8位是杀死进程的信号编号。提取退出码后加断言即可让pytest识别失败状态:

import os
def test_that():
    print("step 1: should work")
    ret = os.system("echo hello")
    assert ret >> 8 == 0, "第一个命令执行失败"
    
    print("step 2: should fail")
    ret = os.system("asdf_failing_non_existing_command")
    assert ret >> 8 == 0, "不存在的命令执行失败"

注意:Windows系统下os.system()的返回值直接就是进程退出码,不需要移位操作,如果需要跨平台运行,更推荐使用下面的subprocess方案。

方案2:使用subprocess标准库(官方推荐,跨平台兼容)

Python官方已明确建议使用subprocess模块替代老旧的os.system()执行shell命令,模块内置了退出码自动校验能力,不需要手动解析返回值,跨平台表现一致。
只要给subprocess.run()传入check=True参数,命令执行失败(退出码非0)时就会自动抛出CalledProcessError异常,pytest捕获到未处理的异常后会直接将用例标记为失败:

import subprocess
def test_that():
    print("step 1: should work")
    # shell=True表示通过系统shell解析命令,和os.system行为一致
    subprocess.run("echo hello", shell=True, check=True)
    
    print("step 2: should fail")
    # 命令不存在,退出码非0,自动抛异常触发用例失败
    subprocess.run("asdf_failing_non_existing_command", shell=True, check=True)
  • 如果不需要shell解析命令语法,建议将命令拆成参数列表传入,去掉shell=True,可以避免shell注入风险:
    subprocess.run(["echo", "hello"], check=True)
    
  • 如果需要捕获命令的标准输出、标准错误内容,可以加上capture_output=True、text=True参数:
    result = subprocess.run(
        ["echo", "hello"],
        check=True,
        capture_output=True,
        text=True
    )
    print(result.stdout)  # 读取命令输出的hello字符串
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 15:48:14